aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lisp/mail/mailalias.el93
1 files changed, 57 insertions, 36 deletions
diff --git a/lisp/mail/mailalias.el b/lisp/mail/mailalias.el
index 0ccb1b4d939..685b992ab13 100644
--- a/lisp/mail/mailalias.el
+++ b/lisp/mail/mailalias.el
@@ -302,6 +302,7 @@ By default, this is the file specified by `mail-personal-alias-file'."
302 302
303;; Always autoloadable in case the user wants to define aliases 303;; Always autoloadable in case the user wants to define aliases
304;; interactively or in .emacs. 304;; interactively or in .emacs.
305;; define-mail-abbrev in mailabbrev.el duplicates much of this code.
305;;;###autoload 306;;;###autoload
306(defun define-mail-alias (name definition &optional from-mailrc-file) 307(defun define-mail-alias (name definition &optional from-mailrc-file)
307 "Define NAME as a mail alias that translates to DEFINITION. 308 "Define NAME as a mail alias that translates to DEFINITION.
@@ -327,44 +328,64 @@ if it is quoted with double-quotes."
327 (setq definition (substring definition (match-end 0)))) 328 (setq definition (substring definition (match-end 0))))
328 (if (string-match "[ \t\n,]+\\'" definition) 329 (if (string-match "[ \t\n,]+\\'" definition)
329 (setq definition (substring definition 0 (match-beginning 0)))) 330 (setq definition (substring definition 0 (match-beginning 0))))
330 (let ((result '()) 331
331 ;; If DEFINITION is null string, avoid looping even once. 332 (let* ((L (length definition))
332 (start (and (not (equal definition "")) 0)) 333 (start (if (> L 0) 0))
333 (L (length definition)) 334 end this-entry result tem)
334 convert-backslash
335 end tem)
336 (while start 335 (while start
337 (setq convert-backslash nil) 336 (cond
338 ;; If we're reading from the mailrc file, then addresses are delimited 337 (from-mailrc-file
339 ;; by spaces, and addresses with embedded spaces must be surrounded by 338 ;; If we're reading from the mailrc file, addresses are
340 ;; double-quotes. Otherwise, addresses are separated by commas. 339 ;; delimited by spaces, and addresses with embedded spaces are
341 (if from-mailrc-file 340 ;; surrounded by non-escaped double-quotes.
342 (if (eq ?\" (aref definition start)) 341 (if (eq ?\" (aref definition start))
343 ;; The following test on `found' compensates for a bug 342 (setq start (1+ start)
344 ;; in match-end, which does not return nil when match 343 end (and (string-match
345 ;; failed. 344 "[^\\]\\(\\([\\][\\]\\)*\\)\"[ \t,]*"
346 (let ((found (string-match "[^\\]\\(\\([\\][\\]\\)*\\)\"[ \t,]*" 345 definition start)
347 definition start))) 346 (match-end 1)))
348 (setq start (1+ start) 347 (setq end (string-match "[ \t,]+" definition start)))
349 end (and found (match-end 1)) 348 ;; Extract the address and advance the loop past it.
350 convert-backslash t)) 349 (setq this-entry (substring definition start end)
351 (setq end (string-match "[ \t,]+" definition start))) 350 start (and end (/= (match-end 0) L) (match-end 0)))
352 (setq end (string-match "[ \t\n,]*,[ \t\n,]*" definition start))) 351 ;; If the full name contains a problem character, quote it.
353 (let ((temp (substring definition start end)) 352 (and (string-match "\\(.+?\\)[ \t]*\\(<.*>\\)" this-entry)
354 (pos 0)) 353 (string-match "[^- !#$%&'*+/0-9=?A-Za-z^_`{|}~]"
355 (setq start (and end 354 (match-string 1 this-entry))
356 (/= (match-end 0) L) 355 (setq this-entry (replace-regexp-in-string
357 (match-end 0))) 356 "\\(.+?\\)[ \t]*\\(<.*>\\)"
358 (if convert-backslash 357 "\"\\1\" \\2"
359 (while (string-match "[\\]" temp pos) 358 this-entry))))
360 (setq temp (replace-match "" t t temp)) 359 ;; When we are not reading from .mailrc, addresses are
361 (if start 360 ;; separated by commas. Try to accept a rfc822-like syntax.
362 (setq start (1- start))) 361 ;; (Todo: extend rfc822.el to do the work for us.)
363 (setq pos (match-end 0)))) 362 ((equal (string-match
364 (setq result (cons temp result)))) 363 "[ \t,]*\\(\"\\(?:[^\"]\\|[^\\]\\(?:[\\][\\]\\)*\"\\)*\"[ \t]*\
364<[-.!#$%&'*+/0-9=?A-Za-z^_`{|}~@]+>\\)[ \t,]*"
365 definition start)
366 start)
367 ;; If an entry has a valid [ "foo bar" <foo@example.com> ]
368 ;; form, use it literally . This also allows commas in the
369 ;; quoted string, e.g. [ "foo bar, jr" <foo@example.com> ]
370 (setq this-entry (match-string 1 definition)
371 start (and (/= (match-end 0) L) (match-end 0))))
372 (t
373 ;; Otherwise, read the next address by looking for a comma.
374 (setq end (string-match "[ \t\n,]*,[ \t\n]*" definition start))
375 (setq this-entry (substring definition start end))
376 ;; Advance the loop past this address.
377 (setq start (and end (/= (match-end 0) L) (match-end 0)))
378 ;; If the full name contains a problem character, quote it.
379 (and (string-match "\\(.+?\\)[ \t]*\\(<.*>\\)" this-entry)
380 (string-match "[^- !#$%&'*+/0-9=?A-Za-z^_`{|}~]"
381 (match-string 1 this-entry))
382 (setq this-entry (replace-regexp-in-string
383 "\\(.+?\\)[ \t]*\\(<.*>\\)" "\"\\1\" \\2"
384 this-entry)))))
385 (push this-entry result))
386
365 (setq definition (mapconcat (function identity) 387 (setq definition (mapconcat (function identity)
366 (nreverse result) 388 (nreverse result) ", "))
367 ", "))
368 (setq tem (assoc name mail-aliases)) 389 (setq tem (assoc name mail-aliases))
369 (if tem 390 (if tem
370 (rplacd tem definition) 391 (rplacd tem definition)