2001-07-16 12:23:00 +00:00
|
|
|
;;; mailheader.el --- mail header parsing, merging, formatting
|
1996-06-25 22:35:26 +00:00
|
|
|
|
2012-01-05 09:46:05 +00:00
|
|
|
;; Copyright (C) 1996, 2001-2012 Free Software Foundation, Inc.
|
1996-06-25 22:35:26 +00:00
|
|
|
|
2000-07-19 11:04:18 +00:00
|
|
|
;; Author: Erik Naggum <erik@naggum.no>
|
1996-06-25 22:35:26 +00:00
|
|
|
;; Keywords: tools, mail, news
|
2010-08-29 16:17:13 +00:00
|
|
|
;; Package: mail-utils
|
1996-06-25 22:35:26 +00:00
|
|
|
|
|
|
|
;; This file is part of GNU Emacs.
|
|
|
|
|
2008-05-06 07:25:26 +00:00
|
|
|
;; GNU Emacs is free software: you can redistribute it and/or modify
|
1996-06-25 22:35:26 +00:00
|
|
|
;; it under the terms of the GNU General Public License as published by
|
2008-05-06 07:25:26 +00:00
|
|
|
;; the Free Software Foundation, either version 3 of the License, or
|
|
|
|
;; (at your option) any later version.
|
1996-06-25 22:35:26 +00:00
|
|
|
|
|
|
|
;; GNU Emacs is distributed in the hope that it will be useful,
|
|
|
|
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
;; GNU General Public License for more details.
|
|
|
|
|
|
|
|
;; You should have received a copy of the GNU General Public License
|
2008-05-06 07:25:26 +00:00
|
|
|
;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
|
1996-06-25 22:35:26 +00:00
|
|
|
|
|
|
|
;;; Commentary:
|
|
|
|
|
|
|
|
;; This package provides an abstraction to RFC822-style messages, used in
|
1996-07-02 00:01:05 +00:00
|
|
|
;; mail, news, and some other systems. The simple syntactic rules for such
|
1996-06-25 22:35:26 +00:00
|
|
|
;; headers, such as quoting and line folding, are routinely reimplemented
|
|
|
|
;; in many individual packages. This package removes the need for this
|
|
|
|
;; redundancy by representing message headers as association lists,
|
|
|
|
;; offering functions to extract the set of headers from a message, to
|
|
|
|
;; parse individual headers, to merge sets of headers, and to format a set
|
|
|
|
;; of headers.
|
|
|
|
|
|
|
|
;; The car of each element in the message-header alist is a symbol whose
|
|
|
|
;; print name is the name of the header, in all lower-case. The cdr of an
|
|
|
|
;; element depends on the operation. After extracting headers from a
|
2000-11-12 00:21:13 +00:00
|
|
|
;; message, it is a string, the value of the header. An extracted set of
|
1996-06-25 22:35:26 +00:00
|
|
|
;; headers may be parsed further, which may turn it into a list, whose car
|
|
|
|
;; is the original value and whose subsequent elements depend on the
|
|
|
|
;; header. For formatting, it is evaluated to obtain the strings to be
|
|
|
|
;; inserted. For merging, one set of headers consists of strings, while
|
|
|
|
;; the other set will be evaluated with the symbols in the first set of
|
|
|
|
;; headers bound to their respective values.
|
|
|
|
|
|
|
|
;;; Code:
|
|
|
|
|
|
|
|
(defun mail-header-extract ()
|
|
|
|
"Extract headers from current buffer after point.
|
|
|
|
Returns a header alist, where each element is a cons cell (name . value),
|
|
|
|
where NAME is a symbol, and VALUE is the string value of the header having
|
|
|
|
that name."
|
|
|
|
(let ((message-headers ()) (top (point))
|
|
|
|
start end)
|
|
|
|
(while (and (setq start (point))
|
|
|
|
(> (skip-chars-forward "^\0- :") 0)
|
|
|
|
(= (following-char) ?:)
|
|
|
|
(setq end (point))
|
1999-10-22 16:44:37 +00:00
|
|
|
(progn (forward-char)
|
1996-06-25 22:35:26 +00:00
|
|
|
(> (skip-chars-forward " \t") 0)))
|
|
|
|
(let ((header (intern (downcase (buffer-substring start end))))
|
|
|
|
(value (list (buffer-substring
|
|
|
|
(point) (progn (end-of-line) (point))))))
|
|
|
|
(while (progn (forward-char) (> (skip-chars-forward " \t") 0))
|
|
|
|
(push (buffer-substring (point) (progn (end-of-line) (point)))
|
|
|
|
value))
|
|
|
|
(push (if (cdr value)
|
|
|
|
(cons header (mapconcat #'identity (nreverse value) " "))
|
|
|
|
(cons header (car value)))
|
|
|
|
message-headers)))
|
|
|
|
(goto-char top)
|
|
|
|
(nreverse message-headers)))
|
|
|
|
|
|
|
|
(defun mail-header-extract-no-properties ()
|
|
|
|
"Extract headers from current buffer after point, without properties.
|
|
|
|
Returns a header alist, where each element is a cons cell (name . value),
|
|
|
|
where NAME is a symbol, and VALUE is the string value of the header having
|
|
|
|
that name."
|
|
|
|
(mapcar
|
|
|
|
(lambda (elt)
|
|
|
|
(set-text-properties 0 (length (cdr elt)) nil (cdr elt))
|
|
|
|
elt)
|
|
|
|
(mail-header-extract)))
|
|
|
|
|
|
|
|
(defun mail-header-parse (parsing-rules headers)
|
|
|
|
"Apply PARSING-RULES to HEADERS.
|
|
|
|
PARSING-RULES is an alist whose keys are header names (symbols) and whose
|
|
|
|
value is a parsing function. The function takes one argument, a string,
|
|
|
|
and return a list of values, which will destructively replace the value
|
|
|
|
associated with the key in HEADERS, after being prepended with the original
|
|
|
|
value."
|
|
|
|
(dolist (rule parsing-rules)
|
|
|
|
(let ((header (assq (car rule) headers)))
|
|
|
|
(when header
|
|
|
|
(if (consp (cdr header))
|
|
|
|
(setf (cddr header) (funcall (cdr rule) (cadr header)))
|
|
|
|
(setf (cdr header)
|
|
|
|
(cons (cdr header) (funcall (cdr rule) (cdr header))))))))
|
|
|
|
headers)
|
|
|
|
|
2011-02-23 04:27:42 +00:00
|
|
|
;; Advertised part of the interface; see mail-header, mail-header-set.
|
2010-11-11 04:10:38 +00:00
|
|
|
(defvar headers)
|
|
|
|
|
1996-06-25 22:35:26 +00:00
|
|
|
(defsubst mail-header (header &optional header-alist)
|
|
|
|
"Return the value associated with header HEADER in HEADER-ALIST.
|
|
|
|
If the value is a string, it is the original value of the header. If the
|
|
|
|
value is a list, its first element is the original value of the header,
|
1999-10-22 16:44:37 +00:00
|
|
|
with any subsequent elements being the result of parsing the value.
|
1996-06-25 22:35:26 +00:00
|
|
|
If HEADER-ALIST is nil, the dynamically bound variable `headers' is used."
|
More CL cleanups and reduction of use of cl.el.
* woman.el, winner.el, vc/vc-rcs.el, vc/vc-hooks.el, vc/vc-hg.el:
* vc/vc-git.el, vc/vc-dir.el, vc/vc-bzr.el, vc/vc-annotate.el:
* textmodes/tex-mode.el, textmodes/sgml-mode.el, tar-mode.el:
* strokes.el, ses.el, server.el, progmodes/js.el, progmodes/gdb-mi.el:
* progmodes/flymake.el, progmodes/ebrowse.el, progmodes/compile.el:
* play/tetris.el, play/snake.el, play/pong.el, play/landmark.el:
* play/hanoi.el, play/decipher.el, play/5x5.el, nxml/nxml-mode.el:
* net/secrets.el, net/quickurl.el, midnight.el, mail/footnote.el:
* image-dired.el, ibuffer.el, ibuf-macs.el, ibuf-ext.el, hexl.el:
* eshell/eshell.el, eshell/esh-io.el, eshell/esh-ext.el:
* eshell/esh-cmd.el, eshell/em-ls.el, eshell/em-hist.el:
* eshell/em-cmpl.el, eshell/em-banner.el:
* url/url.el, url/url-queue.el, url/url-parse.el, url/url-http.el:
* url/url-future.el, url/url-dav.el, url/url-cookie.el:
* calendar/parse-time.el, test/eshell.el: Use cl-lib.
* wid-browse.el, wdired.el, vc/vc.el, vc/vc-mtn.el, vc/vc-cvs.el:
* vc/vc-arch.el, tree-widget.el, textmodes/texinfo.el:
* textmodes/refill.el, textmodes/css-mode.el, term/tvi970.el:
* term/ns-win.el, term.el, shell.el, ps-samp.el:
* progmodes/perl-mode.el, progmodes/pascal.el, progmodes/gud.el:
* progmodes/glasses.el, progmodes/etags.el, progmodes/cwarn.el:
* play/gamegrid.el, play/bubbles.el, novice.el, notifications.el:
* net/zeroconf.el, net/xesam.el, net/snmp-mode.el, net/mairix.el:
* net/ldap.el, net/eudc.el, net/browse-url.el, man.el:
* mail/mailheader.el, mail/feedmail.el:
* url/url-util.el, url/url-privacy.el, url/url-nfs.el, url/url-misc.el:
* url/url-methods.el, url/url-gw.el, url/url-file.el, url/url-expand.el:
Dont use CL.
* ibuf-ext.el (ibuffer-mark-old-buffers): Use float-time.
* eshell/esh-opt.el (eshell-eval-using-options): Quote code with
`lambda' rather than with `quote'.
(eshell-do-opt): Adjust accordingly.
(eshell-process-option): Simplify.
* eshell/esh-var.el:
* eshell/em-script.el: Require `esh-opt' for eshell-eval-using-options.
* emacs-pcase.el (pcase--dontcare-upats, pcase--let*)
(pcase--expand, pcase--u1): Rename pcase's internal `dontcare' pattern
to `pcase--dontcare'.
* emacs-cl.el (labels): Mark obsolete.
(cl--letf, letf): Move to cl-lib.
(cl--letf*, letf*): Remove.
* emacs-cl-lib.el (cl-nth-value): Use defalias.
* emacs-cl-macs.el (cl-dolist, cl-dotimes): Add indent rule.
(cl-progv): Rewrite.
(cl--letf, cl-letf): Move from cl.el.
(cl-letf*): New macro.
* emacs-cl-extra.el (cl--progv-before, cl--progv-after): Remove.
2012-07-11 23:13:41 +00:00
|
|
|
(declare (gv-setter (lambda (value)
|
|
|
|
`(mail-header-set ,header ,value ,header-alist))))
|
1996-06-25 22:35:26 +00:00
|
|
|
(cdr (assq header (or header-alist headers))))
|
|
|
|
|
|
|
|
(defun mail-header-set (header value &optional header-alist)
|
|
|
|
"Set the value associated with header HEADER to VALUE in HEADER-ALIST.
|
|
|
|
HEADER-ALIST defaults to the dynamically bound variable `headers' if nil.
|
|
|
|
See `mail-header' for the semantics of VALUE."
|
|
|
|
(let* ((alist (or header-alist headers))
|
|
|
|
(entry (assq header alist)))
|
|
|
|
(if entry
|
|
|
|
(setf (cdr entry) value)
|
|
|
|
(nconc alist (list (cons header value)))))
|
|
|
|
value)
|
|
|
|
|
|
|
|
(defun mail-header-merge (merge-rules headers)
|
|
|
|
"Return a new header alist with MERGE-RULES applied to HEADERS.
|
|
|
|
MERGE-RULES is an alist whose keys are header names (symbols) and whose
|
|
|
|
values are forms to evaluate, the results of which are the new headers. It
|
|
|
|
should be a string or a list of string. The first element may be nil to
|
|
|
|
denote that the formatting functions must use the remaining elements, or
|
|
|
|
skip the header altogether if there are no other elements.
|
|
|
|
The macro `mail-header' can be used to access headers in HEADERS."
|
|
|
|
(mapcar
|
|
|
|
(lambda (rule)
|
|
|
|
(cons (car rule) (eval (cdr rule))))
|
|
|
|
merge-rules))
|
|
|
|
|
|
|
|
(defvar mail-header-format-function
|
|
|
|
(lambda (header value)
|
|
|
|
"Function to format headers without a specified formatting function."
|
|
|
|
(insert (capitalize (symbol-name header))
|
|
|
|
": "
|
|
|
|
(if (consp value) (car value) value)
|
2005-11-29 23:54:47 +00:00
|
|
|
"\n")))
|
1996-06-25 22:35:26 +00:00
|
|
|
|
|
|
|
(defun mail-header-format (format-rules headers)
|
|
|
|
"Use FORMAT-RULES to format HEADERS and insert into current buffer.
|
1998-08-01 19:12:59 +00:00
|
|
|
HEADERS should be an alist of the form (HEADER . VALUE),
|
|
|
|
where HEADER is a header field name (a symbol or a string),
|
|
|
|
and VALUE is the contents for that header field.
|
|
|
|
|
|
|
|
FORMAT-RULES is an alist of elements (HEADER . FUNCTION) Here HEADER
|
|
|
|
is a header field name (a symbol), and FUNCTION is how to format that
|
|
|
|
header field, if it appears in HEADERS. Each FUNCTION should take two
|
|
|
|
arguments: the header symbol, and the value of that header. The value
|
|
|
|
returned by FUNCTION is inserted in the buffer unless it is nil.
|
|
|
|
|
|
|
|
If the function for a header field is nil, or if no function is
|
|
|
|
specified for a particular header field, the default action is to
|
|
|
|
insert the value of the header, unless it is nil.
|
|
|
|
|
1996-06-25 22:35:26 +00:00
|
|
|
The headers are inserted in the order of the FORMAT-RULES.
|
1999-10-22 16:44:37 +00:00
|
|
|
A key of t in FORMAT-RULES represents any otherwise unmentioned headers.
|
1996-06-25 22:35:26 +00:00
|
|
|
A key of nil has as its value a list of defaulted headers to ignore."
|
|
|
|
(let ((ignore (append (cdr (assq nil format-rules))
|
|
|
|
(mapcar #'car format-rules))))
|
|
|
|
(dolist (rule format-rules)
|
|
|
|
(let* ((header (car rule))
|
|
|
|
(value (mail-header header)))
|
1998-08-01 19:12:59 +00:00
|
|
|
(if (stringp header)
|
|
|
|
(setq header (intern header)))
|
1996-06-25 22:35:26 +00:00
|
|
|
(cond ((null header) 'ignore)
|
|
|
|
((eq header t)
|
|
|
|
(dolist (defaulted headers)
|
|
|
|
(unless (memq (car defaulted) ignore)
|
|
|
|
(let* ((header (car defaulted))
|
|
|
|
(value (cdr defaulted)))
|
|
|
|
(if (cdr rule)
|
|
|
|
(funcall (cdr rule) header value)
|
1998-08-01 19:12:59 +00:00
|
|
|
(funcall mail-header-format-function header value))))))
|
1996-06-25 22:35:26 +00:00
|
|
|
(value
|
|
|
|
(if (cdr rule)
|
|
|
|
(funcall (cdr rule) header value)
|
1998-08-01 19:12:59 +00:00
|
|
|
(funcall mail-header-format-function header value))))))
|
2005-11-29 23:54:47 +00:00
|
|
|
(insert "\n")))
|
1996-06-25 22:35:26 +00:00
|
|
|
|
|
|
|
(provide 'mailheader)
|
|
|
|
|
1996-07-02 00:01:05 +00:00
|
|
|
;;; mailheader.el ends here
|