Mercurial > emacs
comparison lisp/mail/smtpmail.el @ 89909:68c22ea6027c
Sync to HEAD
author | Kenichi Handa <handa@m17n.org> |
---|---|
date | Fri, 16 Apr 2004 12:51:06 +0000 |
parents | 375f2633d815 |
children | 4c90ffeb71c5 |
comparison
equal
deleted
inserted
replaced
89908:ee1402f7b568 | 89909:68c22ea6027c |
---|---|
1 ;;; smtpmail.el --- simple SMTP protocol (RFC 821) for sending mail | 1 ;;; smtpmail.el --- simple SMTP protocol (RFC 821) for sending mail |
2 | 2 |
3 ;; Copyright (C) 1995, 1996, 2001, 2002, 2003 Free Software Foundation, Inc. | 3 ;; Copyright (C) 1995, 1996, 2001, 2002, 2003, 2004 |
4 ;; Free Software Foundation, Inc. | |
4 | 5 |
5 ;; Author: Tomoji Kagatani <kagatani@rbc.ncl.omron.co.jp> | 6 ;; Author: Tomoji Kagatani <kagatani@rbc.ncl.omron.co.jp> |
6 ;; Maintainer: Simon Josefsson <simon@josefsson.org> | 7 ;; Maintainer: Simon Josefsson <simon@josefsson.org> |
7 ;; w32 Maintainer: Brian D. Carlstrom <bdc@ai.mit.edu> | 8 ;; w32 Maintainer: Brian D. Carlstrom <bdc@ai.mit.edu> |
8 ;; ESMTP support: Simon Leinen <simon@switch.ch> | 9 ;; ESMTP support: Simon Leinen <simon@switch.ch> |
42 ;;(setq smtpmail-debug-info t) ; only to debug problems | 43 ;;(setq smtpmail-debug-info t) ; only to debug problems |
43 ;;(setq smtpmail-auth-credentials ; or use ~/.authinfo | 44 ;;(setq smtpmail-auth-credentials ; or use ~/.authinfo |
44 ;; '(("YOUR SMTP HOST" 25 "username" "password"))) | 45 ;; '(("YOUR SMTP HOST" 25 "username" "password"))) |
45 ;;(setq smtpmail-starttls-credentials | 46 ;;(setq smtpmail-starttls-credentials |
46 ;; '(("YOUR SMTP HOST" 25 "~/.my_smtp_tls.key" "~/.my_smtp_tls.cert"))) | 47 ;; '(("YOUR SMTP HOST" 25 "~/.my_smtp_tls.key" "~/.my_smtp_tls.cert"))) |
48 ;; Where the 25 equals the value of `smtpmail-smtp-service', it can be an | |
49 ;; integer or a string, just as long as they match (eq). | |
47 | 50 |
48 ;; To queue mail, set smtpmail-queue-mail to t and use | 51 ;; To queue mail, set smtpmail-queue-mail to t and use |
49 ;; smtpmail-send-queued-mail to send. | 52 ;; smtpmail-send-queued-mail to send. |
50 | 53 |
51 ;; Modified by Stephen Cranefield <scranefield@infoscience.otago.ac.nz>, | 54 ;; Modified by Stephen Cranefield <scranefield@infoscience.otago.ac.nz>, |
210 ;;; | 213 ;;; |
211 ;;; | 214 ;;; |
212 ;;; | 215 ;;; |
213 | 216 |
214 (defvar smtpmail-mail-address nil | 217 (defvar smtpmail-mail-address nil |
215 "Value of `user-mail-address' in ambient buffer.") | 218 "Value to use for envelope-from address for mail from ambient buffer.") |
216 | 219 |
217 ;;;###autoload | 220 ;;;###autoload |
218 (defun smtpmail-send-it () | 221 (defun smtpmail-send-it () |
219 (let ((errbuf (if mail-interactive | 222 (let ((errbuf (if mail-interactive |
220 (generate-new-buffer " smtpmail errors") | 223 (generate-new-buffer " smtpmail errors") |
221 0)) | 224 0)) |
222 (tembuf (generate-new-buffer " smtpmail temp")) | 225 (tembuf (generate-new-buffer " smtpmail temp")) |
223 (case-fold-search nil) | 226 (case-fold-search nil) |
224 delimline | 227 delimline |
225 (mailbuf (current-buffer)) | 228 (mailbuf (current-buffer)) |
226 (smtpmail-mail-address user-mail-address) | 229 ;; Examine this variable now, so that |
230 ;; local binding in the mail buffer will take effect. | |
231 (smtpmail-mail-address | |
232 (or (and mail-specify-envelope-from (mail-envelope-from)) | |
233 user-mail-address)) | |
227 (smtpmail-code-conv-from | 234 (smtpmail-code-conv-from |
228 (if enable-multibyte-characters | 235 (if enable-multibyte-characters |
229 (let ((sendmail-coding-system smtpmail-code-conv-from)) | 236 (let ((sendmail-coding-system smtpmail-code-conv-from)) |
230 (select-message-coding-system))))) | 237 (select-message-coding-system))))) |
231 (unwind-protect | 238 (unwind-protect |
397 ;; the MIME headers, and code conversions might guess the | 404 ;; the MIME headers, and code conversions might guess the |
398 ;; encoding wrongly. | 405 ;; encoding wrongly. |
399 (with-temp-buffer | 406 (with-temp-buffer |
400 (let ((coding-system-for-read 'no-conversion)) | 407 (let ((coding-system-for-read 'no-conversion)) |
401 (insert-file-contents file-msg)) | 408 (insert-file-contents file-msg)) |
402 (if (not (null smtpmail-recipient-address-list)) | 409 (let ((smtpmail-mail-address |
403 (if (not (smtpmail-via-smtp smtpmail-recipient-address-list | 410 (or (and mail-specify-envelope-from (mail-envelope-from)) |
404 (current-buffer))) | 411 user-mail-address))) |
405 (error "Sending failed; SMTP protocol error")) | 412 (if (not (null smtpmail-recipient-address-list)) |
406 (error "Sending failed; no recipients"))) | 413 (if (not (smtpmail-via-smtp smtpmail-recipient-address-list |
414 (current-buffer))) | |
415 (error "Sending failed; SMTP protocol error")) | |
416 (error "Sending failed; no recipients")))) | |
407 (delete-file file-msg) | 417 (delete-file file-msg) |
408 (delete-file (concat file-msg ".el")) | 418 (delete-file (concat file-msg ".el")) |
409 (delete-region (point-at-bol) (point-at-bol 2))) | 419 (delete-region (point-at-bol) (point-at-bol 2))) |
410 (write-region (point-min) (point-max) smtpmail-queue-index)))) | 420 (write-region (point-min) (point-max) smtpmail-queue-index)))) |
411 | 421 |
479 (defun smtpmail-try-auth-methods (process supported-extensions host port) | 489 (defun smtpmail-try-auth-methods (process supported-extensions host port) |
480 (let* ((mechs (cdr-safe (assoc 'auth supported-extensions))) | 490 (let* ((mechs (cdr-safe (assoc 'auth supported-extensions))) |
481 (mech (car (smtpmail-intersection smtpmail-auth-supported mechs))) | 491 (mech (car (smtpmail-intersection smtpmail-auth-supported mechs))) |
482 (cred (if (stringp smtpmail-auth-credentials) | 492 (cred (if (stringp smtpmail-auth-credentials) |
483 (let* ((netrc (netrc-parse smtpmail-auth-credentials)) | 493 (let* ((netrc (netrc-parse smtpmail-auth-credentials)) |
484 (hostentry (netrc-machine | 494 (port-name (format "%s" (or port "smtp"))) |
485 netrc host (format "%s" (or port "smtp")) | 495 (hostentry (netrc-machine netrc host port-name |
486 "smtp"))) | 496 port-name))) |
487 (when hostentry | 497 (when hostentry |
488 (list host port | 498 (list host port |
489 (netrc-get hostentry "login") | 499 (netrc-get hostentry "login") |
490 (netrc-get hostentry "password")))) | 500 (netrc-get hostentry "password")))) |
491 (smtpmail-find-credentials | 501 (smtpmail-find-credentials |
495 (read-passwd | 505 (read-passwd |
496 (format "SMTP password for %s:%s: " | 506 (format "SMTP password for %s:%s: " |
497 (smtpmail-cred-server cred) | 507 (smtpmail-cred-server cred) |
498 (smtpmail-cred-port cred)))))) | 508 (smtpmail-cred-port cred)))))) |
499 ret) | 509 ret) |
500 (when cred | 510 (when (and cred mech) |
501 (cond | 511 (cond |
502 ((eq mech 'cram-md5) | 512 ((eq mech 'cram-md5) |
503 (smtpmail-send-command process (format "AUTH %s" mech)) | 513 (smtpmail-send-command process (format "AUTH %s" mech)) |
504 (if (or (null (car (setq ret (smtpmail-read-response process)))) | 514 (if (or (null (car (setq ret (smtpmail-read-response process)))) |
505 (not (integerp (car ret))) | 515 (not (integerp (car ret))) |
543 (defun smtpmail-via-smtp (recipient smtpmail-text-buffer) | 553 (defun smtpmail-via-smtp (recipient smtpmail-text-buffer) |
544 (let ((process nil) | 554 (let ((process nil) |
545 (host (or smtpmail-smtp-server | 555 (host (or smtpmail-smtp-server |
546 (error "`smtpmail-smtp-server' not defined"))) | 556 (error "`smtpmail-smtp-server' not defined"))) |
547 (port smtpmail-smtp-service) | 557 (port smtpmail-smtp-service) |
548 (envelope-from (or (mail-envelope-from) | 558 ;; smtpmail-mail-address should be set to the appropriate |
549 smtpmail-mail-address | 559 ;; buffer-local value by the caller, but in case not: |
550 user-mail-address)) | 560 (envelope-from (or smtpmail-mail-address |
561 (and mail-specify-envelope-from | |
562 (mail-envelope-from)) | |
563 user-mail-address)) | |
551 response-code | 564 response-code |
552 greeting | 565 greeting |
553 process-buffer | 566 process-buffer |
554 (supported-extensions '())) | 567 (supported-extensions '())) |
555 (unwind-protect | 568 (unwind-protect |
659 (if (or (null (car (setq response-code (smtpmail-read-response process)))) | 672 (if (or (null (car (setq response-code (smtpmail-read-response process)))) |
660 (not (integerp (car response-code))) | 673 (not (integerp (car response-code))) |
661 (>= (car response-code) 400)) | 674 (>= (car response-code) 400)) |
662 (throw 'done nil)))) | 675 (throw 'done nil)))) |
663 | 676 |
664 ;; MAIL FROM: <sender> | 677 ;; MAIL FROM:<sender> |
665 (let ((size-part | 678 (let ((size-part |
666 (if (or (member 'size supported-extensions) | 679 (if (or (member 'size supported-extensions) |
667 (assoc 'size supported-extensions)) | 680 (assoc 'size supported-extensions)) |
668 (format " SIZE=%d" | 681 (format " SIZE=%d" |
669 (with-current-buffer smtpmail-text-buffer | 682 (with-current-buffer smtpmail-text-buffer |
670 ;; size estimate: | 683 ;; size estimate: |
671 (+ (- (point-max) (point-min)) | 684 (+ (- (point-max) (point-min)) |
672 ;; Add one byte for each change-of-line | 685 ;; Add one byte for each change-of-line |
673 ;; because or CR-LF representation: | 686 ;; because of CR-LF representation: |
674 (count-lines (point-min) (point-max)) | 687 (count-lines (point-min) (point-max))))) |
675 ;; For some reason, an empty line is | |
676 ;; added to the message. Maybe this | |
677 ;; is a bug, but it can't hurt to add | |
678 ;; those two bytes anyway: | |
679 2))) | |
680 "")) | 688 "")) |
681 (body-part | 689 (body-part |
682 (if (member '8bitmime supported-extensions) | 690 (if (member '8bitmime supported-extensions) |
683 ;; FIXME: | 691 ;; FIXME: |
684 ;; Code should be added here that transforms | 692 ;; Code should be added here that transforms |
694 (if nil | 702 (if nil |
695 " BODY=8BITMIME" | 703 " BODY=8BITMIME" |
696 "") | 704 "") |
697 ""))) | 705 ""))) |
698 ; (smtpmail-send-command process (format "MAIL FROM:%s@%s" (user-login-name) (smtpmail-fqdn))) | 706 ; (smtpmail-send-command process (format "MAIL FROM:%s@%s" (user-login-name) (smtpmail-fqdn))) |
699 (smtpmail-send-command process (format "MAIL FROM: <%s>%s%s" | 707 (smtpmail-send-command process (format "MAIL FROM:<%s>%s%s" |
700 envelope-from | 708 envelope-from |
701 size-part | 709 size-part |
702 body-part)) | 710 body-part)) |
703 | 711 |
704 (if (or (null (car (setq response-code (smtpmail-read-response process)))) | 712 (if (or (null (car (setq response-code (smtpmail-read-response process)))) |
705 (not (integerp (car response-code))) | 713 (not (integerp (car response-code))) |
706 (>= (car response-code) 400)) | 714 (>= (car response-code) 400)) |
707 (throw 'done nil) | 715 (throw 'done nil) |
708 )) | 716 )) |
709 | 717 |
710 ;; RCPT TO: <recipient> | 718 ;; RCPT TO:<recipient> |
711 (let ((n 0)) | 719 (let ((n 0)) |
712 (while (not (null (nth n recipient))) | 720 (while (not (null (nth n recipient))) |
713 (smtpmail-send-command process (format "RCPT TO: <%s>" (smtpmail-maybe-append-domain (nth n recipient)))) | 721 (smtpmail-send-command process (format "RCPT TO:<%s>" (smtpmail-maybe-append-domain (nth n recipient)))) |
714 (setq n (1+ n)) | 722 (setq n (1+ n)) |
715 | 723 |
716 (setq response-code (smtpmail-read-response process)) | 724 (setq response-code (smtpmail-read-response process)) |
717 (if (or (null (car response-code)) | 725 (if (or (null (car response-code)) |
718 (not (integerp (car response-code))) | 726 (not (integerp (car response-code))) |
771 (let ((case-fold-search nil) | 779 (let ((case-fold-search nil) |
772 (response-strings nil) | 780 (response-strings nil) |
773 (response-continue t) | 781 (response-continue t) |
774 (return-value '(nil ())) | 782 (return-value '(nil ())) |
775 match-end) | 783 match-end) |
776 | 784 (catch 'done |
777 (while response-continue | 785 (while response-continue |
778 (goto-char smtpmail-read-point) | 786 (goto-char smtpmail-read-point) |
779 (while (not (search-forward "\r\n" nil t)) | 787 (while (not (search-forward "\r\n" nil t)) |
780 (accept-process-output process) | 788 (unless (memq (process-status process) '(open run)) |
781 (goto-char smtpmail-read-point)) | 789 (throw 'done nil)) |
782 | 790 (accept-process-output process) |
783 (setq match-end (point)) | 791 (goto-char smtpmail-read-point)) |
784 (setq response-strings | 792 |
785 (cons (buffer-substring smtpmail-read-point (- match-end 2)) | 793 (setq match-end (point)) |
786 response-strings)) | 794 (setq response-strings |
787 | 795 (cons (buffer-substring smtpmail-read-point (- match-end 2)) |
788 (goto-char smtpmail-read-point) | 796 response-strings)) |
789 (if (looking-at "[0-9]+ ") | 797 |
790 (let ((begin (match-beginning 0)) | 798 (goto-char smtpmail-read-point) |
791 (end (match-end 0))) | 799 (if (looking-at "[0-9]+ ") |
792 (if smtpmail-debug-info | 800 (let ((begin (match-beginning 0)) |
793 (message "%s" (car response-strings))) | 801 (end (match-end 0))) |
794 | 802 (if smtpmail-debug-info |
795 (setq smtpmail-read-point match-end) | 803 (message "%s" (car response-strings))) |
796 | 804 |
797 ;; ignore lines that start with "0" | 805 (setq smtpmail-read-point match-end) |
798 (if (looking-at "0[0-9]+ ") | 806 |
799 nil | 807 ;; ignore lines that start with "0" |
808 (if (looking-at "0[0-9]+ ") | |
809 nil | |
810 (setq response-continue nil) | |
811 (setq return-value | |
812 (cons (string-to-int | |
813 (buffer-substring begin end)) | |
814 (nreverse response-strings))))) | |
815 | |
816 (if (looking-at "[0-9]+-") | |
817 (progn (if smtpmail-debug-info | |
818 (message "%s" (car response-strings))) | |
819 (setq smtpmail-read-point match-end) | |
820 (setq response-continue t)) | |
821 (progn | |
822 (setq smtpmail-read-point match-end) | |
800 (setq response-continue nil) | 823 (setq response-continue nil) |
801 (setq return-value | 824 (setq return-value |
802 (cons (string-to-int | 825 (cons nil (nreverse response-strings))))))) |
803 (buffer-substring begin end)) | 826 (setq smtpmail-read-point match-end)) |
804 (nreverse response-strings))))) | |
805 | |
806 (if (looking-at "[0-9]+-") | |
807 (progn (if smtpmail-debug-info | |
808 (message "%s" (car response-strings))) | |
809 (setq smtpmail-read-point match-end) | |
810 (setq response-continue t)) | |
811 (progn | |
812 (setq smtpmail-read-point match-end) | |
813 (setq response-continue nil) | |
814 (setq return-value | |
815 (cons nil (nreverse response-strings))) | |
816 ) | |
817 ))) | |
818 (setq smtpmail-read-point match-end) | |
819 return-value)) | 827 return-value)) |
820 | 828 |
821 | 829 |
822 (defun smtpmail-send-command (process command) | 830 (defun smtpmail-send-command (process command) |
823 (goto-char (point-max)) | 831 (goto-char (point-max)) |
846 (process-send-string process data) | 854 (process-send-string process data) |
847 (process-send-string process "\r\n") | 855 (process-send-string process "\r\n") |
848 ) | 856 ) |
849 | 857 |
850 (defun smtpmail-send-data (process buffer) | 858 (defun smtpmail-send-data (process buffer) |
851 (let | 859 (let ((data-continue t) sending-data) |
852 ((data-continue t) | |
853 (sending-data nil) | |
854 this-line | |
855 this-line-end) | |
856 | |
857 (with-current-buffer buffer | 860 (with-current-buffer buffer |
858 (goto-char (point-min))) | 861 (goto-char (point-min))) |
859 | |
860 (while data-continue | 862 (while data-continue |
861 (with-current-buffer buffer | 863 (with-current-buffer buffer |
862 (beginning-of-line) | 864 (setq sending-data (buffer-substring (point-at-bol) (point-at-eol))) |
863 (setq this-line (point)) | 865 (end-of-line 2) |
864 (end-of-line) | 866 (setq data-continue (not (eobp)))) |
865 (setq this-line-end (point)) | 867 (smtpmail-send-data-1 process sending-data)))) |
866 (setq sending-data nil) | |
867 (setq sending-data (buffer-substring this-line this-line-end)) | |
868 (if (/= (forward-line 1) 0) | |
869 (setq data-continue nil))) | |
870 | |
871 (smtpmail-send-data-1 process sending-data) | |
872 ) | |
873 ) | |
874 ) | |
875 | |
876 | 868 |
877 (defun smtpmail-deduce-address-list (smtpmail-text-buffer header-start header-end) | 869 (defun smtpmail-deduce-address-list (smtpmail-text-buffer header-start header-end) |
878 "Get address list suitable for smtp RCPT TO: <address>." | 870 "Get address list suitable for smtp RCPT TO: <address>." |
879 (unwind-protect | 871 (unwind-protect |
880 (with-current-buffer smtpmail-address-buffer | 872 (with-current-buffer smtpmail-address-buffer |
948 (replace-match "")))))) | 940 (replace-match "")))))) |
949 | 941 |
950 | 942 |
951 (provide 'smtpmail) | 943 (provide 'smtpmail) |
952 | 944 |
945 ;;; arch-tag: a76992df-6d71-43b7-9e72-4bacc6c05466 | |
953 ;;; smtpmail.el ends here | 946 ;;; smtpmail.el ends here |