Update FSF's address.
[bpt/emacs.git] / lisp / mail / mailalias.el
index 09335af..ce1cbf3 100644 (file)
@@ -18,8 +18,9 @@
 ;; GNU General Public License for more details.
 
 ;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING.  If not, write to
-;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
 
 ;;; Commentary:
 
 
 ;;; Code:
 
-(defvar mail-aliases t
-  "Alias of mail address aliases,
-or t meaning should be initialized from `~/.mailrc'.")
+(require 'sendmail)
 
 ;; Called from sendmail-send-it, or similar functions,
 ;; only if some mail aliases are defined.
 (defun expand-mail-aliases (beg end &optional exclude)
   "Expand all mail aliases in suitable header fields found between BEG and END.
-Suitable header fields are `To', `Cc' and `Bcc' and their `Resent-' variants.
+Suitable header fields are `To', `From', `CC' and `BCC', `Reply-to', and
+their `Resent-' variants.
+
 Optional second arg EXCLUDE may be a regular expression defining text to be
 removed from alias expansions."
+  (sendmail-sync-aliases)
   (if (eq mail-aliases t)
       (progn (setq mail-aliases nil) (build-mail-aliases)))
   (goto-char beg)
   (setq end (set-marker (make-marker) end))
   (let ((case-fold-search nil))
     (while (let ((case-fold-search t))
-            (re-search-forward "^\\(to\\|cc\\|bcc\\|resent-to\\|resent-cc\\|resent-bcc\\):" end t))
+            (re-search-forward "^\\(Resent-\\)?\\(To\\|From\\|CC\\|BCC\\|Reply-to\\):" end t))
       (skip-chars-forward " \t")
       (let ((beg1 (point))
            end1 pos epos seplen
@@ -74,7 +76,7 @@ removed from alias expansions."
                    seplen (- (point) epos))
            (setq epos (marker-position end1) seplen 0))
          (let (translation
-               (string (buffer-substring pos epos)))
+               (string (buffer-substring-no-properties pos epos)))
            (if (and (not (assoc string disabled-aliases))
                     (setq translation
                           (cdr (assoc string mail-aliases))))
@@ -102,10 +104,12 @@ removed from alias expansions."
        (set-marker end1 nil)))
     (set-marker end nil)))
 
-;; Called by mail-setup, or similar functions, only if ~/.mailrc exists.
+;; Called by mail-setup, or similar functions, only if the file specified
+;; by mail-personal-alias-file (usually `~/.mailrc') exists.
 (defun build-mail-aliases (&optional file)
-  "Read mail aliases from `~/.mailrc' and set `mail-aliases'."
-  (setq file (expand-file-name (or file (or (getenv "MAILRC") "~/.mailrc"))))
+  "Read mail aliases from personal aliases file and set `mail-aliases'.
+By default, this is the file specified by `mail-personal-alias-file'."
+  (setq file (expand-file-name (or file mail-personal-alias-file)))
   (let ((buffer nil)
        (obuf (current-buffer)))
     (unwind-protect
@@ -117,7 +121,8 @@ removed from alias expansions."
            (cond ((get-file-buffer file)
                   (insert (save-excursion
                             (set-buffer (get-file-buffer file))
-                            (buffer-substring (point-min) (point-max)))))
+                            (buffer-substring-no-properties
+                             (point-min) (point-max)))))
                  ((file-exists-p file) (insert-file-contents file))
                  ((file-exists-p (setq file (concat "~/" file)))
                   (insert-file-contents file))
@@ -136,22 +141,22 @@ removed from alias expansions."
            ;; handle `source' directives -- Eddy/1994/May/25
            (cond ((re-search-forward "^source[ \t]+" nil t)
                   (re-search-forward "\\S-+")
-                  (setq file
-                        (buffer-substring (match-beginning 0) (match-end 0)))
+                  (setq file (buffer-substring-no-properties
+                              (match-beginning 0) (match-end 0)))
                   (beginning-of-line)
                   (insert "# ") ; to ensure we don't re-process this file
                   (beginning-of-line))
                  (t (setq file nil))))
          (goto-char (point-min))
-         (while (or (re-search-forward "^a\\(lias\\|\\)[ \t]+" nil t)
-                    (re-search-forward "^g\\(roup\\|\\)[ \t]+" nil t))
-           (re-search-forward "[^ \t]+")
-           (let* ((name (buffer-substring (match-beginning 0) (match-end 0)))
+         (while (re-search-forward
+                 "^\\(a\\|alias\\|g\\|group\\)[ \t]+\\([^ \t]+\\)" nil t)
+           (let* ((name (match-string 2))
                   (start (progn (skip-chars-forward " \t") (point))))
              (end-of-line)
              (define-mail-alias
                name
-               (buffer-substring start (point)))))
+               (buffer-substring-no-properties start (point))
+               t)))
          mail-aliases)
       (if buffer (kill-buffer buffer))
       (set-buffer obuf))))
@@ -159,38 +164,50 @@ removed from alias expansions."
 ;; Always autoloadable in case the user wants to define aliases
 ;; interactively or in .emacs.
 ;;;###autoload
-(defun define-mail-alias (name definition)
+(defun define-mail-alias (name definition &optional from-mailrc-file)
   "Define NAME as a mail alias that translates to DEFINITION.
 This means that sending a message to NAME will actually send to DEFINITION.
-DEFINITION can be one or more mail addresses separated by commas."
+
+Normally, the addresses in DEFINITION must be separated by commas.
+If FROM-MAILRC-FILE is non-nil, then addresses in DEFINITION 
+can be separated by spaces; an address can contain spaces
+if it is quoted with double-quotes."
+
   (interactive "sDefine mail alias: \nsDefine %s as mail alias for: ")
   ;; Read the defaults first, if we have not done so.
+  (sendmail-sync-aliases)
   (if (eq mail-aliases t)
       (progn
        (setq mail-aliases nil)
-       (if (file-exists-p "~/.mailrc")
+       (if (file-exists-p mail-personal-alias-file)
            (build-mail-aliases))))
   ;; strip garbage from front and end
   (if (string-match "\\`[ \t\n,]+" definition)
       (setq definition (substring definition (match-end 0))))
   (if (string-match "[ \t\n,]+\\'" definition)
       (setq definition (substring definition 0 (match-beginning 0))))
-  (let ((first (aref definition 0))
-       (last (aref definition (1- (length definition))))
-       tem)
-    (if (and (= first last) (memq first '(?\' ?\")))
-       ;; Strip quotation marks.
-       (setq definition (substring definition 1 (1- (length definition))))
-      ;; ~/.mailrc contains addresses separated by spaces.
-      ;; mailers should expect addresses separated by commas.
-      (while (setq tem (string-match "[^ \t,][ \t,]+" definition tem))
-       (if (= (match-end 0) (length definition))
-           (setq definition (substring definition 0 (1+ tem)))
-         (setq definition (concat (substring definition
-                                             0 (1+ tem))
-                                  ", "
-                                  (substring definition (match-end 0))))
-         (setq tem (+ 3 tem)))))
+  (let ((result '())
+       ;; If DEFINITION is null string, avoid looping even once.
+       (start (and (not (equal definition "")) 0))
+       (L (length definition))
+       end tem)
+    (while start
+      ;; If we're reading from the mailrc file, then addresses are delimited
+      ;; by spaces, and addresses with embedded spaces must be surrounded by
+      ;; double-quotes.  Otherwise, addresses are separated by commas.
+      (if from-mailrc-file
+         (if (eq ?\" (aref definition start))
+             (setq start (1+ start)
+                   end (string-match "\"[ \t,]*" definition start))
+           (setq end (string-match "[ \t,]+" definition start)))
+       (setq end (string-match "[ \t\n,]*,[ \t\n,]*" definition start)))
+      (setq result (cons (substring definition start end) result))
+      (setq start (and end
+                      (/= (match-end 0) L)
+                      (match-end 0))))
+    (setq definition (mapconcat (function identity)
+                               (nreverse result)
+                               ", "))
     (setq tem (assoc name mail-aliases))
     (if tem
        (rplacd tem definition)