diff --git a/mu4e/mu4e-context.el b/mu4e/mu4e-context.el index 43688770..eaafdd83 100644 --- a/mu4e/mu4e-context.el +++ b/mu4e/mu4e-context.el @@ -22,7 +22,7 @@ ;;; Commentary: -;; A mu4e 'context' is a a set of variable-settings and functions, which can be +;; A mu4e 'context' is a set of variable-settings and functions, which can be ;; used e.g. to switch between accounts. (require 'cl-lib) (require 'mu4e-utils) @@ -69,13 +69,129 @@ none." that takes a message plist for the message replied to or forwarded, and nil otherwise. Before composing a new message, `mu4e' switches to the first context for which `match-func' - returns t." + returns t. +- `vars': variables to set when entering context." name ;; name of the context, e.g. "work" (enter-func nil) ;; function invoked when entering the context (leave-func nil) ;; function invoked when leaving the context (match-func nil) ;; function that takes a msg-proplist, and return t ;; if it matches, nil otherwise - vars) ;; alist of variables. + vars) ;; alist of variables. + +(defvar mu4e-no-trash-providers '("gmail.com" "googlemail.com") + "List of email providers that don't support the trash flag.") + +(cl-defun make-mu4e-context-account (name &key + enter-func + leave-func + match-func + vars + ;; We set sane defaults for the following variables. They will be added to + ;; the context vars. + (user-mail-address user-mail-address) + (smtpmail-smtp-user smtpmail-smtp-user) + ;; Folders: + maildir + (drafts-folder "drafts") + (sent-folder "sent") + (trash-folder "trash") + (refile-folder "archive") + ;; Trash fix. + no-trash-flag + ;; Rule for matching the context. + predicate) + "Create a context with sane defaults (see `make-mu4e-context'). +Also: +- Add the context to the `mu4e-contexts'. +- Update the bookmarks to ignore the trash folder if NO-TRASH-FLAG is non-nil. +- Update the `mu4e-user-mail-address-list'. + +Options beyond those of `make-mu4e-context': +- `user-mail-address': Defaults to the global value when the context is created. +- `smtpmail-smtp-user': Defaults to the global value if non-nil when the context + is created, or the context `user-mail-address' otherwise. +- `maildir': Mailbox folder name in as stored in `mu4e-maildir' (just the name, + there must be no '/'). Defaults to `name'. +- `drafts-folder': Context value of `mu4e-drafts-folder'. Defaults to + \"drafts\". +- `sent-folder': Context value of `mu4e-sent-folder'. Defaults to \"sent\". +- `trash-folder': Context value of `mu4e-trash-folder'. Defaults to \"trash\". +- `refile-folder': Context value of `mu4e-refile-folder'. Defaults to + \"refile\". +- `no-trash-flag': If non-nil, the maildir will be added to + `mu4e-move-to-trash-patterns' so that trashing moves the message instead of flagging. +- `predicate': A function that takes a message and returns non-nil if it matches + the context. This is only used if `match-func' is not provided, in which case + the context is always matched against the message folder. + +Example of a mailbox where only the sent-folder differs from the +default folders (see `make-mu4e-context' and `mu4e-context'): + + (let ((gandi-smtp-vars '((smtpmail-smtp-server . \"mail.gandi.net\") + (smtpmail-stream-type . starttls) + (smtpmail-smtp-service . 587)))) + (make-mu4e-context-account + :name \"personal\" + :user-mail-address \"john@doe.xyz\" + :sent-folder \"Sent\" + :vars gandi-smtp-vars) + (make-mu4e-context-account + :name \"work\" + :user-mail-address \"john@work.org\" + :sent-folder \"Sent\" + :predicate (lambda (msg) + (mu4e-message-contact-field-matches + msg '(:from :to) \"boss@work.org\")) + :vars gandi-smtp-vars))" + (cl-assert name) + (setq maildir (concat "/" (or maildir name) "/") + smtpmail-smtp-user (or smtpmail-smtp-user user-mail-address) + no-trash-flag (or no-trash-flag + (string-match (regexp-opt mu4e-no-trash-providers) + user-mail-address))) + (when no-trash-flag + ;; Exclude trash folder from all bookmarks. This is useful for mailboxes + ;; which don't use the "trash" flag like Gmail. + (dolist (bookmark mu4e-bookmarks) + ;; TODO: mu4e-bookmark-query does not work here, why? + (setf (car bookmark) (format "NOT maildir:\"%s\" and %s" + mu4e-trash-folder + (car bookmark)))) + ;; If this is a Gmail context, we add the maildir to the pattern list so + ;; that they can be properly trashed. + (add-to-list 'mu4e-move-to-trash-patterns (concat "^" maildir))) + ;; TODO: Seems that mu4e fails to start when no default folder is set. + ;; The following setq is a workaround. + (setq mu4e-drafts-folder (concat maildir drafts-folder) + mu4e-sent-folder (concat maildir sent-folder) + mu4e-trash-folder (concat maildir trash-folder) + mu4e-refile-folder (concat maildir refile-folder)) + (let ((context (make-mu4e-context :name name + :enter-func enter-func + :leave-func leave-func + :match-func match-func + :vars vars))) + (unless (mu4e-context-match-func context) + (setf (mu4e-context-match-func context) + `(lambda (msg) + (when msg + (or + ,(when predicate + `(funcall ,predicate msg)) + (string-prefix-p ,maildir (mu4e-message-field msg :maildir))))))) + (setf (mu4e-context-vars context) + (append `((user-mail-address . ,user-mail-address) + (smtpmail-smtp-user . ,smtpmail-smtp-user) + (mu4e-drafts-folder . ,mu4e-drafts-folder) + (mu4e-sent-folder . ,mu4e-sent-folder) + (mu4e-trash-folder . ,mu4e-trash-folder) + (mu4e-refile-folder . ,mu4e-refile-folder)) + (mu4e-context-vars context))) + ;; Required when using multiple addresses and if we don't want to + ;; reply to ourselves. + (add-to-list 'mu4e-user-mail-address-list user-mail-address) + (add-to-list 'mu4e-contexts context) + context)) (defun mu4e~context-ask-user (prompt) "Let user choose some context based on its name."