diff options
| -rw-r--r-- | lisp/mail/mailalias.el | 93 |
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) |