Forum OpenACS Development: How do I send HTML email?

Collapse
Posted by Jade Rubick on
Is it possible to send HTML emails using acs-mail-lite, and if so, where is a good example of how this is done. I haven't been able to find any documentation for this, or anything in the forums, although there are a lot of hints out there...
Collapse
Posted by Malte Sussdorff on
look at the mailinglist manager. This package (in contrib) sends out html, multipart, alternative and attachments through acs-mail-lite.

If you want to do the community a great favour, strip out this functionality of mailing list manager and add it to asc-mail-lite while enhancing the documentation in the great style you proved so many times on your site.

Collapse
Posted by Steve Manning on
Malte

How does this compare to using the acs_mail package?

acs_mail is documented here https://openacs.org/doc/acs-mail/openacs-mail.html. I've used it on one occasion and its powerful but quite complex to use.

    - Steve

Collapse
Posted by Samer Abukhait on
I guess an html_p column is to be added to acs_mail_lite_queue

The sweeper code is to become:
db_foreach get_queued_messages {} {
            set eh [util_list_to_ns_set $extra_headers]
	    if {$html_p} {  ns_set put $eh Content-Type text/html }
            if {[catch {ns_sendmail $to_addr $from_addr $subject $body $eh $bcc} errmsg]} {
                ns_log Error "ns_sendmail failed: $errmsg"
            } else {
                db_dml delete_queue_entry {}
            }
        }
Collapse
Posted by Janine Ohmer on
Look at acs-tcl/tcl/html-email-procs.tcl, which contains the handy proc build_mime_message, and bulk-mail/tcl/bulk-mail-procs.tcl for an example of how to use it.  You will have to make one edit to the first file - someone renamed base64.tcl to base64-procs.tcl but didn't change the reference to it.  I will be committing a fix for that soon, along with some other stuff, but the copy you have will be wrong.
Collapse
Posted by Jade Rubick on
I added a section to the docs on how to do HTML based email from acs-mail-lite. It does require the fix that Janine points out here (which is quite an easy fix).

I'm uncovered a bug in acs-mail-lite's rollout support, however, something I introduced (or at least didn't address when I added in rollout support). ns_sendmail doesn't handle the extra_headers the same, so it bombs out when trying to send MIME email when you have rollout support enabled.

Collapse
Posted by Jade Rubick on
Oh, and thank you all! :)
Collapse
Posted by Jade Rubick on
Thanks to Jeff, the documentation is now online:

https://openacs.org/doc/current/tutorial-html-email.html

Collapse
Posted by Jade Rubick on
Any idea why the HTML in my email gets mangled a bit?

The HTML sent in is as follows:

<a href="https://mydomain.com/intranet/project-manager/task-one?task_id=283046">Unable to remove deadline from task</a> (#283046)

What I get in my email (in Mail.app in Mac OS X, viewing source):

The link is returned as:

x-msg://6/3d%22https://mydomain.com/intranet/project-manager/task-one?task_id=3d283046%22

Any idea what's going on here?

Collapse
Posted by Jeff Davis on
well =3d is "=" as quoted printable and %22 is " url encoded so it looks like some sort of mishmash of encodings. You should really look at what's really being sent (put some logging stuff in acs-mail-lite or something, and send it to a unix account and see what ends up in the spool file before an MUA gets hold of it).
Collapse
Posted by Jade Rubick on
Thanks for the hint, Jeff.

Looking at this further....

I send an email with the following code:

    set to_addr myemail@email.com
    set from_addr myemail@email.com
    set subject "Test"
    set message "<a href=\"http://www.safe4all.org\">http://www.safe4all.org</a>"
    set mime_type "text/html"

    # first of all, set up the HTML and text versions of the message

    set message_html [ad_html_text_convert -from $mime_type -to "text/html" -- $body]

    # some mailers chop off the last few characters.
    append message_html "   "

    set message_text [ad_html_text_convert -from $mime_type -to "text/plain" -- $body]

    set message_data [build_mime_message $message_text $message_html]
    
    set extra_headers [ns_set new]
    ns_set put $extra_headers MIME-Version [ns_set get $message_data MIME-Version]
    ns_set put $extra_headers Content-ID   [ns_set get $message_data Content-ID]
    ns_set put $extra_headers Content-Type [ns_set get $message_data Content-Type]
    set message [ns_set get $message_data body]

    foreach to $to_addr {

        acs_mail_lite::send \
            -to_addr  "$to" \
            -from_addr "$from_addr" \
            -subject "$subject" \
            -body "$message" \
            -extraheaders $extra_headers
    }

What I see when I send this to a UNIX mailbox and cat the spool file is:

In the HTML portion of the MIME message:

MIME-Version: 1.0
Content-ID: <3427.1088195999.2@dev2.bread.com>
Content-Type: text/html;
              charset="iso-8859-1"
Content-Transfer-Encoding: quoted-printable

<a href=3D3d=22http://www.safe4all.org=22>http://www.safe4all.org</a>  =20
This seems to look just fine on Microsoft Outlook, but on Apple's Mail.app program, it appears as:
x-msg://46/3d'http://www.safe4all.org'
for some reason.

Any idea why it's not working on the Mac?

Collapse
Posted by Dirk Gomez on
Jade, did you find a fix for this quoting issue?
Collapse
Posted by Jade Rubick on
No I never did fix it. Anyone have any ideas?
Collapse
Posted by Jeff Davis on
I committed a fix for this in html-email-procs. html-email-procs which was in 5.1.1 I think.
Collapse
Posted by Nima Mazloumi on
How can I send attachments? Has someone experience on that? Maybe we could add that to the documentation as well.
Collapse
Posted by Brian Fenton on
Collapse
Posted by Nima Mazloumi on
Hi Brian,
I tested the multipart part and it doesn't work. This call breaks:

set body_id [acs_mail_body_new -header_subject $subject -content_item_id $multipart_id ]

Error:

Database operation "0or1row" failed (exception NSDB, "Query was not a statement returning rows.")

ERROR:  Function acs_mail_body__new("unknown", "unknown", "unknown", "unknown", "unknown", "unknown", "unknown", "unknown", "unknown", "unknown", "unknown", timestamptz, "unknown", "unknown", "unknown") does not exist
    Unable to identify a function that satisfies the given argument types
    You may need to add explicit typecasts

SQL:

select acs_mail_body__new (
  NULL,                -- body_id
  NULL,        -- body_reply_to
  NULL,            -- body_from
  NULL,            -- body_date
  NULL,    -- header_message_id
  NULL,        -- header_reply_to
  'Testemail mit acs-mail',      -- header_subject
  NULL,            -- header_from
  NULL,            -- header_to
  '2009',        -- content_item_id
  'acs_mail_body',        -- object_type
  now(),                -- creation_date
  NULL,        -- creation_user
  NULL,            -- creation_ip
  null                    -- context_id
);

Collapse
Posted by Brian Fenton on
Nima, here's some code I used recently to send an attachment. Let me know how you get on. Brian
set generated_name "test"
set csv_string "contents of csv file"
set csv_file_name "outputfilename.csv"

set file_handle [open $csv_file_name w]
puts $file_handle $csv_string
close $file_handle

set ip_addr [ad_conn peeraddr]
set modifying_user [ad_conn user_id]

set from_addr [db_string some_sql "select email from parties where party_id = :modifying_user"]

# create the multipart message ('multipart/mixed')
set multipart_id [acs_mail_multipart_new -multipart_kind "mixed"]

# create an acs_mail_body (with content_item_id = multipart_id )
set body_id [acs_mail_body_new -header_subject $generated_name -content_item_id $multipart_id ]

# create a new text/plain item
set content_item_id [db_exec_plsql create_text_item {
    begin
        :1 := content_item.new (
               name      => :generated_name, 
               title => :generated_name,
               mime_type => 'text/plain',
               text => :csv_string);
    end;}]    

set sequence_num [acs_mail_multipart_add_content -multipart_id $multipart_id -content_item_id $content_item_id]

db_dml update_multiparts "
      update acs_mail_multipart_parts 
      set mime_disposition='attachment; filename=\"$generated_name\"' 
      where sequence_number=:sequence_num 
      and multipart_id=:multipart_id"

# queue it
set mail_link_id [db_exec_plsql queue_the_mail {
    begin

        :1 := acs_mail_queue_message.new (
                  null,             -- p_mail_link_id
                  :body_id,         -- p_body_id
                  null,             -- p_context_id
                  sysdate,          -- p_creation_date
                  :modifying_user,  -- p_creation_user
                  :ip_addr,         -- p_creation_ip
                  'acs_mail_link'   -- p_object_type
                  );
    end;
    }
    ]      

# send a copy of the mail to the logged in user
set sql_string "
    insert into acs_mail_queue_outgoing
     ( message_id, envelope_from, envelope_to )
    values
     ( :mail_link_id, :from_addr, :to_addr )"

set to_addr $from_addr
if {![empty_string_p $to_addr]} {
  db_dml outgoing_queue $sql_string
} else {
  ns_log Error "To email address  is blank"
}
Collapse
Posted by Nima Mazloumi on
set multipart_id [acs_mail_multipart_new -multipart_kind "mixed"]
set body_id [acs_mail_body_new -header_subject "test" -content_item_id $multipart_id ]

Already breaks on oacs-5-1. postgres installation:

ERROR:  Function acs_mail_body__new("unknown", "unknown", "unknown", "unknown", "unknown", "unknown", "unknown", "unknown", "unknown", "unknown", "unknown", timestamptz, "unknown", "unknown", "unknown") does not exist
    Unable to identify a function that satisfies the given argument types
    You may need to add explicit typecasts

SQL:

select acs_mail_body__new (
  NULL,                -- body_id
  NULL,        -- body_reply_to
  NULL,            -- body_from
  NULL,            -- body_date
  NULL,    -- header_message_id
  NULL,        -- header_reply_to
  'test',      -- header_subject
  NULL,            -- header_from
  NULL,            -- header_to
  '2015',        -- content_item_id
  'acs_mail_body',        -- object_type
  now(),                -- creation_date
  NULL,        -- creation_user
  NULL,            -- creation_ip
  null                    -- context_id
);

Collapse
Posted by Brian Fenton on
Ahh! Postgres! I don't use Postgres, only Oracle. Sorry about that. 😟