Browse code
2006-11-16 Ahmon Dancy <dancy@dancy>
layer authored on 17/11/2006 00:32:07
Showing 3 changed files
Showing 3 changed files
... | ... |
@@ -1,3 +1,17 @@ |
1 |
+2006-11-16 Ahmon Dancy <dancy@dancy> |
|
2 |
+ |
|
3 |
+ bug16495: |
|
4 |
+ |
|
5 |
+ * smtp.cl: send-smtp-1: New external-format keyword arg. |
|
6 |
+ Now processes input in terms of bytes |
|
7 |
+ instead of characters. |
|
8 |
+ |
|
9 |
+ * mime-api.cl: make-mime-part: Default external-format is :utf8 |
|
10 |
+ now. Default encoding changed once again. Now always base64, |
|
11 |
+ except for when :text is supplied and is stringp, in which case |
|
12 |
+ the encoded version of the string is examined to see if 7bit can |
|
13 |
+ be used). |
|
14 |
+ |
|
1 | 15 |
2006-10-18 Ahmon Dancy <dancy@dancy> |
2 | 16 |
|
3 | 17 |
* mime-api.cl: bug16479: Improve default content-transfer-encoding |
... | ... |
@@ -1,18 +1,20 @@ |
1 | 1 |
#+(version= 8 0) |
2 |
-(sys:defpatch "mime" 1 |
|
2 |
+(sys:defpatch "mime" 2 |
|
3 | 3 |
"v0: New module. See documentation.; |
4 |
-v1: Improve default transfer encoding determination." |
|
4 |
+v1: Improve default transfer encoding determination; |
|
5 |
+v2: make-mime-part: Default external-format is :utf8." |
|
5 | 6 |
:type :system |
6 | 7 |
:post-loadable t) |
7 | 8 |
|
8 | 9 |
#+(version= 7 0) |
9 |
-(sys:defpatch "mime" 1 |
|
10 |
+(sys:defpatch "mime" 2 |
|
10 | 11 |
"v0: New module. See documentation.; |
11 |
-v1: Improve default transfer encoding determination." |
|
12 |
+v1: Improve default transfer encoding determination; |
|
13 |
+v2: make-mime-part: Default external-format is :utf8." |
|
12 | 14 |
:type :system |
13 | 15 |
:post-loadable t) |
14 | 16 |
|
15 |
-;; $Id: mime-api.cl,v 1.3 2006/10/18 18:41:57 layer Exp $ |
|
17 |
+;; $Id: mime-api.cl,v 1.4 2006/11/17 00:32:07 layer Exp $ |
|
16 | 18 |
|
17 | 19 |
(defpackage :net.post-office |
18 | 20 |
(:use #:lisp #:excl) |
... | ... |
@@ -100,10 +102,10 @@ v1: Improve default transfer encoding determination." |
100 | 102 |
(defun make-mime-part (&key content-type encoding headers |
101 | 103 |
(attachmentp nil attachmentp-supplied) |
102 | 104 |
name text (start 0) end file |
103 |
- subparts (external-format :default) |
|
105 |
+ subparts (external-format :utf8) |
|
104 | 106 |
parameters charset id description) |
105 | 107 |
(let ((part (make-instance 'mime-part-constructed)) |
106 |
- type subtype multipart textp filepath) |
|
108 |
+ type subtype multipart textp filepath orig-text) |
|
107 | 109 |
|
108 | 110 |
(if* (and text file) |
109 | 111 |
then (error "Only one of :text or :file may be specified")) |
... | ... |
@@ -115,7 +117,8 @@ v1: Improve default transfer encoding determination." |
115 | 117 |
(if* (streamp file) |
116 | 118 |
then (setf filepath (ignore-errors (namestring file))) |
117 | 119 |
else (setf filepath file))) |
118 |
- |
|
120 |
+ |
|
121 |
+ ;; Select default content-type |
|
119 | 122 |
(when (null content-type) |
120 | 123 |
(if* filepath |
121 | 124 |
then (setf content-type (lookup-mime-type filepath))) |
... | ... |
@@ -145,21 +148,34 @@ v1: Improve default transfer encoding determination." |
145 | 148 |
|
146 | 149 |
(if* (and (not multipart) (null text) (null file)) |
147 | 150 |
then (error "One of :text or :file must be specified")) |
151 |
+ |
|
148 | 152 |
|
153 |
+ ;; Select default charset |
|
149 | 154 |
(if* (and (null charset) textp) |
150 | 155 |
then (setf charset |
151 | 156 |
(or |
152 | 157 |
(guess-charset-from-ef (find-external-format external-format)) |
153 | 158 |
"us-ascii"))) |
159 |
+ |
|
160 |
+ ;; For :text, break down to the final usb8. |
|
161 |
+ (when text |
|
162 |
+ (setf orig-text text) |
|
163 |
+ (setf text (if* (stringp text) |
|
164 |
+ then (string-to-octets text :null-terminate nil |
|
165 |
+ :external-format external-format |
|
166 |
+ :start start |
|
167 |
+ :end end) |
|
168 |
+ else (subseq text start end)))) |
|
154 | 169 |
|
170 |
+ ;; Select default encoding, which is always base64 except for |
|
171 |
+ ;; when :text was supplied as a string, in which case we scan to |
|
172 |
+ ;; choose between 7bit and base64. |
|
155 | 173 |
(when (and (not multipart) (null encoding)) |
156 |
- (if* textp |
|
157 |
- then (if* (member charset '("us-ascii" "iso-2022-jp") |
|
158 |
- :test #'equalp) |
|
159 |
- then (setf encoding "7bit") |
|
160 |
- else (setf encoding "8bit")) |
|
161 |
- else (setf encoding "base64"))) |
|
162 |
- |
|
174 |
+ (setf encoding |
|
175 |
+ (if* (and (stringp orig-text) (not (8-bit-array-p text))) |
|
176 |
+ then "7bit" |
|
177 |
+ else "base64"))) |
|
178 |
+ |
|
163 | 179 |
(setf (mime-part-type part) type) |
164 | 180 |
(setf (mime-part-subtype part) subtype) |
165 | 181 |
(setf (mime-part-parameters part) parameters) |
... | ... |
@@ -179,11 +195,7 @@ v1: Improve default transfer encoding determination." |
179 | 195 |
(if* (not attachmentp-supplied) |
180 | 196 |
then (setf attachmentp t)) |
181 | 197 |
else (setf (source-type part) :usb8) |
182 |
- (setf (source part) |
|
183 |
- (if* (stringp text) |
|
184 |
- then (string-to-octets text :null-terminate nil |
|
185 |
- :external-format external-format) |
|
186 |
- else (subseq text start end)))) |
|
198 |
+ (setf (source part) text)) |
|
187 | 199 |
|
188 | 200 |
(if* (and (not textp) (not attachmentp) (not multipart)) |
189 | 201 |
then (setf (disposition part) "inline")) |
... | ... |
@@ -206,6 +218,14 @@ v1: Improve default transfer encoding determination." |
206 | 218 |
|
207 | 219 |
part)) |
208 | 220 |
|
221 |
+(defun 8-bit-array-p (usb8) |
|
222 |
+ (declare (optimize (speed 3) (safety 0)) |
|
223 |
+ ((simple-array (unsigned-byte 8) (*)) usb8)) |
|
224 |
+ (dotimes (n (length usb8)) |
|
225 |
+ (declare (fixnum n)) |
|
226 |
+ (if (> (aref usb8 n) 127) |
|
227 |
+ (return t)))) |
|
228 |
+ |
|
209 | 229 |
(defparameter *ef-nick-to-mime-charset* |
210 | 230 |
'((:ascii . "us-ascii") |
211 | 231 |
(:iso-2022-jp . "iso-2022-jp") |
... | ... |
@@ -223,7 +243,7 @@ v1: Improve default transfer encoding determination." |
223 | 243 |
(let ((ef-name (string-downcase (symbol-name (ef-name (crlf-base-ef ef)))))) |
224 | 244 |
;; Try iso-8559-x names. |
225 | 245 |
(multiple-value-bind (found ignore suffix) |
226 |
- (match-re (load-time-value "^iso8859-(\\d+)-base") ef-name) |
|
246 |
+ (match-re "^iso8859-(\\d+)-base" ef-name) |
|
227 | 247 |
(declare (ignore ignore)) |
228 | 248 |
(if found |
229 | 249 |
(return-from guess-charset-from-ef |
... | ... |
@@ -231,7 +251,7 @@ v1: Improve default transfer encoding determination." |
231 | 251 |
|
232 | 252 |
;; Try windows- names. |
233 | 253 |
(multiple-value-bind (found whole value) |
234 |
- (match-re (load-time-value "^(\\d+)-base$") ef-name) |
|
254 |
+ (match-re "^(\\d+)-base$" ef-name) |
|
235 | 255 |
(declare (ignore whole)) |
236 | 256 |
(if found |
237 | 257 |
(return-from guess-charset-from-ef |
... | ... |
@@ -1,17 +1,19 @@ |
1 | 1 |
#+(version= 8 0) |
2 |
-(sys:defpatch "smtp" 4 |
|
2 |
+(sys:defpatch "smtp" 5 |
|
3 | 3 |
"v1: send-letter w/attachments; send-smtp* can take streams; |
4 | 4 |
v2: add :port argument to send-letter, send-smtp, send-smtp-auth; |
5 | 5 |
v3: fix incompatibility introduced in v2; |
6 |
-v4: remove stray force-output of t." |
|
6 |
+v4: remove stray force-output of t; |
|
7 |
+v5: send-smtp-1: New external-format keyword arg." |
|
7 | 8 |
:type :system |
8 | 9 |
:post-loadable t) |
9 | 10 |
|
10 | 11 |
#+(version= 7 0) |
11 |
-(sys:defpatch "smtp" 4 |
|
12 |
+(sys:defpatch "smtp" 5 |
|
12 | 13 |
"v2: send-letter w/attachments; send-smtp* can take streams; |
13 | 14 |
v3: add :port argument to send-letter, send-smtp, send-smtp-auth; |
14 |
-v4: fix incompatibility introduced in v3." |
|
15 |
+v4: fix incompatibility introduced in v3; |
|
16 |
+v5: rm stray force-output of t; send-smtp-1: New external-format keyword arg." |
|
15 | 17 |
:type :system |
16 | 18 |
:post-loadable t) |
17 | 19 |
|
... | ... |
@@ -41,7 +43,7 @@ v4: fix incompatibility introduced in v3." |
41 | 43 |
;; Suite 330, Boston, MA 02111-1307 USA |
42 | 44 |
;; |
43 | 45 |
;; |
44 |
-;; $Id: smtp.cl,v 1.20 2006/10/16 17:35:38 layer Exp $ |
|
46 |
+;; $Id: smtp.cl,v 1.21 2006/11/17 00:32:07 layer Exp $ |
|
45 | 47 |
|
46 | 48 |
;; Description: |
47 | 49 |
;; send mail to an smtp server. See rfc821 for the spec. |
... | ... |
@@ -247,7 +249,8 @@ Attachments must be filenames, streams, or mime-part-constructed, not ~s" |
247 | 249 |
(defun send-smtp-auth (server from to login password &rest messages) |
248 | 250 |
(send-smtp-1 server from to login password messages)) |
249 | 251 |
|
250 |
-(defun send-smtp-1 (server from to login password messages) |
|
252 |
+(defun send-smtp-1 (server from to login password messages |
|
253 |
+ &key (external-format :default)) |
|
251 | 254 |
;; send the effective concatenation of the messages via |
252 | 255 |
;; smtp to the mail server |
253 | 256 |
;; Each message should be a string or a stream. |
... | ... |
@@ -297,24 +300,24 @@ Attachments must be filenames, streams, or mime-part-constructed, not ~s" |
297 | 300 |
(when message |
298 | 301 |
(setf stream (if* (streamp message) |
299 | 302 |
then message |
300 |
- else (make-string-input-stream message))) |
|
301 |
- (unwind-protect |
|
302 |
- (progn |
|
303 |
- (while (setf ch (read-char stream nil nil)) |
|
304 |
- (if* (and at-bol (eq ch #\.)) |
|
305 |
- then ;; to prevent . from being interpreted as eol |
|
306 |
- (write-char #\. sock)) |
|
307 |
- (if* (eq ch #\newline) |
|
308 |
- then (setq at-bol t) |
|
309 |
- (if* (not (eq prev-ch #\return)) |
|
310 |
- then (write-char #\return sock)) |
|
311 |
- else (setq at-bol nil)) |
|
312 |
- (write-char ch sock) |
|
313 |
- (setq prev-ch ch))) |
|
314 |
- ;; unwind-protect |
|
315 |
- (if* (not (streamp message)) |
|
316 |
- then (close stream)))))) |
|
317 |
- |
|
303 |
+ else (make-buffer-input-stream |
|
304 |
+ (string-to-octets |
|
305 |
+ message |
|
306 |
+ :null-terminate nil |
|
307 |
+ :external-format external-format)))) |
|
308 |
+ |
|
309 |
+ (while (setf ch (read-byte stream nil)) |
|
310 |
+ (if* (and at-bol (eq ch #.(char-code #\.))) |
|
311 |
+ then ;; to prevent . from being interpreted as eol |
|
312 |
+ (write-char #\. sock)) |
|
313 |
+ (if* (eq ch #.(char-code #\newline)) |
|
314 |
+ then (setq at-bol t) |
|
315 |
+ (if* (not (eq prev-ch #.(char-code #\return))) |
|
316 |
+ then (write-char #\return sock)) |
|
317 |
+ else (setq at-bol nil)) |
|
318 |
+ (write-byte ch sock) |
|
319 |
+ (setq prev-ch ch))))) |
|
320 |
+ |
|
318 | 321 |
(write-char #\return sock) (write-char #\linefeed sock) |
319 | 322 |
(write-char #\. sock) |
320 | 323 |
(write-char #\return sock) (write-char #\linefeed sock) |