Update of /project/cl-smtp/cvsroot/cl-smtp In directory cl-net:/tmp/cvs-serv16391
Modified Files: CHANGELOG cl-smtp.lisp Log Message: Fixed encoding errors in header strings
--- /project/cl-smtp/cvsroot/cl-smtp/CHANGELOG 2010/04/20 10:19:21 1.15 +++ /project/cl-smtp/cvsroot/cl-smtp/CHANGELOG 2010/04/22 10:51:34 1.16 @@ -1,3 +1,9 @@ +Version 20100422.1 +2010.04.22 +Fixed encoding errors in header strings, +new function q-encode-str to encode strings in header +Change cl-smtp.lisp, CHANGELOG + Version 20100420.1 2010.04.20 Fixed error when send more than 1 attachment, --- /project/cl-smtp/cvsroot/cl-smtp/cl-smtp.lisp 2008/04/12 19:40:36 1.13 +++ /project/cl-smtp/cvsroot/cl-smtp/cl-smtp.lisp 2010/04/22 10:51:34 1.14 @@ -62,6 +62,28 @@ #+allegro (excl:string-to-base64-string str) #-allegro (cl-base64:string-to-base64-string str))
+(defun q-encode-str (str &key (external-format + (flex:make-external-format :iso-8859-15))) + (let ((line-has-non-ascii nil)) + (with-output-to-string (s) + (loop for c across str do + (cond + ((< 127 (char-code c)) + (unless line-has-non-ascii + (format s "=?~A?Q?" (flex:external-format-name external-format)) + (setf line-has-non-ascii t)) + (loop for byte across (flex:string-to-octets + (make-string 1 :initial-element c) + :external-format external-format) + do (format s "=~2,'0X" byte))) + (t + (when line-has-non-ascii + (format s "?=") + (setf line-has-non-ascii nil)) + (format s "~C" c)))) + (when line-has-non-ascii + (format s "?="))))) + (define-condition smtp-error (error) ())
@@ -104,7 +126,13 @@ lines))
(defun do-with-smtp-mail (host from to thunk &key port authentication ssl local-hostname) - (usocket:with-client-socket (socket stream host port) + (usocket:with-client-socket (socket stream host port + :element-type '(unsigned-byte 8)) + (setf stream (flexi-streams:make-flexi-stream + stream + :external-format + (flexi-streams:make-external-format + :latin-1 :eol-style :lf))) (let ((stream (smtp-handshake stream :authentication authentication :ssl ssl @@ -155,6 +183,7 @@ :authentication authentication :ssl ssl :local-hostname local-hostname) + (setf (in-header stream) nil) (let* ((boundary (make-random-boundary)) (html-boundary (if (and attachments html-message) (make-random-boundary) @@ -288,9 +317,9 @@ (setf stream #+allegro (socket:make-ssl-client-stream stream) #-allegro - (let ((s stream)) + (let ((s (flexi-streams:flexi-stream-stream stream))) (cl+ssl:make-ssl-client-stream - (cl+ssl:stream-fd stream) + (cl+ssl:stream-fd s) :close-callback (lambda () (close s))))) #-allegro (setf stream (flexi-streams:make-flexi-stream @@ -360,14 +389,16 @@ server connected to on STREAM. The server is expected to have previously accepted the DATA SMTP command." (write-to-smtp stream (format nil "Date: ~A" (get-email-date-string))) - (write-to-smtp stream (format nil "From: ~@[~A <~]~A~@[>~]" - display-name from display-name)) + (if display-name + (write-to-smtp stream (format nil "From: ~A <~A>" + (q-encode-str display-name) from)) + (write-to-smtp stream (format nil "From: ~A" from))) (write-to-smtp stream (format nil "To: ~{ ~a~^,~}" to)) (when cc (write-to-smtp stream (format nil "Cc: ~{ ~a~^,~}" cc))) - (write-to-smtp stream (format nil "Subject: ~A" subject)) + (write-to-smtp stream (format nil "Subject: ~A" (q-encode-str subject))) (write-to-smtp stream (format nil "X-Mailer: cl-smtp ~A" - *x-mailer*)) + (q-encode-str *x-mailer*))) (when reply-to (write-to-smtp stream (format nil "Reply-To: ~A" reply-to))) (when (and extra-headers @@ -388,7 +419,7 @@
(defun write-to-smtp (stream command) (print-debug (format nil "to server: ~A" command)) - (write-string command stream) + (write-sequence command stream) (write-char #\Return stream) (write-char #\NewLine stream) (force-output stream))