This is quite the long thread, but I think no one has yet added
generation of the Message-Id in any of the versions of ns_sendmail
above? Hm, at first glance, looks like the AOLserver 4.0 beta
sendmail.tcl has some slight improvements over 3.3, but still doesn't
do that. Well, I hacked my ns_sendmail to do some simply Message-Id
generation a year or two ago to do that. It wasn't hard, but FYI,
here's the code:
My _ns_smtp_recv
, _ns_smtp_send
, and
ns_sendmail
procs are unchanged from the versions shipped
with 3.3+ad13. I just added this extra top level nsv command, and
changed _ns_sendmail
a bit. Note there are only a few
lines of changed code here! (But I find trying to read diffs in
BBoard annoying, so I didn't do that.) After the
if { ! $message_id_already_done_p }
line it's all stock, except for some comments:
if { ![nsv_exists ns_sendmail sequence] } {
nsv_set ns_sendmail sequence 0
}
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)
set message_id_already_done_p 0
if ![string match "" $extraheaders] {
set size [ns_set size $extraheaders]
for {set i 0} {$i < $size} {incr i} {
set key [ns_set key $extraheaders $i]
# This is rather hack-ish...
if { [string compare $key {Message-ID}] == 0 } {
set message_id_already_done_p 1
}
append msg "\n${key}: [ns_set value $extraheaders $i]"
}
}
# Insert a unique "Message-ID:" header, but only if the caller did
# not manually include a Message-ID header:
#
# An application could use the Message-ID header for
# e.g. threading support, but we're not trying to do anything
# fancy like that here. We just want to include a globally-unique
# ID. Why? Well, for one thing, since most email user agents
# include a Message-ID, but most SPAM software does not, some
# anti-SPAM software filters out email which does not have a
# Message-ID...
#
# Note: The $message_id below is guaranteed to be globally unique
# if and only if *ALL* of the following conditions are true:
#
# 1. Your unix box's hostname (which is what [ns_info hostname]
# returns) is set to a fully-qualified name like
# "philip.greenspun.com", NOT just a local hostname like
# "philip".
# 2. Your fully-qualified hostname is in fact globally-unique.
# AKA, you didn't do something foolish like set up two separate
# machines that both think their hostname is
# "philip.greenspun.com".
# 3. On your unix host, you have only ONE AOLserver running with
# the server name returned by [ns_info server].
# 4. Since [ns_info boottime] is in seconds, you never restart
# your AOLserver multiple times in < 1 second, jump your system
# clock backwards in time, or etc.
# 5. Once the "ns_sendmail sequence" nsv variable is set, you
# never manually fool with it to re-set it to a previous value.
# While the server is running, this value must always increase,
# never decrease.
#
# --atp@piskorski.com, 2001/10/11 11:51 EDT
if { ! $message_id_already_done_p } {
set message_id "[nsv_incr ns_sendmail sequence].[ns_info boottime].[ns_info server]@[ns_info hostname]"
append msg "\nMessage-ID: $message_id"
}
## Blank line between headers and body
append msg "\n\n$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]
## Perform the SMTP conversation
if { [catch {
_ns_smtp_recv $rfp 220 $timeout
_ns_smtp_send $wfp "HELO AOLserver [ns_info hostname]" $timeout
_ns_smtp_recv $rfp 250 $timeout
_ns_smtp_send $wfp "MAIL FROM:<$from>" $timeout
_ns_smtp_recv $rfp 250 $timeout
# TODO: Above, should optionally take a "Return-Path" to use
# as the envelope sender address (aka, envelope return path)
# rather than always using $from. This would allow using
# VERPs, for instance, as discussed at:
# "http://cr.yp.to/proto/verp.txt"
# See also discussion at:
# "http://www.arsdigita.com/bboard/q-and-a-fetch-msg?msg%5fid=000awU"
# --atp@piskorski.com, 2001/10/11 10:25 EDT
## 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
}
_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
}