;;; mail-utils.el --- utility functions used both by rmail and rnews
-;; Copyright (C) 1985, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
-;; 2009, 2010, 2011 Free Software Foundation, Inc.
+;; Copyright (C) 1985, 2001-2016 Free Software Foundation, Inc.
-;; Maintainer: FSF
+;; Maintainer: emacs-devel@gnu.org
;; Keywords: mail, news
;; This file is part of GNU Emacs.
:type 'boolean
:group 'mail)
+;;;###autoload
+(defcustom mail-dont-reply-to-names nil
+ "Regexp specifying addresses to prune from a reply message.
+If this is nil, it is set the first time you compose a reply, to
+a value which excludes your own email address.
+
+Matching addresses are excluded from the CC field in replies, and
+also the To field, unless this would leave an empty To field."
+ :type '(choice regexp (const :tag "Your Name" nil))
+ :group 'mail)
+
;; Returns t if file FILE is an Rmail file.
;;;###autoload
(defun mail-file-babyl-p (file)
"Return non-nil if FILE is a Babyl file."
- (with-temp-buffer
- (insert-file-contents file nil 0 100)
- (looking-at "BABYL OPTIONS:")))
+ (let ((epa-inhibit t))
+ (with-temp-buffer
+ (insert-file-contents file nil 0 100)
+ (looking-at "BABYL OPTIONS:"))))
(defun mail-string-delete (string start end)
"Returns a string containing all of STRING except the part
;;;###autoload
(defun mail-quote-printable (string &optional wrapper)
- "Convert a string to the \"quoted printable\" Q encoding.
+ "Convert a string to the \"quoted printable\" Q encoding if necessary.
+If the string contains only ASCII characters and no troublesome ones,
+we return it unconverted.
+
If the optional argument WRAPPER is non-nil,
we add the wrapper characters =?ISO-8859-1?Q?....?=."
(let ((i 0) (result ""))
(save-match-data
- (while (string-match "[?=\"\200-\377]" string i)
+ (while (or (string-match "[?=\"]" string i)
+ (string-match "[^\000-\177]" string i))
(setq result
(concat result (substring string i (match-beginning 0))
(upcase (format "=%02x"
(error "Malformed MIME quoted-printable message"))))
(not failed))))))
-(eval-when-compile (require 'rfc822))
+(autoload 'rfc822-addresses "rfc822")
(defun mail-strip-quoted-names (address)
"Delete comments and quoted strings in an address list ADDRESS.
Also delete leading/trailing whitespace and replace FOO <BAR> with just BAR.
Return a modified address list."
- (if (null address)
- nil
+ (when address
(if mail-use-rfc822
- (progn (require 'rfc822)
- (mapconcat 'identity (rfc822-addresses address) ", "))
+ (mapconcat 'identity (rfc822-addresses address) ", ")
(let (pos)
- ;; Detect nested comments.
- (if (string-match "[ \t]*(\\([^)\\]\\|\\\\.\\|\\\\\n\\)*(" address)
- ;; Strip nested comments.
- (with-temp-buffer
- (insert address)
- (set-syntax-table lisp-mode-syntax-table)
- (goto-char 1)
- (while (search-forward "(" nil t)
- (forward-char -1)
- (skip-chars-backward " \t")
- (delete-region (point)
- (save-excursion
- (condition-case ()
- (forward-sexp 1)
- (error (goto-char (point-max))))
- (point))))
- (setq address (buffer-string)))
- ;; Strip non-nested comments an easier way.
- (while (setq pos (string-match
- ;; This doesn't hack rfc822 nested comments
- ;; `(xyzzy (foo) whinge)' properly. Big deal.
- "[ \t]*(\\([^)\\]\\|\\\\.\\|\\\\\n\\)*)"
- address))
- (setq address (replace-match "" nil nil address 0))))
-
- ;; strip surrounding whitespace
- (string-match "\\`[ \t\n]*" address)
- (setq address (substring address
- (match-end 0)
- (string-match "[ \t\n]*\\'" address
- (match-end 0))))
-
- ;; strip `quoted' names (This is supposed to hack `"Foo Bar" <bar@host>')
- (setq pos 0)
- (while (setq pos (string-match
+ ;; Strip comments.
+ (while (setq pos (string-match
+ "[ \t]*(\\([^()\\]\\|\\\\.\\|\\\\\n\\)*)"
+ address))
+ (setq address (replace-match "" nil nil address 0)))
+
+ ;; strip surrounding whitespace
+ (string-match "\\`[ \t\n]*" address)
+ (setq address (substring address
+ (match-end 0)
+ (string-match "[ \t\n]*\\'" address
+ (match-end 0))))
+
+ ;; strip `quoted' names (This is supposed to hack `"Foo Bar" <bar@host>')
+ (setq pos 0)
+ (while (setq pos (string-match
"\\([ \t]?\\)\\([ \t]*\"\\([^\"\\]\\|\\\\.\\|\\\\\n\\)*\"[ \t\n]*\\)"
address pos))
- ;; If the next thing is "@", we have "foo bar"@host. Leave it.
- (if (and (> (length address) (match-end 0))
- (= (aref address (match-end 0)) ?@))
- (setq pos (match-end 0))
- ;; Otherwise discard the "..." part.
- (setq address (replace-match "" nil nil address 2))))
- ;; If this address contains <...>, replace it with just
- ;; the part between the <...>.
- (while (setq pos (string-match "\\(,\\s-*\\|\\`\\)\\([^,]*<\\([^>,:]*\\)>[^,]*\\)\\(\\s-*,\\|\\'\\)"
- address))
- (setq address (replace-match (match-string 3 address)
- nil 'literal address 2)))
- address))))
-
-;; The following piece of ugliness is legacy code. The name was an
-;; unfortunate choice --- a flagrant violation of the Emacs Lisp
-;; coding conventions. `mail-dont-reply-to' would have been
-;; infinitely better. Also, `rmail-dont-reply-to-names' might have
-;; been better named `mail-dont-reply-to-names' and sourced from this
-;; file instead of in rmail.el. Yuck. -pmr
-(defun rmail-dont-reply-to (destinations)
+ ;; If the next thing is "@", we have "foo bar"@host. Leave it.
+ (if (and (> (length address) (match-end 0))
+ (= (aref address (match-end 0)) ?@))
+ (setq pos (match-end 0))
+ ;; Otherwise discard the "..." part.
+ (setq address (replace-match "" nil nil address 2))))
+ ;; If this address contains <...>, replace it with just
+ ;; the part between the <...>.
+ (while (setq pos (string-match "\\(,\\s-*\\|\\`\\)\\([^,]*<\\([^>,:]*\\)>[^,]*\\)\\(\\s-*,\\|\\'\\)"
+ address))
+ (setq address (replace-match (match-string 3 address)
+ nil 'literal address 2)))
+ address))))
+
+(defun mail-dont-reply-to (destinations)
"Prune addresses from DESTINATIONS, a list of recipient addresses.
-All addresses matching `rmail-dont-reply-to-names' are removed from
-the comma-separated list. The pruned list is returned."
+Remove all addresses matching `mail-dont-reply-to-names' from the
+comma-separated list, and return the pruned list."
;; FIXME this (setting a user option the first time a command is used)
;; is somewhat strange. Normally one would never set the option,
;; but instead fall back to the default so long as it was nil.
;; Or just set the default directly in the defcustom.
- (if (null rmail-dont-reply-to-names)
- (setq rmail-dont-reply-to-names
- (concat (if rmail-default-dont-reply-to-names
- (concat rmail-default-dont-reply-to-names "\\|")
- "")
- (if (and user-mail-address
- (not (equal user-mail-address user-login-name)))
- ;; Anchor the login name and email address so
- ;; that we don't match substrings: if the
- ;; login name is "foo", we shouldn't match
- ;; "barfoo@baz.com".
- (concat "\\`"
- (regexp-quote user-mail-address)
- "\\'\\|")
- "")
- (concat "\\`" (regexp-quote user-login-name) "@"))))
+ (if (null mail-dont-reply-to-names)
+ (setq mail-dont-reply-to-names
+ (concat
+ ;; `rmail-default-dont-reply-to-names' is obsolete.
+ (if (bound-and-true-p rmail-default-dont-reply-to-names)
+ (concat rmail-default-dont-reply-to-names "\\|")
+ "")
+ (if (and user-mail-address
+ (not (equal user-mail-address user-login-name)))
+ ;; Anchor the login name and email address so that we
+ ;; don't match substrings: if the login name is
+ ;; "foo", we shouldn't match "barfoo@baz.com".
+ (concat "\\`"
+ (regexp-quote user-mail-address)
+ "\\'\\|")
+ "")
+ (concat "\\`" (regexp-quote user-login-name) "@"))))
;; Split up DESTINATIONS and match each element separately.
(let ((start-pos 0) (cur-pos 0)
(case-fold-search t))
(setq cur-pos start-pos)))
(let* ((address (substring destinations start-pos cur-pos))
(naked-address (mail-strip-quoted-names address)))
- (if (string-match rmail-dont-reply-to-names naked-address)
+ (if (string-match mail-dont-reply-to-names naked-address)
(setq destinations (concat (substring destinations 0 start-pos)
(and cur-pos (substring destinations
(1+ cur-pos))))
(substring destinations (match-end 0))
destinations))
+;; Legacy name
+(define-obsolete-function-alias 'rmail-dont-reply-to 'mail-dont-reply-to "24.1")
+
\f
;;;###autoload
(defun mail-fetch-field (field-name &optional last all list)