mu4e: update to use server maildir/database/addresses

Mkae mu4e-maildir and mu4e-personal-addresses obsolete, we get those
from the server.
This commit is contained in:
Dirk-Jan C. Binnema 2020-02-06 20:28:24 +02:00
parent dea4789e0e
commit e1e26d1da2
17 changed files with 791 additions and 889 deletions

View File

@ -577,7 +577,8 @@ cmd_init (MuConfig *opts, GError **err)
if (!opts->quiet) { if (!opts->quiet) {
mu_store_print_info (store, opts->nocolor); mu_store_print_info (store, opts->nocolor);
g_print ("\nstore created.\n" g_print ("\nstore created.\n"
"now you can use the index command to index some messages.\n" "use 'mu index' to fill the database "
"with your messsages.\n"
"see mu-index(1) for details\n"); "see mu-index(1) for details\n");
} }

View File

@ -323,7 +323,6 @@ Example: +tag,+long tag,-oldtag
would add 'tag' and 'long tag', and remove 'oldtag'." would add 'tag' and 'long tag', and remove 'oldtag'."
(let* ( (let* (
(path (mu4e-message-field msg :path)) (path (mu4e-message-field msg :path))
(maildir (mu4e-message-field msg :maildir))
(oldtags (mu4e-message-field msg :tags)) (oldtags (mu4e-message-field msg :tags))
(tags-completion (tags-completion
(append (append
@ -369,7 +368,7 @@ would add 'tag' and 'long tag', and remove 'oldtag'."
path)) path))
(mu4e-message (concat "tagging: " (mapconcat 'identity taglist ", "))) (mu4e-message (concat "tagging: " (mapconcat 'identity taglist ", ")))
(mu4e-refresh-message path maildir))) (mu4e-refresh-message path)))
(defun mu4e-action-show-thread (msg) (defun mu4e-action-show-thread (msg)
"Show thread for message at point with point remaining on MSG. "Show thread for message at point with point remaining on MSG.

View File

@ -1,6 +1,6 @@
;; mu4e-compose.el -- part of mu4e, the mu mail user agent for emacs -*- lexical-binding: t -*- ;; mu4e-compose.el -- part of mu4e, the mu mail user agent for emacs -*- lexical-binding: t -*-
;; ;;
;; Copyright (C) 2011-2019 Dirk-Jan C. Binnema ;; Copyright (C) 2011-2020 Dirk-Jan C. Binnema
;; Author: Dirk-Jan C. Binnema <djcb@djcbsoftware.nl> ;; Author: Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
;; Maintainer: Dirk-Jan C. Binnema <djcb@djcbsoftware.nl> ;; Maintainer: Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
@ -260,8 +260,8 @@ If needed, set the Fcc header, and register the handler function."
`mu4e-sent-messages-behavior'" `mu4e-sent-messages-behavior'"
mu4e-sent-messages-behavior)))) mu4e-sent-messages-behavior))))
(fccfile (and mdir (fccfile (and mdir
(concat mu4e-maildir mdir "/cur/" (concat (mu4e-root-maildir) mdir "/cur/"
(mu4e~draft-message-filename-construct "S"))))) (mu4e~draft-message-filename-construct "S")))))
;; if there's an fcc header, add it to the file ;; if there's an fcc header, add it to the file
(when fccfile (when fccfile
(message-add-header (concat "Fcc: " fccfile "\n")) (message-add-header (concat "Fcc: " fccfile "\n"))
@ -273,7 +273,7 @@ If needed, set the Fcc header, and register the handler function."
(old-handler message-fcc-handler-function)) (old-handler message-fcc-handler-function))
(lambda (file) (lambda (file)
(setq message-fcc-handler-function old-handler) ;; reset the fcc handler (setq message-fcc-handler-function old-handler) ;; reset the fcc handler
(let ((mdir-path (concat mu4e-maildir maildir))) (let ((mdir-path (concat (mu4e-root-maildir) maildir)))
;; Create the full maildir structure for the sent folder if it doesn't exist. ;; Create the full maildir structure for the sent folder if it doesn't exist.
;; `mu4e~proc-mkdir` runs asynchronously but no matter whether it runs before or after ;; `mu4e~proc-mkdir` runs asynchronously but no matter whether it runs before or after
;; `write-file`, the sent maildir ends up in the correct state. ;; `write-file`, the sent maildir ends up in the correct state.
@ -817,8 +817,8 @@ draft message."
;; as default emacs mailer (define-mail-user-agent etc.) ;; as default emacs mailer (define-mail-user-agent etc.)
;;;###autoload ;;;###autoload
(defun mu4e~compose-mail (&optional to subject other-headers continue (defun mu4e~compose-mail (&optional to subject other-headers _continue
switch-function yank-action send-actions return-action) _switch-function yank-action _send-actions _return-action)
"This is mu4e's implementation of `compose-mail'. "This is mu4e's implementation of `compose-mail'.
Quoting its docstring: Quoting its docstring:
Start composing a mail message to send. Start composing a mail message to send.

View File

@ -1,6 +1,6 @@
; mu4e-context.el -- part of mu4e, the mu mail user agent -*- lexical-binding: t -*- ; mu4e-context.el -- part of mu4e, the mu mail user agent -*- lexical-binding: t -*-
;; ;;
;; Copyright (C) 2015-2016 Dirk-Jan C. Binnema ;; Copyright (C) 2015-2020 Dirk-Jan C. Binnema
;; Author: Dirk-Jan C. Binnema <djcb@djcbsoftware.nl> ;; Author: Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
;; Maintainer: Dirk-Jan C. Binnema <djcb@djcbsoftware.nl> ;; Maintainer: Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
@ -31,14 +31,11 @@
(defvar smtpmail-smtp-user) (defvar smtpmail-smtp-user)
(defvar mu4e-view-date-format) (defvar mu4e-view-date-format)
(defcustom mu4e-contexts nil "The list of `mu4e-context' objects (defvar mu4e-contexts nil "The list of `mu4e-context' objects
describing mu4e's contexts." describing mu4e's contexts.")
:group 'mu4e)
(defcustom mu4e-context-changed-hook nil (defvar mu4e-context-changed-hook nil
"Hook run just *after* the context changed." "Hook run just *after* the context changed.")
:type 'hook
:group 'mu4e-headers)
(defvar mu4e~context-current nil (defvar mu4e~context-current nil
"The current context; for internal use. Use "The current context; for internal use. Use
@ -238,8 +235,7 @@ non-nil."
(set (car cell) (cdr cell))) (set (car cell) (cdr cell)))
(mu4e-context-vars context))) (mu4e-context-vars context)))
(setq mu4e~context-current context) (setq mu4e~context-current context)
(unless (eq mu4e-split-view 'single-window)
(mu4e~main-view-real nil nil))
(run-hooks 'mu4e-context-changed-hook) (run-hooks 'mu4e-context-changed-hook)
(mu4e-message "Switched context to %s" (mu4e-context-name context))) (mu4e-message "Switched context to %s" (mu4e-context-name context)))
context)) context))
@ -248,7 +244,7 @@ non-nil."
"When contexts are defined but there is no context yet, switch "When contexts are defined but there is no context yet, switch
to the first whose :match-func return non-nil. If none of them to the first whose :match-func return non-nil. If none of them
match, return the first. For MSG and POLICY, see `mu4e-context-determine'." match, return the first. For MSG and POLICY, see `mu4e-context-determine'."
(when mu4e-contexts (when (and mu4e-contexts (not mu4e~context-current))
(let ((context (mu4e-context-determine msg policy))) (let ((context (mu4e-context-determine msg policy)))
(when context (mu4e-context-switch (when context (mu4e-context-switch
nil (mu4e-context-name context)))))) nil (mu4e-context-name context))))))

View File

@ -1,6 +1,6 @@
;;; mu4e-contrib.el -- part of mu4e, the mu mail user agent -*- lexical-binding: t -*- ;;; mu4e-contrib.el -- part of mu4e, the mu mail user agent -*- lexical-binding: t -*-
;; ;;
;; Copyright (C) 2013-2016 Dirk-Jan C. Binnema ;; Copyright (C) 2013-2020 Dirk-Jan C. Binnema
;; This file is not part of GNU Emacs. ;; This file is not part of GNU Emacs.
;; ;;
@ -20,7 +20,10 @@
;;; Commentary: ;;; Commentary:
;; Some user-contributed functions for mu4e ;; Some user-contributed functions for mu4e
(require 'mu4e-headers)
(require 'mu4e-view)
(require 'bookmark)
(require 'eshell)
;; Contributed by sabof ;; Contributed by sabof
(defvar bookmark-make-record-function) (defvar bookmark-make-record-function)

View File

@ -1,6 +1,6 @@
;; mu4e-draft.el -- part of mu4e, the mu mail user agent for emacs -*- lexical-binding: t -*- ;; mu4e-draft.el -- part of mu4e, the mu mail user agent for emacs -*- lexical-binding: t -*-
;; ;;
;; Copyright (C) 2011-2019 Dirk-Jan C. Binnema ;; Copyright (C) 2011-2020 Dirk-Jan C. Binnema
;; Author: Dirk-Jan C. Binnema <djcb@djcbsoftware.nl> ;; Author: Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
;; Maintainer: Dirk-Jan C. Binnema <djcb@djcbsoftware.nl> ;; Maintainer: Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
@ -38,7 +38,7 @@
(defcustom mu4e-compose-dont-reply-to-self nil (defcustom mu4e-compose-dont-reply-to-self nil
"If non-nil, don't include self. "If non-nil, don't include self.
\(that is, member of `mu4e-user-mail-address-list') in replies." \(that is, member of `(mu4e-personal-addresses)') in replies."
:type 'boolean :type 'boolean
:group 'mu4e-compose) :group 'mu4e-compose)
@ -189,7 +189,7 @@ of the original, we simple copy the list form the original."
(cl-member-if (cl-member-if
(lambda (addr) (lambda (addr)
(string= (downcase addr) (downcase (cdr to-cell)))) (string= (downcase addr) (downcase (cdr to-cell))))
mu4e-user-mail-address-list)) (mu4e-personal-addresses)))
reply-to) reply-to)
reply-to))) reply-to)))
@ -253,7 +253,7 @@ REPLY-ALL."
(cl-member-if (cl-member-if
(lambda (addr) (lambda (addr)
(string= (downcase addr) (downcase (cdr cc-cell)))) (string= (downcase addr) (downcase (cdr cc-cell))))
mu4e-user-mail-address-list)) (mu4e-personal-addresses)))
cc-lst)))) cc-lst))))
cc-lst))) cc-lst)))
@ -540,7 +540,7 @@ This is based on `mu4e-drafts-folder', which is evaluated once.")
(defun mu4e~draft-determine-path (draft-dir) (defun mu4e~draft-determine-path (draft-dir)
"Determines the path for a new draft file in DRAFT-DIR." "Determines the path for a new draft file in DRAFT-DIR."
(format "%s/%s/cur/%s" (format "%s/%s/cur/%s"
mu4e-maildir draft-dir (mu4e~draft-message-filename-construct "DS"))) (mu4e-root-maildir) draft-dir (mu4e~draft-message-filename-construct "DS")))
(defun mu4e-draft-open (compose-type &optional msg) (defun mu4e-draft-open (compose-type &optional msg)
@ -550,12 +550,11 @@ In case of a new message (when COMPOSE-TYPE is `reply', `forward'
or re-send an existing message (when COMPOSE-TYPE is `resend'). or re-send an existing message (when COMPOSE-TYPE is `resend').
The name of the draft folder is constructed from the The name of the draft folder is constructed from the
concatenation of `mu4e-maildir' and `mu4e-drafts-folder' (the concatenation of `(mu4e-root-maildir)' and `mu4e-drafts-folder' (the
latter will be evaluated). The message file name is a unique name latter will be evaluated). The message file name is a unique name
determined by `mu4e-send-draft-file-name'. The initial contents determined by `mu4e-send-draft-file-name'. The initial contents
will be created from either `mu4e~draft-reply-construct', or will be created from either `mu4e~draft-reply-construct', or
`mu4e~draft-forward-construct' or `mu4e~draft-newmsg-construct'." `mu4e~draft-forward-construct' or `mu4e~draft-newmsg-construct'."
(unless mu4e-maildir (mu4e-error "Variable mu4e-maildir not set"))
(let ((draft-dir nil)) (let ((draft-dir nil))
(cl-case compose-type (cl-case compose-type

File diff suppressed because it is too large Load Diff

View File

@ -42,6 +42,9 @@
(require 'gnus-icalendar) (require 'gnus-icalendar)
(require 'cl-lib) (require 'cl-lib)
(eval-when-compile (require 'mu4e-mark))
(eval-when-compile (require 'mu4e-vars))
;;;###autoload ;;;###autoload
(defun mu4e-icalendar-setup () (defun mu4e-icalendar-setup ()
"Perform the necessary initialization to use mu4e-icalendar." "Perform the necessary initialization to use mu4e-icalendar."
@ -49,34 +52,34 @@
(cl-defmethod gnus-icalendar-event:inline-reply-buttons :around (cl-defmethod gnus-icalendar-event:inline-reply-buttons :around
((event gnus-icalendar-event) handle) ((event gnus-icalendar-event) handle)
(if (and (boundp 'mu4e~view-rendering) (if (and (boundp 'mu4e~view-rendering)
(gnus-icalendar-event:rsvp event)) (gnus-icalendar-event:rsvp event))
(let ((method (gnus-icalendar-event:method event))) (let ((method (gnus-icalendar-event:method event)))
(when (or (string= method "REQUEST") (string= method "PUBLISH")) (when (or (string= method "REQUEST") (string= method "PUBLISH"))
`(("Accept" mu4e-icalendar-reply (,handle accepted ,event)) `(("Accept" mu4e-icalendar-reply (,handle accepted ,event))
("Tentative" mu4e-icalendar-reply (,handle tentative ,event)) ("Tentative" mu4e-icalendar-reply (,handle tentative ,event))
("Decline" mu4e-icalendar-reply (,handle declined ,event))))) ("Decline" mu4e-icalendar-reply (,handle declined ,event)))))
(cl-call-next-method event handle)))) (cl-call-next-method event handle))))
(defun mu4e-icalendar-reply (data) (defun mu4e-icalendar-reply (data)
"Reply to the text/calendar event present in DATA." "Reply to the text/calendar event present in DATA."
;; Based on `gnus-icalendar-reply'. ;; Based on `gnus-icalendar-reply'.
(let* ((handle (car data)) (let* ((handle (car data))
(status (cadr data)) (status (cadr data))
(event (caddr data)) (event (caddr data))
(gnus-icalendar-additional-identities mu4e-user-mail-address-list) (gnus-icalendar-additional-identities (mu4e-personal-addresses))
(reply (gnus-icalendar-with-decoded-handle handle (reply (gnus-icalendar-with-decoded-handle handle
(gnus-icalendar-event-reply-from-buffer (gnus-icalendar-event-reply-from-buffer
(current-buffer) status (gnus-icalendar-identities)))) (current-buffer) status (gnus-icalendar-identities))))
(msg (mu4e-message-at-point 'noerror)) (msg (mu4e-message-at-point 'noerror))
(charset (cdr (assoc 'charset (mm-handle-type handle))))) (charset (cdr (assoc 'charset (mm-handle-type handle)))))
(when reply (when reply
(cl-labels (cl-labels
((fold-icalendar-buffer ((fold-icalendar-buffer
() ()
(goto-char (point-min)) (goto-char (point-min))
(while (re-search-forward "^\\(.\\{72\\}\\)\\(.+\\)$" nil t) (while (re-search-forward "^\\(.\\{72\\}\\)\\(.+\\)$" nil t)
(replace-match "\\1\n \\2") (replace-match "\\1\n \\2")
(goto-char (line-beginning-position))))) (goto-char (line-beginning-position)))))
(with-current-buffer (get-buffer-create gnus-icalendar-reply-bufname) (with-current-buffer (get-buffer-create gnus-icalendar-reply-bufname)
(delete-region (point-min) (point-max)) (delete-region (point-min) (point-max))
@ -92,7 +95,7 @@
(gnus-icalendar--update-org-event event status)) (gnus-icalendar--update-org-event event status))
(when mu4e-icalendar-diary-file (when mu4e-icalendar-diary-file
(mu4e~icalendar-insert-diary event status (mu4e~icalendar-insert-diary event status
mu4e-icalendar-diary-file)))))) mu4e-icalendar-diary-file))))))
(defun mu4e~icalendar-delete-citation () (defun mu4e~icalendar-delete-citation ()
"Function passed to `mu4e-compose-cite-function' to remove the citation." "Function passed to `mu4e-compose-cite-function' to remove the citation."
@ -104,17 +107,17 @@
"See `mu4e-sent-handler' for DOCID and PATH." "See `mu4e-sent-handler' for DOCID and PATH."
(mu4e-sent-handler docid path) (mu4e-sent-handler docid path)
(let* ((docid (mu4e-message-field original-msg :docid)) (let* ((docid (mu4e-message-field original-msg :docid))
(markdescr (assq 'trash mu4e-marks)) (markdescr (assq 'trash mu4e-marks))
(action (plist-get (cdr markdescr) :action)) (action (plist-get (cdr markdescr) :action))
(target (mu4e-get-trash-folder original-msg))) (target (mu4e-get-trash-folder original-msg)))
(with-current-buffer (mu4e-get-headers-buffer) (with-current-buffer (mu4e-get-headers-buffer)
(run-hook-with-args 'mu4e-mark-execute-pre-hook 'trash original-msg) (run-hook-with-args 'mu4e-mark-execute-pre-hook 'trash original-msg)
(funcall action docid original-msg target)) (funcall action docid original-msg target))
(when (and (mu4e~headers-view-this-message-p docid) (when (and (mu4e~headers-view-this-message-p docid)
(buffer-live-p (mu4e-get-view-buffer))) (buffer-live-p (mu4e-get-view-buffer)))
(switch-to-buffer (mu4e-get-view-buffer)) (switch-to-buffer (mu4e-get-view-buffer))
(or (mu4e-view-headers-next) (or (mu4e-view-headers-next)
(kill-buffer-and-window)))))) (kill-buffer-and-window))))))
(defun mu4e-icalendar-reply-ical (original-msg event status buffer-name) (defun mu4e-icalendar-reply-ical (original-msg event status buffer-name)
"Reply to ORIGINAL-MSG containing invitation EVENT with STATUS. "Reply to ORIGINAL-MSG containing invitation EVENT with STATUS.
@ -123,8 +126,8 @@ STATUS values. BUFFER-NAME is the name of the buffer holding the
response in icalendar format." response in icalendar format."
(let ((message-signature nil)) (let ((message-signature nil))
(let ((mu4e-compose-cite-function #'mu4e~icalendar-delete-citation) (let ((mu4e-compose-cite-function #'mu4e~icalendar-delete-citation)
(mu4e-sent-messages-behavior 'delete) (mu4e-sent-messages-behavior 'delete)
(mu4e-compose-reply-recipients 'sender)) (mu4e-compose-reply-recipients 'sender))
(mu4e~compose-handler 'reply original-msg)) (mu4e~compose-handler 'reply original-msg))
;; Make sure the recipient is the organizer ;; Make sure the recipient is the organizer
(let ((organizer (gnus-icalendar-event:organizer event))) (let ((organizer (gnus-icalendar-event:organizer event)))
@ -136,23 +139,23 @@ response in icalendar format."
(mml-insert-multipart "alternative") (mml-insert-multipart "alternative")
(mml-insert-part "text/plain") (mml-insert-part "text/plain")
(let ((reply-event (gnus-icalendar-event-from-buffer (let ((reply-event (gnus-icalendar-event-from-buffer
buffer-name mu4e-user-mail-address-list))) buffer-name (mu4e-personal-addresses))))
(insert (gnus-icalendar-event->gnus-calendar reply-event status))) (insert (gnus-icalendar-event->gnus-calendar reply-event status)))
(forward-line 1); move past closing tag (forward-line 1); move past closing tag
(mml-attach-buffer buffer-name "text/calendar; method=REPLY; charset=utf-8") (mml-attach-buffer buffer-name "text/calendar; method=REPLY; charset=utf-8")
(message-remove-header "Subject") (message-remove-header "Subject")
(message-goto-subject) (message-goto-subject)
(insert (capitalize (symbol-name status)) (insert (capitalize (symbol-name status))
": " (gnus-icalendar-event:summary event)) ": " (gnus-icalendar-event:summary event))
(set-buffer-modified-p nil); not yet modified by user (set-buffer-modified-p nil); not yet modified by user
(when mu4e-icalendar-trash-after-reply (when mu4e-icalendar-trash-after-reply
;; Override `mu4e-sent-handler' set by `mu4e-compose-mode' to ;; Override `mu4e-sent-handler' set by `mu4e-compose-mode' to
;; also trash the message (thus must be appended to hooks). ;; also trash the message (thus must be appended to hooks).
(add-hook (add-hook
'message-sent-hook 'message-sent-hook
(lambda () (setq mu4e-sent-func (lambda () (setq mu4e-sent-func
(mu4e~icalendar-trash-message original-msg))) (mu4e~icalendar-trash-message original-msg)))
t t)))) t t))))
(defun mu4e~icalendar-insert-diary (event reply-status filename) (defun mu4e~icalendar-insert-diary (event reply-status filename)
@ -161,20 +164,20 @@ REPLY-STATUS is the status of the reply. The possible values are
given in the doc of `gnus-icalendar-event-reply-from-buffer'." given in the doc of `gnus-icalendar-event-reply-from-buffer'."
;; FIXME: handle recurring events ;; FIXME: handle recurring events
(let* ((beg (gnus-icalendar-event:start-time event)) (let* ((beg (gnus-icalendar-event:start-time event))
(beg-date (format-time-string "%d/%m/%Y" beg)) (beg-date (format-time-string "%d/%m/%Y" beg))
(beg-time (format-time-string "%H:%M" beg)) (beg-time (format-time-string "%H:%M" beg))
(end (gnus-icalendar-event:end-time event)) (end (gnus-icalendar-event:end-time event))
(end-date (format-time-string "%d/%m/%Y" end)) (end-date (format-time-string "%d/%m/%Y" end))
(end-time (format-time-string "%H:%M" end)) (end-time (format-time-string "%H:%M" end))
(summary (gnus-icalendar-event:summary event)) (summary (gnus-icalendar-event:summary event))
(location (gnus-icalendar-event:location event)) (location (gnus-icalendar-event:location event))
(status (capitalize (symbol-name reply-status))) (status (capitalize (symbol-name reply-status)))
(txt (if location (txt (if location
(format "%s (%s)\n %s " summary status location) (format "%s (%s)\n %s " summary status location)
(format "%s (%s)" summary status)))) (format "%s (%s)" summary status))))
(with-temp-buffer (with-temp-buffer
(if (string= beg-date end-date) (if (string= beg-date end-date)
(insert beg-date " " beg-time "-" end-time " " txt "\n") (insert beg-date " " beg-time "-" end-time " " txt "\n")
(insert beg-date " " beg-time " Start of: " txt "\n") (insert beg-date " " beg-time " Start of: " txt "\n")
(insert beg-date " " end-time " End of: " txt "\n")) (insert beg-date " " end-time " End of: " txt "\n"))
(write-region (point-min) (point-max) filename t)))) (write-region (point-min) (point-max) filename t))))

View File

@ -27,6 +27,7 @@
(require 'smtpmail) ;; the queueing stuff (silence elint) (require 'smtpmail) ;; the queueing stuff (silence elint)
(require 'mu4e-utils) ;; utility functions (require 'mu4e-utils) ;; utility functions
(require 'mu4e-context) ;; the context (require 'mu4e-context) ;; the context
(require 'mu4e-vars) ;; the context
(require 'cl-lib) (require 'cl-lib)
(defconst mu4e~main-buffer-name " *mu4e-main*" (defconst mu4e~main-buffer-name " *mu4e-main*"
@ -140,22 +141,31 @@ clicked."
"\n"))) "\n")))
(defun mu4e~key-val (key val &optional unit)
"Return a key / value pair."
(concat
" * "
(propertize (format "%-20s" key) 'face 'mu4e-header-title-face)
": "
(propertize val 'face 'mu4e-header-key-face)
(if unit
(propertize (concat " " unit) 'face 'mu4e-header-title-face)
"")
"\n"))
;; NEW ;; NEW
;; This is the old `mu4e~main-view' function but without ;; This is the old `mu4e~main-view' function but without
;; buffer switching at the end. ;; buffer switching at the end.
(defun mu4e~main-view-real (ignore-auto noconfirm) (defun mu4e~main-view-real (_ignore-auto _noconfirm)
(let ((buf (get-buffer-create mu4e~main-buffer-name)) (let ((buf (get-buffer-create mu4e~main-buffer-name))
(inhibit-read-only t)) (inhibit-read-only t))
(with-current-buffer buf (with-current-buffer buf
(erase-buffer) (erase-buffer)
(insert (insert
"* " "* "
(propertize "mu4e - mu for emacs version " 'face 'mu4e-title-face) (propertize "mu4e" 'face 'mu4e-header-key-face)
(propertize " - mu for emacs version " 'face 'mu4e-title-face)
(propertize mu4e-mu-version 'face 'mu4e-header-key-face) (propertize mu4e-mu-version 'face 'mu4e-header-key-face)
(propertize "; (in store: " 'face 'mu4e-title-face)
(propertize (format "%s" (plist-get mu4e~server-props :doccount)) 'face 'mu4e-header-key-face)
(propertize " messages)" 'face 'mu4e-title-face)
"\n\n" "\n\n"
(propertize " Basics\n\n" 'face 'mu4e-title-face) (propertize " Basics\n\n" 'face 'mu4e-title-face)
(mu4e~main-action-str (mu4e~main-action-str
@ -183,9 +193,15 @@ clicked."
(mu4e~main-action-str "\t* [N]ews\n" 'mu4e-news) (mu4e~main-action-str "\t* [N]ews\n" 'mu4e-news)
(mu4e~main-action-str "\t* [A]bout mu4e\n" 'mu4e-about) (mu4e~main-action-str "\t* [A]bout mu4e\n" 'mu4e-about)
(mu4e~main-action-str "\t* [H]elp\n" 'mu4e-display-manual) (mu4e~main-action-str "\t* [H]elp\n" 'mu4e-display-manual)
(mu4e~main-action-str "\t* [q]uit\n" 'mu4e-quit)) (mu4e~main-action-str "\t* [q]uit\n" 'mu4e-quit)
(mu4e-main-mode)
))) "\n"
(propertize " Info\n\n" 'face 'mu4e-title-face)
(mu4e~key-val "database-path" (mu4e-database-path))
(mu4e~key-val "maildir" (mu4e-root-maildir))
(mu4e~key-val "in store"
(format "%d" (plist-get mu4e~server-props :doccount)) "messages"))
(mu4e-main-mode))))
(defun mu4e~main-view-queue () (defun mu4e~main-view-queue ()
"Display queue-related actions in the main view." "Display queue-related actions in the main view."

View File

@ -1,6 +1,6 @@
;; mu4e-mark.el -- part of mu4e, the mu mail user agent -*- lexical-binding: t -*- ;; mu4e-mark.el -- part of mu4e, the mu mail user agent -*- lexical-binding: t -*-
;; ;;
;; Copyright (C) 2011-2019 Dirk-Jan C. Binnema ;; Copyright (C) 2011-2020 Dirk-Jan C. Binnema
;; Author: Dirk-Jan C. Binnema <djcb@djcbsoftware.nl> ;; Author: Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
;; Maintainer: Dirk-Jan C. Binnema <djcb@djcbsoftware.nl> ;; Maintainer: Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
@ -288,7 +288,7 @@ The following marks are available, and the corresponding props:
(target (if (string= (substring target 0 1) "/") (target (if (string= (substring target 0 1) "/")
target target
(concat "/" target))) (concat "/" target)))
(fulltarget (concat mu4e-maildir target))) (fulltarget (concat (mu4e-root-maildir) target)))
(when (or (file-directory-p fulltarget) (when (or (file-directory-p fulltarget)
(and (yes-or-no-p (and (yes-or-no-p
(format "%s does not exist. Create now?" fulltarget)) (format "%s does not exist. Create now?" fulltarget))
@ -368,7 +368,7 @@ user which one)."
(defun mu4e~mark-check-target (target) (defun mu4e~mark-check-target (target)
"Check if TARGET exists; if not, offer to create it." "Check if TARGET exists; if not, offer to create it."
(let ((fulltarget (concat mu4e-maildir target))) (let ((fulltarget (concat (mu4e-root-maildir) target)))
(if (not (mu4e-create-maildir-maybe fulltarget)) (if (not (mu4e-create-maildir-maybe fulltarget))
(mu4e-error "Target dir %s does not exist " fulltarget) (mu4e-error "Target dir %s does not exist " fulltarget)
target))) target)))

View File

@ -1,6 +1,6 @@
;;; mu4e-message.el -- part of mu4e, the mu mail user agent -*- lexical-binding: t -*- ;;; mu4e-message.el -- part of mu4e, the mu mail user agent -*- lexical-binding: t -*-
;; ;;
;; Copyright (C) 2012-2018 Dirk-Jan C. Binnema ;; Copyright (C) 2012-2020 Dirk-Jan C. Binnema
;; Author: Dirk-Jan C. Binnema <djcb@djcbsoftware.nl> ;; Author: Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
;; Maintainer: Dirk-Jan C. Binnema <djcb@djcbsoftware.nl> ;; Maintainer: Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
@ -243,11 +243,11 @@ replace with."
(with-temp-buffer (with-temp-buffer
(insert body) (insert body)
(goto-char (point-min)) (goto-char (point-min))
(while (re-search-forward "[  ]" nil t) (while (re-search-forward "[  ’]" nil t)
(replace-match (replace-match
(cond (cond
((string= (match-string 0) "") "'") ((string= (match-string 0) "’") "'")
((string= (match-string 0) " ") " ") ((string= (match-string 0) " ") " ")
(t "")))) (t ""))))
(buffer-string))) (buffer-string)))
@ -282,14 +282,14 @@ expressions, in which case any of those are tried for a match."
Checks whether any of the of the contacts in field Checks whether any of the of the contacts in field
CFIELD (either :to, :from, :cc or :bcc) of msg MSG matches *me*, CFIELD (either :to, :from, :cc or :bcc) of msg MSG matches *me*,
that is, any of the e-mail address in that is, any of the e-mail address in
`mu4e-user-mail-address-list'. Returns the contact cell that `(mu4e-personal-addresses)'. Returns the contact cell that
matched, or nil." matched, or nil."
(cl-find-if (cl-find-if
(lambda (cc-cell) (lambda (cc-cell)
(cl-member-if (cl-member-if
(lambda (addr) (lambda (addr)
(string= (downcase addr) (downcase (cdr cc-cell)))) (string= (downcase addr) (downcase (cdr cc-cell))))
mu4e-user-mail-address-list)) (mu4e-personal-addresses)))
(mu4e-message-field msg cfield))) (mu4e-message-field msg cfield)))
(defsubst mu4e-message-part-field (msgpart field) (defsubst mu4e-message-part-field (msgpart field)

View File

@ -1,5 +1,5 @@
;;; mu4e-org -- Org-links to mu4e messages/queries -*- lexical-binding: t -*- ;;; mu4e-org -- Org-links to mu4e messages/queries -*- lexical-binding: t -*-
;; Copyright (C) 2012-2019 Dirk-Jan C. Binnema ;; Copyright (C) 2012-2020 Dirk-Jan C. Binnema
;; Author: Dirk-Jan C. Binnema <djcb@djcbsoftware.nl> ;; Author: Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
;; Maintainer: Dirk-Jan C. Binnema <djcb@djcbsoftware.nl> ;; Maintainer: Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>

View File

@ -180,8 +180,7 @@ The server output is as follows:
;; received a pong message ;; received a pong message
((plist-get sexp :pong) ((plist-get sexp :pong)
(funcall mu4e-pong-func (funcall mu4e-pong-func sexp))
(plist-get sexp :props)))
;; received a contacts message ;; received a contacts message
;; note: we use 'member', to match (:contacts nil) ;; note: we use 'member', to match (:contacts nil)
@ -253,11 +252,7 @@ Start the process if needed."
(unless (file-executable-p mu4e-mu-binary) (unless (file-executable-p mu4e-mu-binary)
(mu4e-error (format "`mu4e-mu-binary' (%S) not found" mu4e-mu-binary))) (mu4e-error (format "`mu4e-mu-binary' (%S) not found" mu4e-mu-binary)))
(let* ((process-connection-type nil) ;; use a pipe (let* ((process-connection-type nil) ;; use a pipe
(args '("server")) (args '("server")))
(args (append args (when mu4e-mu-home (list (concat "--muhome=" mu4e-mu-home)))))
(args (append args (mapcar (lambda(addr)
(format "--my-address=%s" addr))
mu4e-user-mail-address-list))))
(setq mu4e~proc-buf "") (setq mu4e~proc-buf "")
(setq mu4e~proc-process (apply 'start-process (setq mu4e~proc-process (apply 'start-process
mu4e~proc-name mu4e~proc-name mu4e~proc-name mu4e~proc-name
@ -395,15 +390,12 @@ or an error."
:skip-dups ,skip-dups :skip-dups ,skip-dups
:include-related ,include-related))) :include-related ,include-related)))
(defun mu4e~proc-index (path my-addresses cleanup lazy-check) (defun mu4e~proc-index (&optional cleanup lazy-check)
"Index messages on PATH with possible CLEANUP and LAZY-CHECK. "Index messages with possible CLEANUP and LAZY-CHECK.
PATH should point to some maildir directory structure. PATH should point to some maildir directory structure.
MY-ADDRESSES is a list of 'my' email addresses (see MY-ADDRESSES is a list of 'my' email addresses (see
`mu4e-user-mail-address-list')." `mu4e-user-mail-address-list')."
(mu4e~call-mu `(index (mu4e~call-mu `(index :cleanup ,cleanup :lazy-check ,lazy-check)))
:my-addresses ,my-addresses
:cleanup ,cleanup
:lazy-check ,lazy-check)))
(defun mu4e~proc-mkdir (path) (defun mu4e~proc-mkdir (path)
"Create a new maildir-directory at filesystem PATH." "Create a new maildir-directory at filesystem PATH."
@ -447,26 +439,15 @@ Returns either (:update ... ) or (:error ) sexp, which are handled my
(unless (or maildir flags) (unless (or maildir flags)
(mu4e-error "At least one of maildir and flags must be specified")) (mu4e-error "At least one of maildir and flags must be specified"))
(unless (or (not maildir) (unless (or (not maildir)
(file-exists-p (concat mu4e-maildir "/" maildir "/"))) (file-exists-p (concat (mu4e-root-maildir) "/" maildir "/")))
(mu4e-error "Target dir does not exist")) (mu4e-error "Target dir does not exist"))
(let* ((idparam (mu4e~docid-msgid-param docid-or-msgid)) (mu4e~call-mu `(move
(flagstr :docid ,(if (stringp docid-or-msgid) nil docid-or-msgid)
(when flags :msgid ,(if (stringp docid-or-msgid) docid-or-msgid nil)
(concat " flags:" :flags ,(or flags nil)
(if (stringp flags) flags (mu4e-flags-to-string flags))))) :maildir ,(or maildir nil)
(path :rename ,(and maildir mu4e-change-filenames-when-moving)
(when maildir :noview ,no-view)))
(format " maildir:%s" (mu4e~escape maildir))))
(rename
(if (and maildir mu4e-change-filenames-when-moving)
"true" "false")))
(mu4e~call-mu `(move
:docid ,(if (stringp docid-or-msgid) nil docid-or-msgid)
:msgid ,(if (stringp docid-or-msgid) docid-or-msgid nil)
:flags ,(or flags nil)
:maildir ,(or maildir nil)
:rename ,(and maildir mu4e-change-filenames-when-moving)
:noview ,no-view))))
(defun mu4e~proc-ping (&optional queries) (defun mu4e~proc-ping (&optional queries)
"Sends a ping to the mu server, expecting a (:pong ...) in response. "Sends a ping to the mu server, expecting a (:pong ...) in response.

View File

@ -83,10 +83,10 @@ NODEFAULT, hour and minute fields will be nil if not given."
(defun mu4e-user-mail-address-p (addr) (defun mu4e-user-mail-address-p (addr)
"If ADDR is one of user's e-mail addresses return t, nil otherwise. "If ADDR is one of user's e-mail addresses return t, nil otherwise.
User's addresses are set in `mu4e-user-mail-address-list'. Case User's addresses are set in `(mu4e-personal-addresses)'. Case
insensitive comparison is used." insensitive comparison is used."
(when (and addr mu4e-user-mail-address-list (when (and addr (mu4e-personal-addresses)
(cl-find addr mu4e-user-mail-address-list (cl-find addr (mu4e-personal-addresses)
:test (lambda (s1 s2) :test (lambda (s1 s2)
(eq t (compare-strings s1 nil nil s2 nil nil t))))) (eq t (compare-strings s1 nil nil s2 nil nil t)))))
t)) t))
@ -182,10 +182,10 @@ see its docstring)."
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defun mu4e~guess-maildir (path) (defun mu4e~guess-maildir (path)
"Guess the maildir for some path, or nil if cannot find it." "Guess the maildir for some path, or nil if cannot find it."
(let ((idx (string-match mu4e-maildir path))) (let ((idx (string-match (mu4e-root-maildir) path)))
(when (and idx (zerop idx)) (when (and idx (zerop idx))
(replace-regexp-in-string (replace-regexp-in-string
mu4e-maildir (mu4e-root-maildir)
"" ""
(expand-file-name (expand-file-name
(concat path "/../..")))))) (concat path "/../.."))))))
@ -322,7 +322,7 @@ Function will return the cdr of the list element."
(dolist (dentry dentries) (dolist (dentry dentries)
(when (and (booleanp (cadr dentry)) (cadr dentry)) (when (and (booleanp (cadr dentry)) (cadr dentry))
(if (file-accessible-directory-p (if (file-accessible-directory-p
(concat mu4e-maildir "/" mdir "/" (car dentry) "/cur")) (concat (mu4e-root-maildir) "/" mdir "/" (car dentry) "/cur"))
(setq dirs (cons (concat mdir (car dentry)) dirs))) (setq dirs (cons (concat mdir (car dentry)) dirs)))
(unless (member (car dentry) '("cur" "new" "tmp")) (unless (member (car dentry) '("cur" "new" "tmp"))
(setq dirs (append dirs (mu4e~get-maildirs-1 path (setq dirs (append dirs (mu4e~get-maildirs-1 path
@ -332,7 +332,7 @@ Function will return the cdr of the list element."
(defvar mu4e-cache-maildir-list nil (defvar mu4e-cache-maildir-list nil
"Whether to cache the list of maildirs; set it to t if you find "Whether to cache the list of maildirs; set it to t if you find
that generating the list on the fly is too slow. If you do, you that generating the list on the fly is too slow. If you do, you
can set `mu4e-maildir-list' to nil to force regenerating the can set `(mu4e-root-maildir)-list' to nil to force regenerating the
cache the next time `mu4e-get-maildirs' gets called.") cache the next time `mu4e-get-maildirs' gets called.")
(defvar mu4e-maildir-list nil (defvar mu4e-maildir-list nil
@ -344,14 +344,13 @@ relative paths (ie., /archive, /sent etc.). Most of the work is
done in `mu4e~get-maildirs-1'. Note, these results are /cached/ done in `mu4e~get-maildirs-1'. Note, these results are /cached/
if `mu4e-cache-maildir-list' is customized to non-nil. In that case, if `mu4e-cache-maildir-list' is customized to non-nil. In that case,
the list of maildirs will not change until you restart mu4e." the list of maildirs will not change until you restart mu4e."
(unless mu4e-maildir (mu4e-error "`mu4e-maildir' is not defined"))
(unless (and mu4e-maildir-list mu4e-cache-maildir-list) (unless (and mu4e-maildir-list mu4e-cache-maildir-list)
(setq mu4e-maildir-list (setq mu4e-maildir-list
(sort (sort
(append (append
(when (file-accessible-directory-p (when (file-accessible-directory-p
(concat mu4e-maildir "/cur")) '("/")) (concat (mu4e-root-maildir) "/cur")) '("/"))
(mu4e~get-maildirs-1 mu4e-maildir "/")) (mu4e~get-maildirs-1 (mu4e-root-maildir) "/"))
(lambda (s1 s2) (string< (downcase s1) (downcase s2)))))) (lambda (s1 s2) (string< (downcase s1) (downcase s2))))))
mu4e-maildir-list) mu4e-maildir-list)
@ -389,7 +388,7 @@ maildirs under `mu4e-maildir'."
"Like `mu4e-ask-maildir', but check for existence of the maildir, "Like `mu4e-ask-maildir', but check for existence of the maildir,
and offer to create it if it does not exist yet." and offer to create it if it does not exist yet."
(let* ((mdir (mu4e-ask-maildir prompt)) (let* ((mdir (mu4e-ask-maildir prompt))
(fullpath (concat mu4e-maildir mdir))) (fullpath (concat (mu4e-root-maildir) mdir)))
(unless (file-directory-p fullpath) (unless (file-directory-p fullpath)
(and (yes-or-no-p (and (yes-or-no-p
(mu4e-format "%s does not exist. Create now?" fullpath)) (mu4e-format "%s does not exist. Create now?" fullpath))
@ -724,37 +723,27 @@ completion; for testing/debugging."
(defun mu4e~check-requirements () (defun mu4e~check-requirements ()
"Check for the settings required for running mu4e." "Check for the settings required for running mu4e."
(unless (>= emacs-major-version 23) (unless (>= emacs-major-version 25)
(mu4e-error "Emacs >= 23.x is required for mu4e")) (mu4e-error "Emacs >= 25.x is required for mu4e"))
(when mu4e~server-props (when mu4e~server-props
(let ((version (plist-get mu4e~server-props :version)) (unless (string= (mu4e-server-version) mu4e-mu-version)
(mux (plist-get mu4e~server-props :mux))) (mu4e-error "mu server has version %s, but we need %s"
(unless (or (string= version mu4e-mu-version) mux) (mu4e-server-version) mu4e-mu-version)))
(mu4e-error "mu server has version %s, but we need %s"
version mu4e-mu-version))))
(unless (and mu4e-mu-binary (file-executable-p mu4e-mu-binary)) (unless (and mu4e-mu-binary (file-executable-p mu4e-mu-binary))
(mu4e-error "Please set `mu4e-mu-binary' to the full path to the mu (mu4e-error "Please set `mu4e-mu-binary' to the full path to the mu
binary.")) binary."))
(unless mu4e-maildir
(mu4e-error "Please set `mu4e-maildir' to the full path to your
Maildir directory."))
;; expand mu4e-maildir, mu4e-attachment-dir
(setq mu4e-maildir (expand-file-name mu4e-maildir))
(unless (mu4e-create-maildir-maybe mu4e-maildir)
(mu4e-error "%s is not a valid maildir directory" mu4e-maildir))
(dolist (var '(mu4e-sent-folder mu4e-drafts-folder (dolist (var '(mu4e-sent-folder mu4e-drafts-folder
mu4e-trash-folder)) mu4e-trash-folder))
(unless (and (boundp var) (symbol-value var)) (unless (and (boundp var) (symbol-value var))
(mu4e-error "Please set %S" var)) (mu4e-error "Please set %S" var))
(unless (functionp (symbol-value var)) ;; functions are okay, too (unless (functionp (symbol-value var)) ;; functions are okay, too
(let* ((dir (symbol-value var)) (let* ((dir (symbol-value var))
(path (concat mu4e-maildir dir))) (path (concat (mu4e-root-maildir) dir)))
(unless (string= (substring dir 0 1) "/") (unless (string= (substring dir 0 1) "/")
(mu4e-error "%S must start with a '/'" dir)) (mu4e-error "%S must start with a '/'" dir))
(unless (mu4e-create-maildir-maybe path) (unless (mu4e-create-maildir-maybe path)
(mu4e-error "%s (%S) does not exist" path var)))))) (mu4e-error "%s (%S) does not exist" path var))))))
(defun mu4e-running-p () (defun mu4e-running-p ()
"Whether mu4e is running. "Whether mu4e is running.
Checks whether the server process is live." Checks whether the server process is live."
@ -787,14 +776,15 @@ nothing."
mu4e-compose-complete-only-after mu4e-compose-complete-only-after
mu4e~contacts-tstamp))) mu4e~contacts-tstamp)))
(defun mu4e~pong-handler (props func) (defun mu4e~pong-handler (data func)
"Handle 'pong' responses from the mu server." "Handle 'pong' responses from the mu server."
(setq mu4e~server-props props) ;; save props from the server (setq mu4e~server-props (plist-get data :props)) ;; save info from the server
(let ((doccount (plist-get props :doccount))) (let ((doccount (plist-get mu4e~server-props :doccount)))
(mu4e~check-requirements) (mu4e~check-requirements)
(mu4e~context-autoswitch nil mu4e-context-policy)
(when func (funcall func)) (when func (funcall func))
(when (zerop doccount) (when (zerop doccount)
(mu4e-message "Store is empty; (re)indexing. This can take a while.") ; (mu4e-message "Store is empty; (re)indexing. This may take a while.") ;
(mu4e-update-index)) (mu4e-update-index))
(when (and mu4e-update-interval (null mu4e~update-timer)) (when (and mu4e-update-interval (null mu4e~update-timer))
(setq mu4e~update-timer (setq mu4e~update-timer
@ -811,11 +801,6 @@ non-nil). Otherwise, check various requireme`'nts, then start mu4e.
When successful, call FUNC (if non-nil) afterwards." When successful, call FUNC (if non-nil) afterwards."
;; if we're already running, simply go to the main view ;; if we're already running, simply go to the main view
(unless (mu4e-running-p) ;; already running? (unless (mu4e-running-p) ;; already running?
;; no! try to set a context, do some checks, set up pong handler and ping
;; the server maybe switch the context
(mu4e~context-autoswitch nil mu4e-context-policy)
(mu4e~check-requirements)
;; when it's visible, re-draw the main view when there are changes. ;; when it's visible, re-draw the main view when there are changes.
(add-hook 'mu4e-index-updated-hook (add-hook 'mu4e-index-updated-hook
(lambda() (lambda()
@ -823,7 +808,7 @@ When successful, call FUNC (if non-nil) afterwards."
(when (and (buffer-live-p mainbuf) (get-buffer-window mainbuf)) (when (and (buffer-live-p mainbuf) (get-buffer-window mainbuf))
(mu4e~start 'mu4e~main-view)))))) (mu4e~start 'mu4e~main-view))))))
(setq mu4e-pong-func (lambda (props) (mu4e~pong-handler props func))) (setq mu4e-pong-func (lambda (info) (mu4e~pong-handler info func)))
(mu4e~proc-ping (mu4e~proc-ping
(mapcar ;; send it a list of queries we'd like to see read/unread info (mapcar ;; send it a list of queries we'd like to see read/unread info
;; for. ;; for.
@ -906,12 +891,7 @@ Also scrolls to the final line, and update the progress throbber."
(defun mu4e-update-index () (defun mu4e-update-index ()
"Update the mu4e index." "Update the mu4e index."
(interactive) (interactive)
(unless mu4e-maildir (mu4e~proc-index mu4e-index-cleanup mu4e-index-lazy-check))
(mu4e-error "`mu4e-maildir' is not defined"))
(mu4e~proc-index mu4e-maildir
mu4e-user-mail-address-list
mu4e-index-cleanup
mu4e-index-lazy-check))
(defvar mu4e~update-buffer nil (defvar mu4e~update-buffer nil
"Internal, store the buffer of the update process when "Internal, store the buffer of the update process when

View File

@ -1,6 +1,6 @@
;;; mu4e-vars.el -- part of mu4e, the mu mail user agent -*- lexical-binding: t -*- ;;; mu4e-vars.el -- part of mu4e, the mu mail user agent -*- lexical-binding: t -*-
;; ;;
;; Copyright (C) 2011-2019 Dirk-Jan C. Binnema ;; Copyright (C) 2011-2020 Dirk-Jan C. Binnema
;; Author: Dirk-Jan C. Binnema <djcb@djcbsoftware.nl> ;; Author: Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
;; Maintainer: Dirk-Jan C. Binnema <djcb@djcbsoftware.nl> ;; Maintainer: Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
@ -29,6 +29,7 @@
(require 'mu4e-meta) (require 'mu4e-meta)
(require 'message) (require 'message)
(declare-function mu4e-error "mu4e-utils")
(defgroup mu4e nil (defgroup mu4e nil
"mu4e - mu for emacs" "mu4e - mu for emacs"
@ -50,13 +51,8 @@ path."
:group 'mu4e :group 'mu4e
:safe 'stringp) :safe 'stringp)
(defcustom mu4e-maildir (expand-file-name "~/Maildir") (make-obsolete-variable 'mu4e-maildir
"The absolute file system path to your Maildir. "determined by server; see `mu4e-root-maildir'." "1.3.8")
Must not be a symbolic link, and after starting mu4e, cannot
change until after quitting."
:type 'directory
:safe 'stringp
:group 'mu4e)
(defcustom mu4e-org-support t (defcustom mu4e-org-support t
"Support org-mode links." "Support org-mode links."
@ -172,9 +168,10 @@ matched case-insensitively."
;; don't use the older vars anymore ;; don't use the older vars anymore
(make-obsolete-variable 'mu4e-user-mail-address-regexp (make-obsolete-variable 'mu4e-user-mail-address-regexp
'mu4e-user-mail-address-list "0.9.9.x") 'mu4e-user-mail-address-list "0.9.9.x")
(make-obsolete-variable 'mu4e-my-email-addresses (make-obsolete-variable 'mu4e-my-email-addresses
'mu4e-user-mail-address-list "0.9.9.x") 'mu4e-user-mail-address-list "0.9.9.x")
(make-obsolete-variable 'mu4e-user-mail-address-list
"determined by server; see `mu4e-personal-addresses'." "1.3.8")
(defcustom mu4e-use-fancy-chars nil (defcustom mu4e-use-fancy-chars nil
"When set, allow fancy (Unicode) characters for marks/threads. "When set, allow fancy (Unicode) characters for marks/threads.
@ -365,10 +362,8 @@ The setting is a symbol:
(defcustom mu4e-compose-complete-only-personal nil (defcustom mu4e-compose-complete-only-personal nil
"Whether to consider only 'personal' e-mail addresses for completion. "Whether to consider only 'personal' e-mail addresses for completion.
That is, addresses from messages where user was explicitly in one That is, addresses from messages where user was explicitly in one
of the address fields (this excludes mailing list messages). See of the address fields (this excludes mailing list messages).
`mu4e-user-mail-address-list' and the mu-index manpage for These addresses are the ones specified with `mu init'."
details for details (in particular, how to define your own e-mail
addresses)."
:type 'boolean :type 'boolean
:group 'mu4e-compose) :group 'mu4e-compose)
@ -926,13 +921,42 @@ We need to keep this information around to quickly re-sort
subsets of the contacts in the completions function in subsets of the contacts in the completions function in
mu4e-compose.") mu4e-compose.")
(defvar mu4e~server-props nil
"Properties we receive from the mu4e server process.
\(in the 'pong-handler').")
(defvar mu4e~headers-last-query nil (defvar mu4e~headers-last-query nil
"The present (most recent) query.") "The present (most recent) query.")
(defvar mu4e~server-props nil
"Information we receive from the mu4e server process \(in the 'pong-handler').")
(defun mu4e-root-maildir()
"Get the root maildir."
(let ((root-maildir (and mu4e~server-props
(plist-get mu4e~server-props :root-maildir))))
(unless root-maildir
(mu4e-error "root maildir unknown; did you start mu4e?"))
root-maildir))
(defun mu4e-database-path()
"Get the mu4e database path"
(let ((path (and mu4e~server-props
(plist-get mu4e~server-props :database-path))))
(unless path
(mu4e-error "database-path unknown; did you start mu4e?"))
path))
(defun mu4e-personal-addresses()
"Get the user's personal addresses, if any. If none are set on the server-side,
fall back to the obsolete `mu4e-user-mail-address-list'."
(let ((addrs (and mu4e~server-props
(plist-get mu4e~server-props :personal-addresses))))
(if addrs addrs mu4e-user-mail-address-list)))
(defun mu4e-server-version()
"Get the server version, which should match mu4e's."
(let ((version (and mu4e~server-props (plist-get mu4e~server-props :version))))
(unless version
(mu4e-error "version unknown; did you start mu4e?"))
version))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; our handlers funcs these handler funcs define what happens when we receive a ;; our handlers funcs these handler funcs define what happens when we receive a

View File

@ -1,6 +1,6 @@
;;; mu4e-view.el -- part of mu4e, the mu mail user agent -*- lexical-binding: t -*- ;;; mu4e-view.el -- part of mu4e, the mu mail user agent -*- lexical-binding: t -*-
;; ;;
;; Copyright (C) 2011-2018 Dirk-Jan C. Binnema ;; Copyright (C) 2011-2020 Dirk-Jan C. Binnema
;; Author: Dirk-Jan C. Binnema <djcb@djcbsoftware.nl> ;; Author: Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
;; Maintainer: Dirk-Jan C. Binnema <djcb@djcbsoftware.nl> ;; Maintainer: Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
@ -392,7 +392,7 @@ article-mode."
(run-hooks 'gnus-article-decode-hook) (run-hooks 'gnus-article-decode-hook)
(let ((mu4e~view-rendering t) ; customize gnus in mu4e (let ((mu4e~view-rendering t) ; customize gnus in mu4e
(max-specpdl-size mu4e-view-max-specpdl-size) (max-specpdl-size mu4e-view-max-specpdl-size)
(gnus-icalendar-additional-identities mu4e-user-mail-address-list)) (gnus-icalendar-additional-identities (mu4e-personal-addresses)))
(gnus-article-prepare-display)) (gnus-article-prepare-display))
(mu4e-view-mode) (mu4e-view-mode)
(setq mu4e~view-message msg) (setq mu4e~view-message msg)

View File

@ -217,6 +217,7 @@ After these steps, @t{mu4e} should be ready to go!
* Requirements:: What is needed * Requirements:: What is needed
* Installation:: How to install @t{mu} and @t{mu4e} * Installation:: How to install @t{mu} and @t{mu4e}
* Getting mail:: Getting mail from a server * Getting mail:: Getting mail from a server
* Initializing the message store:: Settings things up
* Indexing your messages:: Creating and maintaining the index * Indexing your messages:: Creating and maintaining the index
* Basic configuration:: Settings for @t{mu4e} * Basic configuration:: Settings for @t{mu4e}
* Folders:: Setting up standard folders * Folders:: Setting up standard folders
@ -230,14 +231,14 @@ After these steps, @t{mu4e} should be ready to go!
@section Requirements @section Requirements
@t{mu}/@t{mu4e} are known to work on a wide variety of Unix- and @t{mu}/@t{mu4e} are known to work on a wide variety of Unix- and
Unix-like systems, including many Linux distributions, OS X and FreeBSD, Unix-like systems, including many Linux distributions, OS X and
and even on MS-Windows (with Cygwin). @command{emacs} 23 or 24 FreeBSD, and even on MS-Windows (with Cygwin). @command{emacs} 24 or
(recommended) is required, as well as higher is required, as well as
Xapian@footnote{@url{https://xapian.org/}} and Xapian@footnote{@url{https://xapian.org/}} and
GMime@footnote{@url{http://spruce.sourceforge.net/gmime/}}. GMime@footnote{@url{http://spruce.sourceforge.net/gmime/}}.
@t{mu} has optional support for the Guile 2.x (Scheme) programming @t{mu} has optional support for the Guile 2.x (Scheme) programming
language. There are also some GUI-tools, which require GTK+ 3.x and language. There are also some GUI-toys, which require GTK+ 3.x and
Webkit. Webkit.
If you intend to compile @t{mu} yourself, you need to have the typical If you intend to compile @t{mu} yourself, you need to have the typical
@ -249,16 +250,17 @@ you also need the development packages for GTK+, Webkit and Guile.
@node Installation @node Installation
@section Installation @section Installation
@t{mu4e} is part of @t{mu} --- by installing the latter, the former is installed @t{mu4e} is part of @t{mu} --- by installing the latter, the former is
as well. Some Linux distributions provide packaged versions of installed as well. Some Linux distributions provide packaged versions
@t{mu}/@t{mu4e}; if you can use those, there is no need to compile anything of @t{mu}/@t{mu4e}; if you can use those, there is no need to compile
yourself. However, if there are no packages for your distribution, if they are anything yourself. However, if there are no packages for your
outdated, or if you want to use the latest development versions, you can distribution, if they are outdated, or if you want to use the latest
follow the steps below. development versions, you can follow the steps below.
First, you need make sure you have the necessary dependencies; the details First, you need make sure you have the necessary dependencies; the
depend on your distribution. If you're using another distribution (or another details depend on your distribution. If you're using another
OS), the below can at least be helpful in identifying the packages to install. distribution (or another OS), the below can at least be helpful in
identifying the packages to install.
We provide some instructions for Debian, Ubuntu and Fedora; if those do not We provide some instructions for Debian, Ubuntu and Fedora; if those do not
apply to you, you can follow either @ref{Building from a release tarball} or apply to you, you can follow either @ref{Building from a release tarball} or
@ -356,46 +358,74 @@ through things step-by-step.
@node Getting mail @node Getting mail
@section Getting mail @section Getting mail
In order for @t{mu} (and, by extension, @t{mu4e}) to work, you need to have In order for @t{mu} (and, by extension, @t{mu4e}) to work, you need to
your e-mail messages stored in a have your e-mail messages stored in a
@emph{maildir}@footnote{@url{https://en.wikipedia.org/wiki/Maildir}; in this @emph{maildir}@footnote{@url{https://en.wikipedia.org/wiki/Maildir};
manual we use the term `maildir' for both the standard and the hierarchy of in this manual we use the term `maildir' for both the standard and the
maildirs that store your messages} --- a specific directory structure with hierarchy of maildirs that store your messages} --- a specific
one-file-per-message. If you are already using a maildir, you are lucky. If directory structure with one-file-per-message. If you are already
not, some setup is required: using a maildir, you are lucky. If not, some setup is required:
@itemize @itemize
@item @emph{Using an external IMAP or POP server} --- if you are using an @item @emph{Using an external IMAP or POP server} --- if you are using an
@abbr{IMAP} or @abbr{POP} server, you can use tools like @t{getmail}, @abbr{IMAP} or @abbr{POP} server, you can use tools like @t{getmail},
@t{fetchmail}, @t{offlineimap} or @t{isync} to download your messages into a @t{fetchmail}, @t{offlineimap} or @t{isync} to download your messages
maildir (@file{~/Maildir}, often). Because it is such a common case, there is into a maildir (@file{~/Maildir}, often). Because it is such a common
a full example of setting @t{mu4e} up with @t{offlineimap} and Gmail; case, there is a full example of setting @t{mu4e} up with
@pxref{Gmail configuration}. @t{offlineimap} and Gmail; @pxref{Gmail configuration}.
@item @emph{Using a local mail server} --- if you are using a local mail-server @item @emph{Using a local mail server} --- if you are using a local mail-server
(such as @t{postfix} or @t{qmail}), you can teach them to deliver into a (such as @t{postfix} or @t{qmail}), you can teach them to deliver into
maildir as well, maybe in combination with @t{procmail}. A bit of googling a maildir as well, maybe in combination with @t{procmail}. A bit of
should be able to provide you with the details. googling should be able to provide you with the details.
@end itemize @end itemize
@node Initializing the message store
@section Initializing the message store
The first time your run @t{mu}, you need to initialize its store
(database). The default location for that is @t{~/.cache/mu/xapian},
but you can change this using the @t{--muhome} option, and remember to
pass that to the other commands as well.
Assuming that your maildir is at @file{~/Maildir}, we issue the
following command:
@example
$ mu init --maildir=~/Maildir
@end example
Optionally, you can add some e-mail addresses, so @t{mu} recognizes
them as yours:
@example
$ mu init --maildir=~/Maildir --my-address=jim@@example.com --my-address=bob@@example.com
@end example
@t{mu} remembers the maildir and your addresses and uses them when
indexing messages. If you want to change them, you need to @t{init}
once again.
If you want to see the current values, you can use @t{mu info}.
@node Indexing your messages @node Indexing your messages
@section Indexing your messages @section Indexing your messages
After you have succeeded in @ref{Getting mail}, we need to @emph{index} the After you have succeeded in @ref{Getting mail} and initialized the
messages. That is --- we need to scan the messages in the maildir and store the message database, we need to @emph{index} the messages. That is --- we
information about them in a special database. We can do that from @t{mu4e} --- need to scan the messages in the maildir and store the information
@ref{Main view}, but the first time, it is a good idea to run it from the about them in a special database.
command line, which makes it easier to verify that everything works correctly.
We can do that from @t{mu4e} --- @ref{Main view}, but the first time,
it is a good idea to run it from the command line, which makes it
easier to verify that everything works correctly.
Assuming that your maildir is at @file{~/Maildir}, we issue the following Assuming that your maildir is at @file{~/Maildir}, we issue the following
command: command:
@example @example
$ mu index --maildir=~/Maildir $ mu index
@end example @end example
This should scan your @file{~/Maildir}@footnote{In most cases, you do not even This should scan your messages and fill the database, and give
need to provide the @t{--maildir=~/Maildir} since it is the default; see the progress information while doing so.
@t{mu-index} man-page for details} and fill the database, and give progress
information while doing so.
The indexing process may take a few minutes the first time you do it The indexing process may take a few minutes the first time you do it
(for thousands of e-mails); afterwards it is much faster, since @t{mu} (for thousands of e-mails); afterwards it is much faster, since @t{mu}
@ -448,19 +478,15 @@ situation. See @ref{Dynamic folders} for details.}:
@lisp @lisp
;; these are actually the defaults ;; these are actually the defaults
(setq (setq
mu4e-maildir "~/Maildir" ;; top-level Maildir
mu4e-sent-folder "/sent" ;; folder for sent messages mu4e-sent-folder "/sent" ;; folder for sent messages
mu4e-drafts-folder "/drafts" ;; unfinished messages mu4e-drafts-folder "/drafts" ;; unfinished messages
mu4e-trash-folder "/trash" ;; trashed messages mu4e-trash-folder "/trash" ;; trashed messages
mu4e-refile-folder "/archive") ;; saved messages mu4e-refile-folder "/archive") ;; saved messages
@end lisp @end lisp
Note, @code{mu4e-maildir} takes an actual filesystem-path, the other Note, the folder names are all relative to the root-maildir (see the
folder names are all relative to @code{mu4e-maildir}. Also note that output of @t{mu info}). If you use @t{mu4e-context}, see @ref{Contexts
this must @emph{not} be a symbolic link. and special folders} for what that means for these special folders.
If you use @t{mu4e-context}, see @ref{Contexts and special folders} for
what that means for these special folders.
@node Retrieval and indexing @node Retrieval and indexing
@section Retrieval and indexing with mu4e @section Retrieval and indexing with mu4e
@ -684,9 +710,9 @@ The main view looks something like the following:
Bookmarks Bookmarks
* [bu] Unread messages (26217/26217) * [bu] Unread messages (26217/26217)
* [bt] Today's messages (2/8) * [bt] Today's messages (2/8)
* [bw] Last 7 days (7/34) * [bw] Last 7 days (7/34)
* [bp] Messages with images (276/2315) * [bp] Messages with images (276/2315)
Misc Misc
@ -710,11 +736,11 @@ Let's walk through the menu.
First, the @emph{Basics}: First, the @emph{Basics}:
@itemize @itemize
@item @t{[j]ump to some maildir}: after pressing @key{j} (``jump''), @item @t{[j]ump to some maildir}: after pressing @key{j} (``jump''),
@t{mu4e} asks you for a maildir to visit. These are the maildirs you set in @t{mu4e} asks you for a maildir to visit. These are the maildirs you
@ref{Basic configuration} and any of your own. If you choose @key{o} set in @ref{Basic configuration} and any of your own. If you choose
(``other'') or @key{/}, you can choose from all maildirs under @key{o} (``other'') or @key{/}, you can choose from all maildirs under
@code{mu4e-maildir}. After choosing a maildir, the messages in that maildir the root-maildir. After choosing a maildir, the messages in that
are listed, in the @ref{Headers view}. maildir are listed, in the @ref{Headers view}.
@item @t{enter a [s]earch query}: after pressing @key{s}, @t{mu4e} asks @item @t{enter a [s]earch query}: after pressing @key{s}, @t{mu4e} asks
you for a search query, and after entering one, shows the results in the you for a search query, and after entering one, shows the results in the
@ref{Headers view}. @ref{Headers view}.
@ -2630,9 +2656,8 @@ invoke those function even in that case.
the current context is also visible in the mode-line when in the current context is also visible in the mode-line when in
headers, view or main mode. headers, view or main mode.
@item You can set any kind of variable; including settings for mail servers etc. @item You can set any kind of variable; including settings for mail servers etc.
However, settings such as @code{mu4e-maildir} and @code{mu4e-mu-home} However, settings such as @code{mu4e-mu-home} are not changeable after
are not changeable after they have been set without quitting @t{mu4e} they have been set without quitting @t{mu4e} first.
first.
@item @code{leave-func} (if defined) for the context we are leaving, is invoked @item @code{leave-func} (if defined) for the context we are leaving, is invoked
before the @code{enter-func} (if defined) of the before the @code{enter-func} (if defined) of the
context we are entering. context we are entering.
@ -3512,10 +3537,6 @@ see, most of it is commented-out.
;; use mu4e for e-mail in emacs ;; use mu4e for e-mail in emacs
(setq mail-user-agent 'mu4e-user-agent) (setq mail-user-agent 'mu4e-user-agent)
;; Only needed if your maildir is _not_ ~/Maildir
;; Must be a real dir, not a symlink
;;(setq mu4e-maildir "/home/user/Maildir")
;; these must start with a "/", and must exist ;; these must start with a "/", and must exist
;; (i.e.. /home/user/Maildir/sent must exist) ;; (i.e.. /home/user/Maildir/sent must exist)
;; you use e.g. 'mu mkdir' to make the Maildirs if they don't ;; you use e.g. 'mu mkdir' to make the Maildirs if they don't
@ -3549,10 +3570,8 @@ customize.
;; use mu4e for e-mail in emacs ;; use mu4e for e-mail in emacs
(setq mail-user-agent 'mu4e-user-agent) (setq mail-user-agent 'mu4e-user-agent)
;; path to our Maildir directory ;; the next are relative to the root maildir
(setq mu4e-maildir "/home/user/Maildir") ;; (see `mu info`).
;; the next are relative to `mu4e-maildir'
;; instead of strings, they can be functions too, see ;; instead of strings, they can be functions too, see
;; their docstring or the chapter 'Dynamic folders' ;; their docstring or the chapter 'Dynamic folders'
(setq mu4e-sent-folder "/sent" (setq mu4e-sent-folder "/sent"
@ -3718,9 +3737,6 @@ Next step: let's make a @t{mu4e} configuration for this:
;; use mu4e for e-mail in emacs ;; use mu4e for e-mail in emacs
(setq mail-user-agent 'mu4e-user-agent) (setq mail-user-agent 'mu4e-user-agent)
;; default
;; (setq mu4e-maildir "~/Maildir")
(setq mu4e-drafts-folder "/[Gmail].Drafts") (setq mu4e-drafts-folder "/[Gmail].Drafts")
(setq mu4e-sent-folder "/[Gmail].Sent Mail") (setq mu4e-sent-folder "/[Gmail].Sent Mail")
(setq mu4e-trash-folder "/[Gmail].Trash") (setq mu4e-trash-folder "/[Gmail].Trash")
@ -4207,7 +4223,6 @@ github-repository.
@menu @menu
* Fancy characters:: Non-ascii characters in the UI * Fancy characters:: Non-ascii characters in the UI
* Multiple accounts:: (Obsolete) the old way to deal with multiple accounts
* Refiling messages:: Moving message to some archive folder * Refiling messages:: Moving message to some archive folder
* Saving outgoing messages:: Automatically save sent messages * Saving outgoing messages:: Automatically save sent messages
* Confirmation before sending:: Check messages before sending * Confirmation before sending:: Check messages before sending
@ -4242,121 +4257,6 @@ try the @emph{unicode-fonts} package:
(unicode-fonts-setup) (unicode-fonts-setup)
@end lisp @end lisp
@node Multiple accounts
@section Multiple accounts
@b{Note}: for @t{mu4e} version 0.9.16 and higher, the recommended way
to deal with multiple accounts is through @t{mu4e}'s built-in
@ref{Contexts} system. For older versions, the below still works.
Using @t{mu4e} with multiple email accounts is fairly easy. Although
variables such as @code{user-mail-address}, @code{mu4e-sent-folder},
@code{message-*}, @code{smtpmail-*}, etc. typically only take one value,
it is easy to change their values using @code{mu4e-compose-pre-hook}.
The setup described here is one way of doing this (though certainly not
the only way).
This setup assumes that you have multiple mail accounts under
@code{mu4e-maildir}. As an example, we'll use @t{~/Maildir/Account1}
and @t{~/Maildir/Account2}, but the setup works just as well if
@code{mu4e-maildir} points to something else.
First, you need to make sure that all variables that you wish to change
based on user account are set to some initial value. So set up your
environment with e.g., your main account:
@lisp
(setq mu4e-sent-folder "/Account1/Saved Items"
mu4e-drafts-folder "/Account1/Drafts"
user-mail-address "my.address@@account1.example.com"
smtpmail-default-smtp-server "smtp.account1.example.com"
smtpmail-local-domain "account1.example.com"
smtpmail-smtp-server "smtp.account1.example.com"
smtpmail-stream-type 'starttls
smtpmail-smtp-service 25)
@end lisp
Then create a variable @code{my-mu4e-account-alist}, which should
contain a list for each of your accounts. Each list should start with
the account name, (which @emph{must} be identical to the account's
directory name under @t{~/Maildir}), followed by @code{(variable
value)} pairs:
@lisp
(defvar my-mu4e-account-alist
'(("Account1"
(mu4e-sent-folder "/Account1/Saved Items")
(mu4e-drafts-folder "/Account1/Drafts")
(user-mail-address "my.address@@account1.example.com")
(smtpmail-default-smtp-server "smtp.account1.example.com")
(smtpmail-local-domain "account1.example.com")
(smtpmail-smtp-user "username1")
(smtpmail-smtp-server "smtp.account1.example.com")
(smtpmail-stream-type starttls)
(smtpmail-smtp-service 25))
("Account2"
(mu4e-sent-folder "/Account2/Saved Items")
(mu4e-drafts-folder "/Account2/Drafts")
(user-mail-address "my.address@@account2.example.com")
(smtpmail-default-smtp-server "smtp.account2.example.com")
(smtpmail-local-domain "account2.example.com")
(smtpmail-smtp-user "username2")
(smtpmail-smtp-server "smtp.account2.example.com")
(smtpmail-stream-type starttls)
(smtpmail-smtp-service 587))))
@end lisp
You can put any variable you want in the account lists, just make sure
that you put in @emph{all} the variables that differ for each account.
Variables that do not differ need not be included. For example, if you
use the same SMTP server for both accounts, you don't need to include
the SMTP-related variables in @code{my-mu4e-account-alist}.
Note that some SMTP servers (such as Gmail) require the SMTP username to
match the user mail address. In this case, your mail appears to
originate from whichever SMTP account you use. Thus unless you are
certain your SMTP server does not have this requirement, you should
generally use different SMTP account credentials for each mail account.
Now, the following function can be used to select an account and set the
variables in @code{my-mu4e-account-alist} to the correct values:
@lisp
(defun my-mu4e-set-account ()
"Set the account for composing a message."
(let* ((account
(if mu4e-compose-parent-message
(let ((maildir (mu4e-message-field mu4e-compose-parent-message :maildir)))
(string-match "/\\(.*?\\)/" maildir)
(match-string 1 maildir))
(completing-read (format "Compose with account: (%s) "
(mapconcat #'(lambda (var) (car var))
my-mu4e-account-alist "/"))
(mapcar #'(lambda (var) (car var)) my-mu4e-account-alist)
nil t nil nil (caar my-mu4e-account-alist))))
(account-vars (cdr (assoc account my-mu4e-account-alist))))
(if account-vars
(mapc #'(lambda (var)
(set (car var) (cadr var)))
account-vars)
(error "No email account found"))))
@end lisp
This function then needs to be added to @code{mu4e-compose-pre-hook}:
@lisp
(add-hook 'mu4e-compose-pre-hook 'my-mu4e-set-account)
@end lisp
This way, @code{my-mu4e-set-account} is called every time you edit a
message. If you compose a new message, it simply asks you for the
account you wish to send the message from (TAB completion works). If
you're replying or forwarding a message, or editing an existing draft,
the account is chosen automatically, based on the first component of the
maildir of the message being replied to, forwarded or edited (i.e., the
directory under @t{~/Maildir}).
@node Refiling messages @node Refiling messages
@section Refiling messages @section Refiling messages