;;; smtp.el --- basic functions to send mail with SMTP server
-;; Copyright (C) 1995, 1996, 1998, 1999, 2000 Free Software Foundation, Inc.
+;; Copyright (C) 1995, 1996, 1998, 1999, 2000, 2001 ,2002, 2004
+;; Free Software Foundation, Inc.
;; Author: Tomoji Kagatani <kagatani@rbc.ncl.omron.co.jp>
;; Simon Leinen <simon@switch.ch> (ESMTP support)
;; You should have received a copy of the GNU General Public License
;; along with this program; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
+;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
;;; Commentary:
:type 'boolean
:group 'smtp-extensions)
+(defcustom smtp-starttls-program "starttls"
+ "The program to run in a subprocess to open an TLSv1 connection."
+ :group 'smtp-extensions)
+
+(defcustom smtp-starttls-extra-args nil
+ "Extra arguments to `starttls-program'"
+ :group 'smtp-extensions)
+
(defcustom smtp-use-sasl nil
"If non-nil, use SMTP Authentication (RFC2554) if available."
:type 'boolean
:type '(repeat string)
:group 'smtp-extensions)
+(defcustom smtp-debug nil
+ "*If non-nil, smtp debug info printout into messages."
+ :type 'boolean
+ :group 'smtp)
+
(defvar sasl-mechanisms)
;;;###autoload
It connects to a SMTP server using \"ssh\" before actually connecting
to the SMTP port. Where the command \"nc\" is the netcat executable;
see http://www.atstake.com/research/tools/index.html#network_utilities
-for details. In addition, you will have to modify the value for
-`smtp-end-of-line' to \"\\n\" if you use \"telnet\" instead of \"nc\".")
+for details.")
(defvar smtp-read-point nil)
(defvar smtp-submit-package-function #'smtp-submit-package)
-(defvar smtp-end-of-line "\r\n"
- "*String to use as end-of-line marker when talking to a SMTP server.
-This is \"\\r\\n\" by default, but it may have to be \"\\n\" when using a non
-native connection function. See also `smtp-open-connection-function'.")
-
;;; @ SMTP package
;;; A package contains a mail message, an envelope sender address,
;;; and one or more envelope recipient addresses. In ESMTP model
BUFFER may be a buffer or a buffer name which contains mail message."
(if smtp-send-by-myself
(smtp-send-buffer-by-myself sender recipients buffer)
- (let ((server
- (if (functionp smtp-server)
- (funcall smtp-server sender recipients)
- smtp-server))
- (package
- (smtp-make-package sender recipients buffer))
- (smtp-open-connection-function
- (if smtp-use-starttls
- #'starttls-open-stream
- smtp-open-connection-function)))
+ (let* ((server
+ (if (functionp smtp-server)
+ (funcall smtp-server sender recipients)
+ (or smtp-server
+ (error "`smtp-server' not defined"))))
+ (package
+ (smtp-make-package sender recipients buffer))
+ (starttls-program smtp-starttls-program)
+ (starttls-extra-args smtp-starttls-extra-args)
+ (smtp-open-connection-function
+ (if smtp-use-starttls
+ #'starttls-open-stream
+ smtp-open-connection-function)))
(save-excursion
(set-buffer
(get-buffer-create
(smtp-primitive-rcptto package)
(smtp-primitive-data package))
(let ((connection (smtp-find-connection (current-buffer))))
- (when (smtp-connection-opened connection)
- (smtp-primitive-quit package)
+ (when (and connection (smtp-connection-opened connection))
+ (condition-case nil
+ (smtp-primitive-quit package)
+ (smtp-error))
(smtp-close-connection connection)))))
(defun smtp-send-buffer-by-myself (sender recipients buffer)
(let ((smtp-use-sasl nil)
(smtp-use-starttls-ignore-error t))
(funcall smtp-submit-package-function package)))
- (setq servers (cdr servers)))))
+ (setq servers (cdr servers)))))
;;; @ hook methods for `smtp-submit-package'
;;;
;; SIZE --- Message Size Declaration (RFC1870)
(if (and smtp-use-size
(assq 'size extensions))
- (setq extension (format "SIZE=%d" (smtp-package-buffer-internal-size package))))
+ (setq extension (format " SIZE=%d" (smtp-package-buffer-internal-size package))))
;; 8BITMIME --- 8bit-MIMEtransport (RFC1652)
(if (and smtp-use-8bitmime
(assq '8bitmime extensions))
(smtp-send-command
connection
(if extension
- (format "MAIL FROM:<%s> %s" sender extension)
+ (format "MAIL FROM:<%s>%s" sender extension)
(format "MAIL FROM:<%s>" sender)))
(setq response (smtp-read-response connection))
(if (/= (car response) 250)
response)
(while response-continue
(goto-char smtp-read-point)
- (while (not (search-forward smtp-end-of-line nil t))
+ (while (not (re-search-forward "\r?\n" nil t))
+ (unless (smtp-connection-opened connection)
+ (signal 'smtp-error "Connection closed"))
(accept-process-output (smtp-connection-process-internal connection))
(goto-char smtp-read-point))
- (if decoder
- (let ((string (buffer-substring smtp-read-point (- (point) 2))))
- (delete-region smtp-read-point (point))
- (insert (funcall decoder string) smtp-end-of-line)))
- (setq response
- (nconc response
- (list (buffer-substring
- (+ 4 smtp-read-point)
- (- (point) 2)))))
- (goto-char
- (prog1 smtp-read-point
- (setq smtp-read-point (point))))
- (if (looking-at "[1-5][0-9][0-9] ")
- (setq response (cons (read (point-marker)) response)
- response-continue nil)))
+ (let ((bol smtp-read-point)
+ (eol (match-beginning 0)))
+ (when decoder
+ (let ((string (buffer-substring bol eol)))
+ (delete-region bol (point))
+ (insert (funcall decoder string))
+ (setq eol (point))
+ (insert "\r\n")))
+ (setq smtp-read-point (point))
+ (goto-char bol)
+ (cond
+ ((looking-at "[1-5][0-9][0-9]\\([ -]\\)")
+ (setq response
+ (nconc response
+ (list (buffer-substring (match-end 0) eol))))
+ (when (string= (match-string 1) " ")
+ (setq response (cons (read (point-marker)) response)
+ response-continue nil)))
+ (smtp-debug
+ (message "Invalid response: %s" (buffer-substring bol eol))))))
response))
(defun smtp-send-command (connection command)
(smtp-connection-encoder-internal connection)))
(set-buffer (process-buffer process))
(goto-char (point-max))
- (setq command (concat command smtp-end-of-line))
+ (setq command (concat command "\r\n"))
(insert command)
(setq smtp-read-point (point))
(if encoder
(smtp-connection-encoder-internal connection)))
;; Escape "." at start of a line.
(if (eq (string-to-char data) ?.)
- (setq data (concat "." data smtp-end-of-line))
- (setq data (concat data smtp-end-of-line)))
+ (setq data (concat "." data "\r\n"))
+ (setq data (concat data "\r\n")))
(if encoder
(setq data (funcall encoder data)))
(process-send-string process data)))
(mail-strip-quoted-names
(buffer-substring this-line this-line-end)))))
(erase-buffer)
- (insert-string " ")
- (insert-string simple-address-list)
- (insert-string "\n")
+ (insert " " simple-address-list "\n")
;; newline --> blank
(subst-char-in-region (point-min) (point-max) 10 ? t)
;; comma --> blank