From b37bfba223b7d54e58b95564292c915f0e0953bb Mon Sep 17 00:00:00 2001 From: Frank Benkstein Date: Fri, 19 Apr 2024 16:24:26 +0200 Subject: [PATCH 001/305] mu-move: remove debug print --- mu/mu-cmd-move.cc | 3 --- 1 file changed, 3 deletions(-) diff --git a/mu/mu-cmd-move.cc b/mu/mu-cmd-move.cc index 46070af1c..7ad7a483c 100644 --- a/mu/mu-cmd-move.cc +++ b/mu/mu-cmd-move.cc @@ -50,9 +50,6 @@ Mu::mu_cmd_move(Mu::Store& store, const Options& opts) "Must have at least one of destination and flags"); else if (!dest.empty()) { const auto mdirs{store.maildirs()}; - mu_printerrln("XXXX"); - for (auto&& m:mdirs) - mu_printerrln("m:'{}'", m); if (!seq_some(mdirs, [&](auto &&d){ return d == dest;})) return Err(Error{Error::Code::InvalidArgument, From 4f72e2656dad879a031378d4e2757125f275d95e Mon Sep 17 00:00:00 2001 From: "Dirk-Jan C. Binnema" Date: Tue, 16 Apr 2024 19:03:08 +0300 Subject: [PATCH 002/305] mu4e: use message-field-value Simplify ...instead of save-restriction/message-narrow-to-headers/message-fetch-field. --- mu4e/mu4e-compose.el | 136 +++++++++++++++++++------------------------ mu4e/mu4e-message.el | 5 +- mu4e/mu4e-view.el | 2 +- 3 files changed, 65 insertions(+), 78 deletions(-) diff --git a/mu4e/mu4e-compose.el b/mu4e/mu4e-compose.el index 3b458c5f0..3c15903c7 100644 --- a/mu4e/mu4e-compose.el +++ b/mu4e/mu4e-compose.el @@ -441,14 +441,12 @@ If MSGPATH is nil, do nothing." ;; - (temporarily) remove the mail-header separator (setq mu4e--compose-undo buffer-undo-list) (save-excursion - (save-restriction - (message-narrow-to-headers) - (unless (message-fetch-field "Message-ID") - (message-generate-headers '(Message-ID))) - ;; older Emacsen (<= 28 perhaps?) won't update the Date - ;; if there already is one; so make sure it's gone. - (message-remove-header "Date") - (message-generate-headers '(Date Subject From))) + (unless (message-field-value "Message-ID") + (message-generate-headers '(Message-ID))) + ;; older Emacsen (<= 28 perhaps?) won't update the Date + ;; if there already is one; so make sure it's gone. + (message-remove-header "Date") + (message-generate-headers '(Date Subject From)) (mu4e--delimit-headers 'undelimit))) ;; remove separator (defvar mu4e--compose-buffer-max-name-length 48) @@ -487,26 +485,24 @@ message buffer." (let ((buf (find-file-noselect path))) (when buf (with-current-buffer buf - (save-restriction - (message-narrow-to-headers) - (let ((in-reply-to (message-fetch-field "in-reply-to")) - (forwarded-from) - (references (message-fetch-field "references"))) - (unless in-reply-to - (when references - (with-temp-buffer ;; inspired by `message-shorten-references'. - (insert references) - (goto-char (point-min)) - (let ((refs)) - (while (re-search-forward "<[^ <]+@[^ <]+>" nil t) - (push (match-string 0) refs)) - ;; the last will be the first - (setq forwarded-from (car refs)))))) - ;; remove the <> and update the flags on the server-side. - (when (and in-reply-to (string-match "<\\(.*\\)>" in-reply-to)) - (mu4e--server-move (match-string 1 in-reply-to) nil "+R-N")) - (when (and forwarded-from (string-match "<\\(.*\\)>" forwarded-from)) - (mu4e--server-move (match-string 1 forwarded-from) nil "+P-N")))))))) + (let ((in-reply-to (message-field-value "in-reply-to")) + (forwarded-from) + (references (message-field-value "references"))) + (unless in-reply-to + (when references + (with-temp-buffer ;; inspired by `message-shorten-references'. + (insert references) + (goto-char (point-min)) + (let ((refs)) + (while (re-search-forward "<[^ <]+@[^ <]+>" nil t) + (push (match-string 0) refs)) + ;; the last will be the first + (setq forwarded-from (car refs)))))) + ;; remove the <> and update the flags on the server-side. + (when (and in-reply-to (string-match "<\\(.*\\)>" in-reply-to)) + (mu4e--server-move (match-string 1 in-reply-to) nil "+R-N")) + (when (and forwarded-from (string-match "<\\(.*\\)>" forwarded-from)) + (mu4e--server-move (match-string 1 forwarded-from) nil "+P-N"))))))) (defun mu4e--compose-after-save() "Function called immediately after the draft buffer is saved." @@ -546,29 +542,25 @@ appropriate flag at the message forwarded or replied-to." ;; Remove References: if In-Reply-To: is missing. ;; This allows the user to effectively start a new message-thread by ;; removing the In-Reply-To header. - (save-restriction - (message-narrow-to-headers) - (when (eq mu4e-compose-type 'reply) - (unless (message-fetch-field "In-Reply-To") - (message-remove-header "References"))) - (when use-hard-newlines - (mu4e--send-harden-newlines)) - ;; now handle what happens _after_ sending; typically, draft is gone and - ;; the sent message appears in sent. Update flags for related messages, - ;; i.e. for Forwarded ('Passed') and Replied messages, try to set the - ;; appropriate flag at the message forwarded or replied-to. - (add-hook 'message-sent-hook - (lambda () - (save-restriction - (message-narrow-to-headers) - (when-let ((fcc-path (message-fetch-field "Fcc"))) - (mu4e--set-parent-flags fcc-path) - ;; we end up with a ((buried) buffer here, visiting - ;; the fcc-path; not quite sure why. But let's - ;; get rid of it (#2681) - (when-let ((buf (find-buffer-visiting fcc-path))) - (kill-buffer buf))))) - nil t))) + (when (eq mu4e-compose-type 'reply) + (unless (message-field-value "In-Reply-To") + (message-remove-header "References"))) + (when use-hard-newlines + (mu4e--send-harden-newlines)) + ;; now handle what happens _after_ sending; typically, draft is gone and + ;; the sent message appears in sent. Update flags for related messages, + ;; i.e. for Forwarded ('Passed') and Replied messages, try to set the + ;; appropriate flag at the message forwarded or replied-to. + (add-hook 'message-sent-hook + (lambda () + (when-let ((fcc-path (message-field-value "Fcc"))) + (mu4e--set-parent-flags fcc-path) + ;; we end up with a ((buried) buffer here, visiting + ;; the fcc-path; not quite sure why. But let's + ;; get rid of it (#2681) + (when-let ((buf (find-buffer-visiting fcc-path))) + (kill-buffer buf)))) + nil t)) ;;; Crypto (defun mu4e--compose-setup-crypto (parent compose-type) @@ -718,11 +710,9 @@ With HEADERS-ONLY non-nil, only include the headers part." ;; in rare (broken) case, if a message-id is missing use the generated one ;; from mu. (mu4e--delimit-headers) - (save-restriction - (message-narrow-to-headers) - (unless (message-fetch-field "Message-Id") - (goto-char (point-min)) - (insert (format "Message-Id: <%s>\n" (plist-get msg :message-id))))) + (unless (message-field-value "Message-Id") + (goto-char (point-min)) + (insert (format "Message-Id: <%s>\n" (plist-get msg :message-id)))) (mu4e--delimit-headers 'undelimit) (ignore-errors (run-hooks 'gnus-article-decode-hook)) (buffer-substring-no-properties (point-min) (point-max)))) @@ -822,14 +812,12 @@ This is mu4e's version of `message-hidden-headers'.") FUNC is the original function, and ARGS are its arguments. Is this address yours?" (if (mu4e-running-p) - (save-restriction - (message-narrow-to-headers) - (let ((sender (message-fetch-field "from")) - (from (message-fetch-field "sender"))) - (or (and sender (mu4e-personal-or-alternative-address-p - (car (mail-header-parse-address sender)))) - (and from (mu4e-personal-or-alternative-address-p - (car (mail-header-parse-address from))))))) + (let ((sender (message-field-value "from")) + (from (message-field-value "sender"))) + (or (and sender (mu4e-personal-or-alternative-address-p + (car (mail-header-parse-address sender)))) + (and from (mu4e-personal-or-alternative-address-p + (car (mail-header-parse-address from)))))) (apply func args))) (defun mu4e--compose-setup-post (compose-type &optional parent) @@ -986,17 +974,15 @@ must be from current user, as determined through (mu4e--delimit-headers) ;; message-forward expects message-reply-headers to be set up; here we ;; only need message-id & references, rest is for completeness. - (save-restriction - (message-narrow-to-headers) - (setq-local message-reply-headers - (make-full-mail-header - 0 - (or (message-fetch-field "subject") "none") - (or (message-fetch-field "from") "nobody") - (message-fetch-field "date") - (message-fetch-field "message-id" t) - (message-fetch-field "references") - 0 0 ""))) + (setq-local message-reply-headers + (make-full-mail-header + 0 + (or (message-field-value "subject") "none") + (or (message-field-value "from") "nobody") + (message-field-value "date") + (message-field-value "message-id" t) + (message-field-value "references") + 0 0 "")) (mu4e--delimit-headers 'undelimit) (set-buffer-modified-p nil) (message-forward))))) diff --git a/mu4e/mu4e-message.el b/mu4e/mu4e-message.el index f7b805c58..95f8aff53 100644 --- a/mu4e/mu4e-message.el +++ b/mu4e/mu4e-message.el @@ -232,7 +232,8 @@ If MSG is nil, use `mu4e-message-at-point'." If the header appears multiple times, the field values are concatenated, unless FIRST is non-nil, in which case only the -first value is returned. See `message-fetch-field' for details. +first value is returned. See `message-field-value' and +`nessage-fetch-field' for details. Note: this loads the full message file such that any available message header can be used. If the header is part of the MSG @@ -240,7 +241,7 @@ plist, it is much more efficient to get the information from that plist." (with-temp-buffer (insert (mu4e--decoded-message msg 'headers-only)) - (message-fetch-field hdr first))) + (message-field-value hdr first))) ;;; (provide 'mu4e-message) ;;; mu4e-message.el ends here diff --git a/mu4e/mu4e-view.el b/mu4e/mu4e-view.el index 10a2bcec0..033540aa3 100644 --- a/mu4e/mu4e-view.el +++ b/mu4e/mu4e-view.el @@ -685,7 +685,7 @@ determine which browser function to use." (ignore-errors (run-hooks 'gnus-article-decode-hook)) (let ((header (unless skip-headers (cl-loop for field in '("from" "to" "cc" "date" "subject") - when (message-fetch-field field) + when (message-field-value field) concat (format "%s: %s\n" (capitalize field) it)))) (parts (mm-dissect-buffer t t))) ;; If singlepart, enforce a list. From 386153f1a7e73fca2b63c6f593b30717316e04fa Mon Sep 17 00:00:00 2001 From: "Dirk-Jan C. Binnema" Date: Sat, 20 Apr 2024 11:43:15 +0300 Subject: [PATCH 003/305] github: update bug filing template --- .github/ISSUE_TEMPLATE/mu4e-bug-report.md | 26 +++++++++++++++++------ 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/mu4e-bug-report.md b/.github/ISSUE_TEMPLATE/mu4e-bug-report.md index cb5c0b2ad..63d857f66 100644 --- a/.github/ISSUE_TEMPLATE/mu4e-bug-report.md +++ b/.github/ISSUE_TEMPLATE/mu4e-bug-report.md @@ -7,23 +7,35 @@ assignees: '' --- **Describe the bug** + +Give the bug a good title. + Please provide a clear and concise description of what you expected to happen -and what actually happened. +and what actually happened, and follow the steps below. **How to Reproduce** + Include the exact steps of what you were doing (commands executed etc.). Include -any relevant logs and outputs. Best start with `emacs -Q` and a minimal `mu4e` setup. +any relevant logs and outputs: -If this is about a specific (kind of) message, attach an example message. (Open -the message, press `.` (`mu4e-view-raw-message`), then `C-x C-w` and attach. -Anonymize as needed, all that matters is that the issue still reproduces. +- Best start from `emacs -Q`, and load a minimal `mu4e` setup; describe the steps + that lead up to the bug. +- Does the problem happen each time? Sometimes? +- If this is about a specific (kind of) message, attach an example message. + (Open the message, press `.` (`mu4e-view-raw-message`), then `C-x C-w` and + attach. Anonymize as needed, all that matters is that the issue still + reproduces. **Environment** + Please describe the versions of OS, Emacs, mu/mu4e etc. you are using. **Checklist** -- [ ] you are running either an 1.8.x/1.10.x release or `master` (otherwise please upgrade) + +- [ ] you are running either an 1.10.x/1.12.x release or `master` (otherwise please upgrade) - [ ] you can reproduce the problem without 3rd party extensions (including Doom/Evil, various extensions etc.) - [ ] you have read all of the above -Please make sure you all items in the checklist are set/met before filing the ticket. Thank you! \ No newline at end of file +Please make sure you all items in the checklist are set/met before filing the ticket. + +Thank you! From a0d60d23b0a34c34d1da639173c7fffd40880b60 Mon Sep 17 00:00:00 2001 From: "Dirk-Jan C. Binnema" Date: Sun, 21 Apr 2024 22:08:10 +0300 Subject: [PATCH 004/305] compat: include sys/wait.h where needed netbsd needs this explicitly, other systems let us get away without it. --- lib/utils/mu-utils-file.cc | 3 ++- mu/mu-cmd-find.cc | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/utils/mu-utils-file.cc b/lib/utils/mu-utils-file.cc index a8be52207..3daea34a3 100644 --- a/lib/utils/mu-utils-file.cc +++ b/lib/utils/mu-utils-file.cc @@ -1,5 +1,5 @@ /* -** Copyright (C) 2023 Dirk-Jan C. Binnema +** Copyright (C) 2023-2024 Dirk-Jan C. Binnema ** ** This program is free software; you can redistribute it and/or modify it ** under the terms of the GNU General Public License as published by the @@ -23,6 +23,7 @@ #include "mu-utils-file.hh" #include +#include #include #include diff --git a/mu/mu-cmd-find.cc b/mu/mu-cmd-find.cc index f21ff6e51..3853856d7 100644 --- a/mu/mu-cmd-find.cc +++ b/mu/mu-cmd-find.cc @@ -1,5 +1,5 @@ /* -** Copyright (C) 2008-2023 Dirk-Jan C. Binnema +** Copyright (C) 2008-2024 Dirk-Jan C. Binnema ** ** This program is free software; you can redistribute it and/or modify it ** under the terms of the GNU General Public License as published by the @@ -27,6 +27,7 @@ #include #include #include +#include #include "message/mu-message.hh" #include "mu-maildir.hh" From 6349091061d3f077cc332f6c56ad2ab5b67bf2a4 Mon Sep 17 00:00:00 2001 From: "Dirk-Jan C. Binnema" Date: Tue, 23 Apr 2024 19:45:39 +0300 Subject: [PATCH 005/305] mu4e-compose: don't interfere with non-mu4e completion When enabled, attempt mu4e's auto-completion the first in line (in completion-at-point-functions); but don't remove any other completions the user may have set up. Fixes #2697. --- mu4e/mu4e-compose.el | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/mu4e/mu4e-compose.el b/mu4e/mu4e-compose.el index 3c15903c7..701ed93d0 100644 --- a/mu4e/mu4e-compose.el +++ b/mu4e/mu4e-compose.el @@ -390,16 +390,18 @@ contact fields." (mu4e-complete-contact)))) (defun mu4e--compose-setup-completion () - "Set up auto-completion of addresses if enabled." - ;; turn off message-mode's completion, it's just interfering. - (remove-hook 'completion-at-point-functions - #'message-completion-function 'local) + "Maybe enable auto-completion of addresses. +Do this when `mu4e-compose-complete-addresses' is non-nil. + +When enabled, this attempts to put mu4e's completions at the +start of the buffer-local `completion-at-point-functions'. Other +completion functions still apply." (when mu4e-compose-complete-addresses (set (make-local-variable 'completion-ignore-case) t) (set (make-local-variable 'completion-cycle-threshold) 7) (add-to-list (make-local-variable 'completion-styles) 'substring) (add-hook 'completion-at-point-functions - #'mu4e--compose-complete-contact-field nil t))) + #'mu4e--compose-complete-contact-field -10 t))) (defun mu4e--fcc-handler (msgpath) "Handle Fcc: for MSGPATH. From 0f0d2189d4453c1e3d328d7927c4c1546f4c35bd Mon Sep 17 00:00:00 2001 From: "Dirk-Jan C. Binnema" Date: Tue, 23 Apr 2024 22:08:23 +0300 Subject: [PATCH 006/305] mu4d-contacts: fix typo --- mu4e/mu4e-contacts.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mu4e/mu4e-contacts.el b/mu4e/mu4e-contacts.el index f70106f7c..ab6079cf2 100644 --- a/mu4e/mu4e-contacts.el +++ b/mu4e/mu4e-contacts.el @@ -236,7 +236,7 @@ case a phrase contains a quote, it will be escaped." (mu4e-contact-email contact))) (defsubst mu4e-contact-make (name email) - "Creata contact plist from NAME and EMAIL." + "Create a contact plist from NAME and EMAIL." `(:name ,name :email ,email)) (defun mu4e-contact-full (contact) From 4d923b6bbc603c7f78050f357dc273681710105c Mon Sep 17 00:00:00 2001 From: Joseph Turner Date: Mon, 22 Apr 2024 00:23:19 -0700 Subject: [PATCH 007/305] mu4e-compose: fix when mu4e-sent-messages-behavior is functional This commits fixes a regression introduced in 85bfe763362b95935a3967f6585e14b3f9890a70 , at which point sent mails ended up in the "cur/" subdirectory of the root maildir when the mu4e-sent-messages-behavior user option was set to a function. --- mu4e/mu4e-compose.el | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/mu4e/mu4e-compose.el b/mu4e/mu4e-compose.el index 701ed93d0..0767ea697 100644 --- a/mu4e/mu4e-compose.el +++ b/mu4e/mu4e-compose.el @@ -330,12 +330,18 @@ Returns the path for the sent message, either in the sent or trash folder, or nil if the message should be removed after sending." (when-let ((sent-dir - (pcase mu4e-sent-messages-behavior - ('delete nil) - ('trash (mu4e-get-trash-folder parent)) - ('sent (mu4e-get-sent-folder parent)) - ((pred functionp) (funcall mu4e-sent-messages-behavior)) - (_ (mu4e-error "Error in `mu4e-sent-messages-behavior'"))))) + ;; We can't call `functionp' since at least 'delete is a function. + (pcase mu4e-sent-messages-behavior + ('delete nil) + ('trash (mu4e-get-trash-folder parent)) + ('sent (mu4e-get-sent-folder parent)) + ((pred functionp) + (pcase (funcall mu4e-sent-messages-behavior) + ('delete nil) + ('trash (mu4e-get-trash-folder parent)) + ('sent (mu4e-get-sent-folder parent)) + (_ (mu4e-error "Error in `mu4e-sent-messages-behavior'")))) + (_ (mu4e-error "Error in `mu4e-sent-messages-behavior'"))))) (mu4e-join-paths (mu4e-root-maildir) sent-dir "cur" (format "%s%s2,S" base-name mu4e-maildir-info-delimiter)))) From f00ca68c670baf30e139a4af381a95e590c82381 Mon Sep 17 00:00:00 2001 From: Joseph Turner Date: Wed, 24 Apr 2024 12:49:06 -0400 Subject: [PATCH 008/305] mu4e-compose: Don't nest pcase --- mu4e/mu4e-compose.el | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/mu4e/mu4e-compose.el b/mu4e/mu4e-compose.el index 0767ea697..0ed93abc0 100644 --- a/mu4e/mu4e-compose.el +++ b/mu4e/mu4e-compose.el @@ -329,18 +329,18 @@ base filename without any Maildir decoration. Returns the path for the sent message, either in the sent or trash folder, or nil if the message should be removed after sending." - (when-let ((sent-dir + (when-let ((sent-behavior ;; We can't call `functionp' since at least 'delete is a function. (pcase mu4e-sent-messages-behavior + ((or 'delete 'trash 'sent) mu4e-sent-messages-behavior) + ((pred functionp mu4e-sent-messages-behavior) + (funcall mu4e-sent-messages-behavior)) + (_ mu4e-sent-messages-behavior))) + (sent-dir + (pcase sent-behavior ('delete nil) ('trash (mu4e-get-trash-folder parent)) ('sent (mu4e-get-sent-folder parent)) - ((pred functionp) - (pcase (funcall mu4e-sent-messages-behavior) - ('delete nil) - ('trash (mu4e-get-trash-folder parent)) - ('sent (mu4e-get-sent-folder parent)) - (_ (mu4e-error "Error in `mu4e-sent-messages-behavior'")))) (_ (mu4e-error "Error in `mu4e-sent-messages-behavior'"))))) (mu4e-join-paths (mu4e-root-maildir) sent-dir "cur" From 178402fabbf6179508463c34f8d6f653cad397ac Mon Sep 17 00:00:00 2001 From: "Dirk-Jan C. Binnema" Date: Fri, 26 Apr 2024 22:57:39 +0300 Subject: [PATCH 009/305] mu4e-compose: prepare for rebase temporarily remove the mu4e-sent-messages-behavior change, it comes back in a slightly different way in the next commits. --- mu4e/mu4e-compose.el | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/mu4e/mu4e-compose.el b/mu4e/mu4e-compose.el index 0ed93abc0..701ed93d0 100644 --- a/mu4e/mu4e-compose.el +++ b/mu4e/mu4e-compose.el @@ -329,19 +329,13 @@ base filename without any Maildir decoration. Returns the path for the sent message, either in the sent or trash folder, or nil if the message should be removed after sending." - (when-let ((sent-behavior - ;; We can't call `functionp' since at least 'delete is a function. - (pcase mu4e-sent-messages-behavior - ((or 'delete 'trash 'sent) mu4e-sent-messages-behavior) - ((pred functionp mu4e-sent-messages-behavior) - (funcall mu4e-sent-messages-behavior)) - (_ mu4e-sent-messages-behavior))) - (sent-dir - (pcase sent-behavior - ('delete nil) - ('trash (mu4e-get-trash-folder parent)) - ('sent (mu4e-get-sent-folder parent)) - (_ (mu4e-error "Error in `mu4e-sent-messages-behavior'"))))) + (when-let ((sent-dir + (pcase mu4e-sent-messages-behavior + ('delete nil) + ('trash (mu4e-get-trash-folder parent)) + ('sent (mu4e-get-sent-folder parent)) + ((pred functionp) (funcall mu4e-sent-messages-behavior)) + (_ (mu4e-error "Error in `mu4e-sent-messages-behavior'"))))) (mu4e-join-paths (mu4e-root-maildir) sent-dir "cur" (format "%s%s2,S" base-name mu4e-maildir-info-delimiter)))) From 6a4d6a49c49594b6feb2496d4eab462128c96b5d Mon Sep 17 00:00:00 2001 From: "Dirk-Jan C. Binnema" Date: Tue, 23 Apr 2024 19:19:26 +0300 Subject: [PATCH 010/305] mu4e-compose: split off parts in mu4e-draft; rework Move draft-creation part of message-composition to a new file mu4e-drafts However, this is more than just some refactoring: rework the message (draft) setup as such to ensure we always get a (non-active, live) buffer back from the composition process. This also fixes (progn (compose-mail "test@example.org" "Test") (insert "TEST")) as mentioned on the mailing list. Fixes #2699 --- mu4e/meson.build | 1 + mu4e/mu4e-compose.el | 745 +++++------------------------------------- mu4e/mu4e-draft.el | 673 ++++++++++++++++++++++++++++++++++++++ mu4e/mu4e-obsolete.el | 6 +- mu4e/mu4e.texi | 4 +- 5 files changed, 765 insertions(+), 664 deletions(-) create mode 100644 mu4e/mu4e-draft.el diff --git a/mu4e/meson.build b/mu4e/meson.build index 079e74869..a2a22bbd7 100644 --- a/mu4e/meson.build +++ b/mu4e/meson.build @@ -43,6 +43,7 @@ mu4e_srcs=[ 'mu4e-contacts.el', 'mu4e-context.el', 'mu4e-contrib.el', + 'mu4e-draft.el', 'mu4e-folders.el', 'mu4e.el', 'mu4e-headers.el', diff --git a/mu4e/mu4e-compose.el b/mu4e/mu4e-compose.el index 701ed93d0..f085619a3 100644 --- a/mu4e/mu4e-compose.el +++ b/mu4e/mu4e-compose.el @@ -22,10 +22,9 @@ ;;; Commentary: -;; Implements mu4e-compose-mode, which is a `message-mode' derivative. This is a -;; *fairly* thin wrapper around the gnus functions for message composition, -;; integrated with mu4e. Still, quite a bit of code to make it work nicely in -;; the mu4e context. +;; Implements mu4e-compose-mode, which is a `message-mode' derivative. There's +;; quite a bit of trickery involved to make the message-mode functions work in +;; this context; see mu4e-draft for details. ;;; Code: @@ -40,124 +39,14 @@ (require 'mu4e-context) (require 'mu4e-folders) +(require 'mu4e-draft) + ;;; User configuration for compose-mode (defgroup mu4e-compose nil "Customization for composing/sending messages." :group 'mu4e) -(defcustom mu4e-sent-messages-behavior 'sent - "Determines what mu4e does with sent messages. - -This is one of the symbols: -* `sent' move the sent message to the Sent-folder (`mu4e-sent-folder') -* `trash' move the sent message to the Trash-folder (`mu4e-trash-folder') -* `delete' delete the sent message. - -Note, when using GMail/IMAP, you should set this to either -`trash' or `delete', since GMail already takes care of keeping -copies in the sent folder. - -Alternatively, `mu4e-sent-messages-behavior' can be a function -which takes no arguments, and which should return one of the mentioned -symbols, for example: - - (setq mu4e-sent-messages-behavior (lambda () - (if (string= (message-sendmail-envelope-from) \"foo@example.com\") - \\='delete \\='sent))) - -The various `message-' functions from `message-mode' are available -for querying the message information." - :type '(choice (const :tag "move message to mu4e-sent-folder" sent) - (const :tag "move message to mu4e-trash-folder" trash) - (const :tag "delete message" delete)) - :group 'mu4e-compose) - -(defcustom mu4e-compose-switch nil - "Where to display the new message? -A symbol: -- nil : default (new buffer) -- window : compose in new window -- frame or t : compose in new frame -- display-buffer: use `display-buffer' / `display-buffer-alist' - (for fine-tuning). - -For backward compatibility with `mu4e-compose-in-new-frame', t is -treated as =\\'frame." - :type 'symbol - :group 'mu4e-compose) - -(defcustom mu4e-compose-context-policy 'ask - "Policy for determining the context when composing a new message. - -If the value is `always-ask', ask the user unconditionally. - -In all other cases, if any context matches (using its match -function), this context is used. Otherwise, if none of the -contexts match, we have the following choices: - -- `pick-first': pick the first of the contexts available (ie. the default) -- `ask': ask the user -- `ask-if-none': ask if there is no context yet, otherwise leave it as it is -- nil: return nil; leaves the current context as is. - -Also see `mu4e-context-policy'." - :type '(choice - (const :tag "Always ask what context to use" always-ask) - (const :tag "Ask if none of the contexts match" ask) - (const :tag "Ask when there's no context yet" ask-if-none) - (const :tag "Pick the first context if none match" pick-first) - (const :tag "Don't change the context when none match" nil)) - :safe 'symbolp - :group 'mu4e-compose) - -(defcustom mu4e-compose-crypto-policy - '(encrypt-encrypted-replies sign-encrypted-replies) - "Policy to control when messages will be signed/encrypted. - -The value is a list which influence the way draft messages are -created. Specifically, it might contain: - -- `sign-all-messages': Always add a signature. -- `sign-new-messages': Add a signature to new message, ie. - messages that aren't responses to another message. -- `sign-forwarded-messages': Add a signature when forwarding - a message -- `sign-edited-messages': Add a signature to drafts -- `sign-all-replies': Add a signature when responding to - another message. -- `sign-plain-replies': Add a signature when responding to - non-encrypted messages. -- `sign-encrypted-replies': Add a signature when responding - to encrypted messages. - -It should be noted that certain symbols have priorities over one -another. So `sign-all-messages' implies `sign-all-replies', which -in turn implies `sign-plain-replies'. Adding both to the set, is -not a contradiction, but a redundant configuration. - -All `sign-*' options have a `encrypt-*' analogue." - :type '(set :greedy t - (const :tag "Sign all messages" sign-all-messages) - (const :tag "Encrypt all messages" encrypt-all-messages) - (const :tag "Sign new messages" sign-new-messages) - (const :tag "Encrypt new messages" encrypt-new-messages) - (const :tag "Sign forwarded messages" sign-forwarded-messages) - (const :tag "Encrypt forwarded messages" - encrypt-forwarded-messages) - (const :tag "Sign edited messages" sign-edited-messages) - (const :tag "Encrypt edited messages" edited-forwarded-messages) - (const :tag "Sign all replies" sign-all-replies) - (const :tag "Encrypt all replies" encrypt-all-replies) - (const :tag "Sign replies to plain messages" sign-plain-replies) - (const :tag "Encrypt replies to plain messages" - encrypt-plain-replies) - (const :tag "Sign replies to encrypted messages" - sign-encrypted-replies) - (const :tag "Encrypt replies to encrypted messages" - encrypt-encrypted-replies)) - :group 'mu4e-compose) - (defcustom mu4e-compose-format-flowed nil "Whether to compose messages to be sent as format=flowed. \(Or with long lines if variable `use-hard-newlines' is set to @@ -184,15 +73,6 @@ the place to do that." :group 'mu4e-compose) -;;; Runtime variables; useful for user-hooks etc. -(defvar-local mu4e-compose-parent-message nil - "The parent message plist. -This is the message being replied to, forwarded or edited; used -in `mu4e-compose-pre-hook'. For new (non-reply, forward etc.) -messages, it is nil.") - -(defvar-local mu4e-compose-type nil - "The compose-type for the current message.") (defvar mu4e-captured-message) (defun mu4e-compose-attach-captured-message () @@ -285,61 +165,6 @@ the file under our feet, which is a bit fragile." (when message-signature (save-excursion (message-insert-signature)))))))) - -;;; Filenames -(defun mu4e--message-basename() - "Construct a randomized filename for a message with flags FLAGSTR. -It looks something like -