;;; smtp.el --- basic functions to send mail with SMTP server
-;; Copyright (C) 1995, 1996, 1998, 1999 Free Software Foundation, Inc.
+;; Copyright (C) 1995, 1996, 1998, 1999, 2000 Free Software Foundation, Inc.
;; Author: Tomoji Kagatani <kagatani@rbc.ncl.omron.co.jp>
;; Simon Leinen <simon@switch.ch> (ESMTP support)
;;; Commentary:
-;;
+;;
;;; Code:
-(require 'pces)
(require 'custom)
(require 'mail-utils) ; mail-strip-quoted-names
(require 'sasl)
(require 'luna)
+(require 'mel) ; binary-funcall
(defgroup smtp nil
"SMTP protocol for sending mail."
(defcustom smtp-service "smtp"
"SMTP service port number. \"smtp\" or 25."
:type '(choice (integer :tag "25" 25)
- (string :tag "smtp" "smtp"))
+ (string :tag "smtp" "smtp"))
:group 'smtp)
(defcustom smtp-local-domain nil
:group 'smtp-extensions)
(defvar sasl-mechanisms)
-
-(defvar smtp-open-connection-function #'open-network-stream)
+
+;;;###autoload
+(defvar smtp-open-connection-function #'open-network-stream
+ "*Function used for connecting to a SMTP server.
+The function will be called with the same four arguments as
+`open-network-stream' and should return a process object.
+Here is an example:
+
+\(setq smtp-open-connection-function
+ #'(lambda (name buffer host service)
+ (let ((process-connection-type nil))
+ (start-process name buffer \"ssh\" \"-C\" host
+ \"nc\" host service))))
+
+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\".")
(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
Return a newly allocated connection-object.
BUFFER is the buffer to associate with the connection. SERVER is name
of the host to connect to. SERVICE is name of the service desired."
- (let* ((coding-system-for-read 'binary)
- (coding-system-for-write 'binary)
- (process
- (funcall smtp-open-connection-function
- "SMTP" buffer server service))
- connection)
+ (let ((process
+ (binary-funcall smtp-open-connection-function
+ "SMTP" buffer server service))
+ connection)
(when process
(setq connection (smtp-make-connection process server service))
(set-process-filter process 'smtp-process-filter)
;;;###autoload
(defun smtp-via-smtp (sender recipients buffer)
+ "Like `smtp-send-buffer', but sucks in any errors."
(condition-case nil
(progn
(smtp-send-buffer sender recipients buffer)
;;;###autoload
(defun smtp-send-buffer (sender recipients buffer)
+ "Send a message.
+SENDER is an envelope sender address.
+RECIPIENTS is a list of envelope recipient addresses.
+BUFFER may be a buffer or a buffer name which contains mail message."
(let ((server
(if (functionp smtp-server)
(funcall smtp-server sender recipients)
(smtp-response-error
(smtp-primitive-helo package)))
(if smtp-use-starttls
- (smtp-primitive-starttls package))
+ (progn
+ (smtp-primitive-starttls package)
+ (smtp-primitive-ehlo package)))
(if smtp-use-sasl
(smtp-primitive-auth package))
(smtp-primitive-mailfrom package)
response)
(while response-continue
(goto-char smtp-read-point)
- (while (not (search-forward "\r\n" nil t))
+ (while (not (search-forward smtp-end-of-line nil t))
(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) "\r\n")))
+ (insert (funcall decoder string) smtp-end-of-line)))
(setq response
(nconc response
(list (buffer-substring
(smtp-connection-encoder-internal connection)))
(set-buffer (process-buffer process))
(goto-char (point-max))
- (setq command (concat command "\r\n"))
+ (setq command (concat command smtp-end-of-line))
(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 "\r\n"))
- (setq data (concat data "\r\n")))
+ (setq data (concat "." data smtp-end-of-line))
+ (setq data (concat data smtp-end-of-line)))
(if encoder
(setq data (funcall encoder data)))
(process-send-string process data)))