Forum OpenACS Development: Re: html in emails.

Collapse
6: Re: html in emails. (response to 1)
Posted by Richard Hamilton on
This evening I have been trying to get my openacs-4-6 to send email password reminders as html and was meeting with mysterious problems.

Having dissected the file line by line it became obvious that the problem was an unwanted newline between the subject line and the "Content-Type:" declaration.

So with tremendous courage I embarked on a search of ns_sendmail.tcl - emboldened by Tilman's patches that I applied yesterday! - And guess what I found.......

There is an extra '\n' included before the body which confuses MS Outlook.

So if anyone wants to send html emails from the ACS and doesn't mind hacking ns_sendmail..................
Modified version posted below - includes Tilman's patches.
Mime header and html body need to go into email-password-2.tcl

proc _ns_sendmail {smtp smtpport timeout tolist bcclist \
	from subject body extraheaders} {
    
    ## Put the tolist in the headers
    set rfcto [join $tolist ", "]
    
    ## Build headers
    set msg "To: $rfcto\nFrom: $from\nSubject: $subject\nDate: [ns_httptime [ns_time]]"

    ## Insert extra headers, if any (not for BCC)
    if ![string match "" $extraheaders] {
	set size [ns_set size $extraheaders]
	for {set i 0} {$i < $size} {incr i} {
	    append msg "\n[ns_set key $extraheaders $i]: [ns_set value $extraheaders $i]"
	}
    }

    ## Blank line between headers and body

    append msg "$body\n"

    ## Terminate body with a solitary period
    foreach line [split $msg "\n"] {
	if [string match . $line] {
	    append data .
	}
	append data $line
	append data "\r\n"
    }
    append data .

    ## Open the connection
    set sock [ns_sockopen $smtp $smtpport]
    set rfp [lindex $sock 0]
    set wfp [lindex $sock 1]

    ## Strip "from" email address
    regexp {.*<(.*)>} $from ig from

    ## Perform the SMTP conversation
    if { [catch {
	_ns_smtp_recv $rfp 220 $timeout
	_ns_smtp_send $wfp "HELO [ns_info hostname]" $timeout
	_ns_smtp_recv $rfp 250 $timeout
	_ns_smtp_send $wfp "MAIL FROM:<$from>" $timeout
	_ns_smtp_recv $rfp 250 $timeout

	## Loop through To list via multiple RCPT TO lines
	foreach toto $tolist {
	    _ns_smtp_send $wfp "RCPT TO:<$toto>" $timeout
	    _ns_smtp_recv $rfp 250 $timeout
	}

	## Loop through BCC list via multiple RCPT TO lines
	## A BCC should never, ever appear in the header.  Ever.  Not even.
	foreach bccto $bcclist {
	    _ns_smtp_send $wfp "RCPT TO:<$bccto>" $timeout
	    _ns_smtp_recv $rfp 250 $timeout
	}

	## Loop through To and BCC list via multiple RCPT TO lines
	## A BCC should never, ever appear in the header.  Ever.  Not even.
	foreach toto [concat $tolist $bcclist] {
	    # Transform "Fritz #fritz@foo.com>" into "fritz@foo.com".
	    regexp {.*<(.*)>} $toto ig toto

	    _ns_smtp_send $wfp "RCPT TO:<$toto>" $timeout
	    _ns_smtp_recv $rfp 250 $timeout
	}

	_ns_smtp_send $wfp DATA $timeout
	_ns_smtp_recv $rfp 354 $timeout
	_ns_smtp_send $wfp $data $timeout
	_ns_smtp_recv $rfp 250 $timeout
	_ns_smtp_send $wfp QUIT $timeout
	_ns_smtp_recv $rfp 221 $timeout
    } errMsg ] } {
	## Error, close and report
	close $rfp
	close $wfp
	return -code error $errMsg
    }

    ## Close the connection
    close $rfp
    close $wfp
}

Regards
Richard
Collapse
7: Re: html in emails. (response to 6)
Posted by Richard Hamilton on
The simple modification above broke the basic default emails for confirming registrations to I added this simple check to ns_sendmail and it seems to be working fine. I have only just started working with tcl so my repertoire of instructions is not good. Perhaps the tcl experts could let me know if this is an efficient way to construct it.
if {[string index $body 0] != "\n"} {
    	set newline "\n"
    } else {
    	set newline ""
    }

    append msg $newline "$body\n"

I was not sure if I had to explicitly tell the interpreter that newline contains null so I thought I had better for safety's sake.
Regards
Richard