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