emacs: Improve the definition and use of `notmuch-fcc-dirs'.

Re-work the declaration and definition of `notmuch-fcc-dirs'. The
variable now allows three types of values:

- nil: no Fcc header is added,

- a string: the value of `notmuch-fcc-dirs' is the name of the
  folder to use,

- a list: the folder is chosen based on the From address of the
  current message using a list of regular expressions and
  corresponding folders:

     ((\"Sebastian@SSpaeth.de\" . \"privat\")
      (\"spaetz@sspaeth.de\" . \"OUTBOX.OSS\")
      (\".*\" . \"defaultinbox\"))

  If none of the regular expressions match the From address, no
  Fcc header will be added.
This commit is contained in:
David Edmondson 2010-11-08 15:01:25 +00:00 committed by Carl Worth
parent c471c4eb04
commit ea1c2bb5c5

View file

@ -16,6 +16,7 @@
;; To use this as the fcc handler for message-mode, ;; To use this as the fcc handler for message-mode,
;; customize the notmuch-fcc-dirs variable ;; customize the notmuch-fcc-dirs variable
(eval-when-compile (require 'cl))
(require 'message) (require 'message)
(require 'notmuch-lib) (require 'notmuch-lib)
@ -23,41 +24,40 @@
(defvar notmuch-maildir-fcc-count 0) (defvar notmuch-maildir-fcc-count 0)
(defcustom notmuch-fcc-dirs "sent" (defcustom notmuch-fcc-dirs "sent"
"Determines the maildir directory to save outgoing mails in. "Determines the maildir directory in which to save outgoing mail.
If set to non-nil, this will cause message mode to file your Three types of values are permitted:
mail in the specified directory (fcc).
It is either a string if you only need one fcc directory or a - nil: no Fcc header is added,
list if they depend on your From address (see example).
In the former case it is a string such as \"INBOX.Sent\". - a string: the value of `notmuch-fcc-dirs' is the name of the
folder to use,
In the fancy setup, where you want different outboxes depending - a list: the folder is chosen based on the From address of the
on your From address, you supply a list like this: current message using a list of regular expressions and
corresponding folders:
((\"defaultinbox\") ((\"Sebastian@SSpaeth.de\" . \"privat\")
(\"Sebastian Spaeth <Sebastian@SSpaeth.de>\" . \"privat\") (\"spaetz@sspaeth.de\" . \"OUTBOX.OSS\")
(\"Sebastian Spaeth <spaetz@sspaeth.de>\" . \"OUTBOX.OSS\") (\".*\" . \"defaultinbox\"))
)
The outbox that matches a key (case insensitive) will be If none of the regular expressions match the From address, no
used. The first entry is used as a default fallback when nothing Fcc header will be added.
else matches.
In all cases, a relative FCC directory will be understood to In all cases, a relative FCC directory will be understood to
specify a directory within the notmuch mail store, (as set by specify a directory within the notmuch mail store, (as set by
the database.path option in the notmuch configuration file). the database.path option in the notmuch configuration file).
You will be prompted to create the directory if it does not exist yet when You will be prompted to create the directory if it does not exist
sending a mail. yet when sending a mail."
This function will not modify the headers if there is a FCC
header, but will check that the target directory exists."
:require 'notmuch-fcc-initialization :require 'notmuch-fcc-initialization
:group 'notmuch :group 'notmuch
) :type '(choice
(const :tag "No FCC header" nil)
(string :tag "A single folder")
(repeat :tag "A folder based on the From header"
(cons regexp (string :tag "Folder")))))
(defun notmuch-fcc-initialization () (defun notmuch-fcc-initialization ()
"If notmuch-fcc-directories is set, "If notmuch-fcc-directories is set,
@ -67,44 +67,66 @@
(setq message-fcc-handler-function (setq message-fcc-handler-function
'(lambda (destdir) '(lambda (destdir)
(notmuch-maildir-fcc-write-buffer-to-maildir destdir t))) (notmuch-maildir-fcc-write-buffer-to-maildir destdir t)))
;;add a hook to actually insert the Fcc header when sending ;; add a hook to actually insert the Fcc header when sending
(add-hook 'message-header-setup-hook 'notmuch-fcc-header-setup)) (add-hook 'message-header-setup-hook 'notmuch-fcc-header-setup))
(defun notmuch-fcc-header-setup () (defun notmuch-fcc-header-setup ()
"Adds an appropriate fcc header to the current mail buffer "Add an Fcc header to the current message buffer.
Can be added to message-send-hook and will set the FCC header Can be added to `message-send-hook' and will set the Fcc header
based on the values of notmuch-fcc-directories (see the based on the values of `notmuch-fcc-dirs'. An existing Fcc header
variable customization there for examples). It uses the first will NOT be removed or replaced."
entry as default fallback if no From address matches."
;; only do something if notmuch-fcc-dirs is set
(when notmuch-fcc-dirs
(let (subdir)
(if (stringp notmuch-fcc-dirs)
;; notmuch-fcc-dirs is a string, just use it as subdir
(setq subdir notmuch-fcc-dirs)
;; else: it's a list of alists (("sent") ("name1" . "sent1"))
(setq subdir (cdr (assoc-string (message-fetch-field "from") notmuch-fcc-dirs t)))
;; if we found no hit, use the first entry as default fallback
(unless subdir (setq subdir (car (car notmuch-fcc-dirs)))))
;; if there is no fcc header yet, add ours (let ((subdir
(unless (message-fetch-field "fcc") (cond
(message-add-header (concat "Fcc: " ((or (not notmuch-fcc-dirs)
(message-fetch-field "Fcc"))
;; Nothing set or an existing header.
nil)
((stringp notmuch-fcc-dirs)
notmuch-fcc-dirs)
((and (listp notmuch-fcc-dirs)
(= 1 (length (car notmuch-fcc-dirs))))
;; Old style - no longer works.
(error "Invalid `notmuch-fcc-dirs' setting (old style)"))
((listp notmuch-fcc-dirs)
(let* ((from (message-fetch-field "From"))
(match
(catch 'first-match
(dolist (re-folder notmuch-fcc-dirs)
(when (string-match-p (car re-folder) from)
(throw 'first-match re-folder))))))
(if match
(cdr match)
(message "No Fcc header added.")
nil)))
(t
(error "Invalid `notmuch-fcc-dirs' setting (neither string nor list)")))))
(when subdir
(message-add-header
(concat "Fcc: "
;; If the resulting directory is not an absolute path,
;; prepend the standard notmuch database path.
(if (= (elt subdir 0) ?/) (if (= (elt subdir 0) ?/)
subdir subdir
(concat (notmuch-database-path) "/" subdir))))) (concat (notmuch-database-path) "/" subdir))))
;; finally test if fcc points to a valid maildir ;; finally test if fcc points to a valid maildir
(let ((fcc-header (message-fetch-field "fcc"))) (let ((fcc-header (message-fetch-field "Fcc")))
(unless (notmuch-maildir-fcc-dir-is-maildir-p fcc-header) (unless (notmuch-maildir-fcc-dir-is-maildir-p fcc-header)
(cond ((not (file-writable-p fcc-header)) (cond ((not (file-writable-p fcc-header))
(error (format "%s is not a maildir, but you don't have permission to create one." fcc-header))) (error (format "No permission to create %s, which does not exist"
fcc-header)))
((y-or-n-p (format "%s is not a maildir. Create it? " ((y-or-n-p (format "%s is not a maildir. Create it? "
fcc-header)) fcc-header))
(notmuch-maildir-fcc-create-maildir fcc-header)) (notmuch-maildir-fcc-create-maildir fcc-header))
(t (t
(error "Not sending message.")))))))) (error "Message not sent"))))))))
(defun notmuch-maildir-fcc-host-fixer (hostname) (defun notmuch-maildir-fcc-host-fixer (hostname)
(replace-regexp-in-string "/\\|:" (replace-regexp-in-string "/\\|:"