diff options
| author | Richard M. Stallman | 1997-06-01 22:24:22 +0000 |
|---|---|---|
| committer | Richard M. Stallman | 1997-06-01 22:24:22 +0000 |
| commit | c50d5ce0d1c6ef8a064e16834da8b903fd73c98d (patch) | |
| tree | 3a3cf3fee67bf5b195c7fa69f741dfd186e15d5e | |
| parent | 95b597ce99aea8d8af098a776a9099afad775552 (diff) | |
| download | emacs-c50d5ce0d1c6ef8a064e16834da8b903fd73c98d.tar.gz emacs-c50d5ce0d1c6ef8a064e16834da8b903fd73c98d.zip | |
(smtpmail-via-smtp): Recognize XVRB as a synonym for
VERB and XONE as a synonym for ONEX.
(smtpmail-read-response): Add "%s" to `message' calls to avoid
problems with percent signs in strings.
(smtpmail-read-response): Return all lines of the
response text as a list of strings. Formerly only the first line
was returned. This is insufficient when one wants to parse
e.g. an EHLO response.
Ignore responses starting with "0". This is necessary to support
the VERB SMTP extension.
(smtpmail-via-smtp): Try EHLO and find out which SMTP service
extensions the receiving mailer supports.
Issue the ONEX and XUSR commands if the corresponding extensions
are supported.
Issue VERB if supported and `smtpmail-debug-info' is non-nil.
Add SIZE attribute to MAIL FROM: command if SIZE extension is
supported.
Add code that could set the BODY= attribute to MAIL FROM: if the
receiving mailer supports 8BITMIME. This is currently disabled,
since doing it right might involve adding MIME headers to, and in
some cases reencoding, the message.
| -rw-r--r-- | lisp/mail/smtpmail.el | 154 |
1 files changed, 120 insertions, 34 deletions
diff --git a/lisp/mail/smtpmail.el b/lisp/mail/smtpmail.el index 71cce7ced0d..6fa2418ce72 100644 --- a/lisp/mail/smtpmail.el +++ b/lisp/mail/smtpmail.el | |||
| @@ -4,6 +4,7 @@ | |||
| 4 | 4 | ||
| 5 | ;; Author: Tomoji Kagatani <kagatani@rbc.ncl.omron.co.jp> | 5 | ;; Author: Tomoji Kagatani <kagatani@rbc.ncl.omron.co.jp> |
| 6 | ;; Maintainer: Brian D. Carlstrom <bdc@ai.mit.edu> | 6 | ;; Maintainer: Brian D. Carlstrom <bdc@ai.mit.edu> |
| 7 | ;; ESMTP support: Simon Leinen <simon@switch.ch> | ||
| 7 | ;; Keywords: mail | 8 | ;; Keywords: mail |
| 8 | 9 | ||
| 9 | ;; This file is part of GNU Emacs. | 10 | ;; This file is part of GNU Emacs. |
| @@ -243,7 +244,8 @@ don't define this value." | |||
| 243 | (port smtpmail-smtp-service) | 244 | (port smtpmail-smtp-service) |
| 244 | response-code | 245 | response-code |
| 245 | greeting | 246 | greeting |
| 246 | process-buffer) | 247 | process-buffer |
| 248 | (supported-extensions '())) | ||
| 247 | (unwind-protect | 249 | (unwind-protect |
| 248 | (catch 'done | 250 | (catch 'done |
| 249 | ;; get or create the trace buffer | 251 | ;; get or create the trace buffer |
| @@ -274,24 +276,105 @@ don't define this value." | |||
| 274 | (throw 'done nil) | 276 | (throw 'done nil) |
| 275 | ) | 277 | ) |
| 276 | 278 | ||
| 277 | ;; HELO | 279 | ;; EHLO |
| 278 | (smtpmail-send-command process (format "HELO %s" (smtpmail-fqdn))) | 280 | (smtpmail-send-command process (format "EHLO %s" (smtpmail-fqdn))) |
| 279 | 281 | ||
| 280 | (if (or (null (car (setq response-code (smtpmail-read-response process)))) | 282 | (if (or (null (car (setq response-code (smtpmail-read-response process)))) |
| 281 | (not (integerp (car response-code))) | 283 | (not (integerp (car response-code))) |
| 282 | (>= (car response-code) 400)) | 284 | (>= (car response-code) 400)) |
| 283 | (throw 'done nil) | 285 | (progn |
| 284 | ) | 286 | ;; HELO |
| 287 | (smtpmail-send-command process (format "HELO %s" (smtpmail-fqdn))) | ||
| 288 | |||
| 289 | (if (or (null (car (setq response-code (smtpmail-read-response process)))) | ||
| 290 | (not (integerp (car response-code))) | ||
| 291 | (>= (car response-code) 400)) | ||
| 292 | (throw 'done nil))) | ||
| 293 | (let ((extension-lines (cdr (cdr response-code)))) | ||
| 294 | (while extension-lines | ||
| 295 | (let ((name (intern (downcase (substring (car extension-lines) 4))))) | ||
| 296 | (and name | ||
| 297 | (cond ((memq name '(verb xvrb 8bitmime onex xone | ||
| 298 | expn size dsn etrn | ||
| 299 | help xusr)) | ||
| 300 | (setq supported-extensions | ||
| 301 | (cons name supported-extensions))) | ||
| 302 | (t (message "unknown extension %s" | ||
| 303 | name))))) | ||
| 304 | (setq extension-lines (cdr extension-lines))))) | ||
| 305 | |||
| 306 | (if (or (member 'onex supported-extensions) | ||
| 307 | (member 'xone supported-extensions)) | ||
| 308 | (progn | ||
| 309 | (smtpmail-send-command process (format "ONEX")) | ||
| 310 | (if (or (null (car (setq response-code (smtpmail-read-response process)))) | ||
| 311 | (not (integerp (car response-code))) | ||
| 312 | (>= (car response-code) 400)) | ||
| 313 | (throw 'done nil)))) | ||
| 314 | |||
| 315 | (if (and smtpmail-debug-info | ||
| 316 | (or (member 'verb supported-extensions) | ||
| 317 | (member 'xvrb supported-extensions))) | ||
| 318 | (progn | ||
| 319 | (smtpmail-send-command process (format "VERB")) | ||
| 320 | (if (or (null (car (setq response-code (smtpmail-read-response process)))) | ||
| 321 | (not (integerp (car response-code))) | ||
| 322 | (>= (car response-code) 400)) | ||
| 323 | (throw 'done nil)))) | ||
| 324 | |||
| 325 | (if (member 'xusr supported-extensions) | ||
| 326 | (progn | ||
| 327 | (smtpmail-send-command process (format "XUSR")) | ||
| 328 | (if (or (null (car (setq response-code (smtpmail-read-response process)))) | ||
| 329 | (not (integerp (car response-code))) | ||
| 330 | (>= (car response-code) 400)) | ||
| 331 | (throw 'done nil)))) | ||
| 285 | 332 | ||
| 286 | ;; MAIL FROM: <sender> | 333 | ;; MAIL FROM: <sender> |
| 287 | ; (smtpmail-send-command process (format "MAIL FROM:%s@%s" (user-login-name) (smtpmail-fqdn))) | 334 | (let ((size-part |
| 288 | (smtpmail-send-command process (format "MAIL FROM: <%s>" user-mail-address)) | 335 | (if (member 'size supported-extensions) |
| 289 | 336 | (format " SIZE=%d" | |
| 290 | (if (or (null (car (setq response-code (smtpmail-read-response process)))) | 337 | (save-excursion |
| 291 | (not (integerp (car response-code))) | 338 | (set-buffer smtpmail-text-buffer) |
| 292 | (>= (car response-code) 400)) | 339 | ;; size estimate: |
| 293 | (throw 'done nil) | 340 | (+ (- (point-max) (point-min)) |
| 294 | ) | 341 | ;; Add one byte for each change-of-line |
| 342 | ;; because or CR-LF representation: | ||
| 343 | (count-lines (point-min) (point-max)) | ||
| 344 | ;; For some reason, an empty line is | ||
| 345 | ;; added to the message. Maybe this | ||
| 346 | ;; is a bug, but it can't hurt to add | ||
| 347 | ;; those two bytes anyway: | ||
| 348 | 2))) | ||
| 349 | "")) | ||
| 350 | (body-part | ||
| 351 | (if (member '8bitmime supported-extensions) | ||
| 352 | ;; FIXME: | ||
| 353 | ;; Code should be added here that transforms | ||
| 354 | ;; the contents of the message buffer into | ||
| 355 | ;; something the receiving SMTP can handle. | ||
| 356 | ;; For a receiver that supports 8BITMIME, this | ||
| 357 | ;; may mean converting BINARY to BASE64, or | ||
| 358 | ;; adding Content-Transfer-Encoding and the | ||
| 359 | ;; other MIME headers. The code should also | ||
| 360 | ;; return an indication of what encoding the | ||
| 361 | ;; message buffer is now, i.e. ASCII or | ||
| 362 | ;; 8BITMIME. | ||
| 363 | (if nil | ||
| 364 | " BODY=8BITMIME" | ||
| 365 | "") | ||
| 366 | ""))) | ||
| 367 | ; (smtpmail-send-command process (format "MAIL FROM:%s@%s" (user-login-name) (smtpmail-fqdn))) | ||
| 368 | (smtpmail-send-command process (format "MAIL FROM: <%s>%s%s" | ||
| 369 | user-mail-address | ||
| 370 | size-part | ||
| 371 | body-part)) | ||
| 372 | |||
| 373 | (if (or (null (car (setq response-code (smtpmail-read-response process)))) | ||
| 374 | (not (integerp (car response-code))) | ||
| 375 | (>= (car response-code) 400)) | ||
| 376 | (throw 'done nil) | ||
| 377 | )) | ||
| 295 | 378 | ||
| 296 | ;; RCPT TO: <recipient> | 379 | ;; RCPT TO: <recipient> |
| 297 | (let ((n 0)) | 380 | (let ((n 0)) |
| @@ -299,7 +382,8 @@ don't define this value." | |||
| 299 | (smtpmail-send-command process (format "RCPT TO: <%s>" (nth n recipient))) | 382 | (smtpmail-send-command process (format "RCPT TO: <%s>" (nth n recipient))) |
| 300 | (setq n (1+ n)) | 383 | (setq n (1+ n)) |
| 301 | 384 | ||
| 302 | (if (or (null (car (setq response-code (smtpmail-read-response process)))) | 385 | (setq response-code (smtpmail-read-response process)) |
| 386 | (if (or (null (car response-code)) | ||
| 303 | (not (integerp (car response-code))) | 387 | (not (integerp (car response-code))) |
| 304 | (>= (car response-code) 400)) | 388 | (>= (car response-code) 400)) |
| 305 | (throw 'done nil) | 389 | (throw 'done nil) |
| @@ -354,15 +438,11 @@ don't define this value." | |||
| 354 | 438 | ||
| 355 | (defun smtpmail-read-response (process) | 439 | (defun smtpmail-read-response (process) |
| 356 | (let ((case-fold-search nil) | 440 | (let ((case-fold-search nil) |
| 357 | (response-string nil) | 441 | (response-strings nil) |
| 358 | (response-continue t) | 442 | (response-continue t) |
| 359 | (return-value '(nil "")) | 443 | (return-value '(nil ())) |
| 360 | match-end) | 444 | match-end) |
| 361 | 445 | ||
| 362 | ; (setq response-string nil) | ||
| 363 | ; (setq response-continue t) | ||
| 364 | ; (setq return-value '(nil "")) | ||
| 365 | |||
| 366 | (while response-continue | 446 | (while response-continue |
| 367 | (goto-char smtpmail-read-point) | 447 | (goto-char smtpmail-read-point) |
| 368 | (while (not (search-forward "\r\n" nil t)) | 448 | (while (not (search-forward "\r\n" nil t)) |
| @@ -370,32 +450,38 @@ don't define this value." | |||
| 370 | (goto-char smtpmail-read-point)) | 450 | (goto-char smtpmail-read-point)) |
| 371 | 451 | ||
| 372 | (setq match-end (point)) | 452 | (setq match-end (point)) |
| 373 | (if (null response-string) | 453 | (setq response-strings |
| 374 | (setq response-string | 454 | (cons (buffer-substring smtpmail-read-point (- match-end 2)) |
| 375 | (buffer-substring smtpmail-read-point (- match-end 2)))) | 455 | response-strings)) |
| 376 | 456 | ||
| 377 | (goto-char smtpmail-read-point) | 457 | (goto-char smtpmail-read-point) |
| 378 | (if (looking-at "[0-9]+ ") | 458 | (if (looking-at "[0-9]+ ") |
| 379 | (progn (setq response-continue nil) | 459 | (let ((begin (match-beginning 0)) |
| 380 | ; (setq return-value response-string) | 460 | (end (match-end 0))) |
| 461 | (if smtpmail-debug-info | ||
| 462 | (message "%s" (car response-strings))) | ||
| 381 | 463 | ||
| 382 | (if smtpmail-debug-info | 464 | (setq smtpmail-read-point match-end) |
| 383 | (message "%s" response-string)) | ||
| 384 | 465 | ||
| 385 | (setq smtpmail-read-point match-end) | 466 | ;; ignore lines that start with "0" |
| 386 | (setq return-value | 467 | (if (looking-at "0[0-9]+ ") |
| 387 | (cons (string-to-int | 468 | nil |
| 388 | (buffer-substring (match-beginning 0) (match-end 0))) | 469 | (setq response-continue nil) |
| 389 | response-string))) | 470 | (setq return-value |
| 471 | (cons (string-to-int | ||
| 472 | (buffer-substring begin end)) | ||
| 473 | (nreverse response-strings))))) | ||
| 390 | 474 | ||
| 391 | (if (looking-at "[0-9]+-") | 475 | (if (looking-at "[0-9]+-") |
| 392 | (progn (setq smtpmail-read-point match-end) | 476 | (progn (if smtpmail-debug-info |
| 477 | (message "%s" (car response-strings))) | ||
| 478 | (setq smtpmail-read-point match-end) | ||
| 393 | (setq response-continue t)) | 479 | (setq response-continue t)) |
| 394 | (progn | 480 | (progn |
| 395 | (setq smtpmail-read-point match-end) | 481 | (setq smtpmail-read-point match-end) |
| 396 | (setq response-continue nil) | 482 | (setq response-continue nil) |
| 397 | (setq return-value | 483 | (setq return-value |
| 398 | (cons nil response-string)) | 484 | (cons nil (nreverse response-strings))) |
| 399 | ) | 485 | ) |
| 400 | ))) | 486 | ))) |
| 401 | (setq smtpmail-read-point match-end) | 487 | (setq smtpmail-read-point match-end) |