From ddcab952f718b57925d800f4a7edd67e65a854ce Mon Sep 17 00:00:00 2001 From: Eli Barzilay Date: Tue, 20 Dec 2011 16:13:13 -0500 Subject: [PATCH] Quote sender, subject, and recipients strings if needed. There might be existing uses of `net/sendmail' that did this quoting since this code didn't do so. Such uses would continue to work fine, since quoted strings would already be plain ASCII, so a second quoting would leave it as is. Note that the quoted strings are also used as command line arguments. It seems that sendmail deals with these all fine when they appear as command line arguments. This means that any valid email address format can be used, not just "raw" emails. If there are some sendmails that don't do this, then it would be better to add a `-t' flag to let sendmail parse the text in the message. One caveat (not a new one): since they're passed as is, it is possible to use two emails in a single string, as in "a@b.com, c@d.com". This could lead to obvious problems if someone uses "Bar, Foo " instead of "\"Bar, Foo\" ". (Using a `-t' to parse the content won't help with that...) The only way to avoid this would be to parse the emails and quote the name part if needed. But that's a much hairier piece of code. --- collects/net/scribblings/sendmail.scrbl | 13 ++++++++----- collects/net/sendmail.rkt | 13 +++++++++---- 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/collects/net/scribblings/sendmail.scrbl b/collects/net/scribblings/sendmail.scrbl index 927612625a..1b73f31d8b 100644 --- a/collects/net/scribblings/sendmail.scrbl +++ b/collects/net/scribblings/sendmail.scrbl @@ -23,11 +23,14 @@ corresponding SMTP specifications, except as noted otherwise. output-port?]{ The first argument is the header for the sender, the second is the -subject line, the third a list of ``To:'' recipients, the fourth a -list of ``CC:'' recipients, and the fifth a list of ``BCC:'' -recipients. Additional arguments argument supply other mail headers, -which must be provided as lines (not terminated by a linefeed or -carriage return) to include verbatim in the header. +subject line, the third a list of ``To:'' recipients, the fourth a list +of ``CC:'' recipients, and the fifth a list of ``BCC:'' recipients. All +of these are quoted if they contain non-ASCII characters. +@margin-note{Note that passing already-quoted strings would be fine, + since then there are no non-ASCII characters.} +Additional arguments argument supply other mail headers, which must be +provided as lines (not terminated by a linefeed or carriage return) to +include verbatim in the header. The return value is an output port into which the client must write the message. Clients are urged to use @racket[close-output-port] on diff --git a/collects/net/sendmail.rkt b/collects/net/sendmail.rkt index 1c655d8337..0cf3e6e02f 100644 --- a/collects/net/sendmail.rkt +++ b/collects/net/sendmail.rkt @@ -2,6 +2,8 @@ (provide send-mail-message/port send-mail-message) +(require net/unihead) + (define sendmail-search-path '("/usr/sbin" "/sbin" "/usr/local/sbin" "/usr/lib")) @@ -21,7 +23,10 @@ ;; Main implementation, returns a port (define (send-mail-core who sender subject TOs CCs BCCs headers) - (define all-recipients (append TOs CCs BCCs)) + (define qTOs (map encode-for-header TOs)) + (define qCCs (map encode-for-header CCs)) + (define qBCCs (map encode-for-header BCCs)) + (define all-recipients (append qTOs qCCs qBCCs)) (when (null? all-recipients) (error who "no mail recipients were specified")) (define-values [p pout pin perr] @@ -31,9 +36,9 @@ (close-input-port perr) (port-count-lines! pin) (fprintf pin "X-Mailer: Racket (racket-lang.org)\n") - (when sender (fprintf pin "From: ~a\n" sender)) + (when sender (fprintf pin "From: ~a\n" (encode-for-header sender))) (for ([header (in-list '("To" "CC"))] - [recipients (in-list (list TOs CCs))] + [recipients (in-list (list qTOs qCCs))] #:unless (null? recipients)) (fprintf pin "~a: ~a" header (car recipients)) (for ([recipient (in-list (cdr recipients))]) @@ -43,7 +48,7 @@ "\n " " ") recipient)) (newline pin)) - (fprintf pin "Subject: ~a\n" subject) + (fprintf pin "Subject: ~a\n" (encode-for-header subject)) (for ([h (in-list headers)]) (fprintf pin "~a\n" h)) (newline pin) pin)