summaryrefslogtreecommitdiff
path: root/mu4e
diff options
context:
space:
mode:
authorChristophe Troestler <Christophe.Troestler@umons.ac.be>2019-04-13 00:53:36 +0200
committerChristophe Troestler <Christophe.Troestler@umons.ac.be>2019-07-13 14:07:03 +0200
commit1078fee2c5fc67bdb8c2aab2c8082b0d9b17ac78 (patch)
tree7c7cc749f009e8ecf49fb530f87571f2f97f3d97 /mu4e
parentc639a939f485b10ff5b5c40a8b7e62024467dafa (diff)
mu4e (ical): Allow to reply to icalendar invitations
Fixes https://github.com/djcb/mu/issues/994
Diffstat (limited to 'mu4e')
-rw-r--r--mu4e/Makefile.am1
-rw-r--r--mu4e/mu4e-draft.el19
-rw-r--r--mu4e/mu4e-icalendar.el92
-rw-r--r--mu4e/mu4e-vars.el8
-rw-r--r--mu4e/mu4e-view.el3
5 files changed, 114 insertions, 9 deletions
diff --git a/mu4e/Makefile.am b/mu4e/Makefile.am
index ebccf26..b84bb48 100644
--- a/mu4e/Makefile.am
+++ b/mu4e/Makefile.am
@@ -28,6 +28,7 @@ dist_lisp_LISP= \
mu4e-contrib.el \
mu4e-draft.el \
mu4e-headers.el \
+ mu4e-icalendar.el \
mu4e-lists.el \
mu4e-main.el \
mu4e-mark.el \
diff --git a/mu4e/mu4e-draft.el b/mu4e/mu4e-draft.el
index 3b7679c..2b22164 100644
--- a/mu4e/mu4e-draft.el
+++ b/mu4e/mu4e-draft.el
@@ -413,14 +413,17 @@ You can append flags."
Replying-to-self is special; in that case, the To and Cc fields
will be the same as in the original."
(let* ((reply-to-self (mu4e-message-contact-field-matches-me origmsg :from))
- (recipnum
- (+ (length (mu4e~draft-create-to-lst origmsg))
- (length (mu4e~draft-create-cc-lst origmsg t))))
- ;; reply-to-self implies reply-all
- (reply-all (or reply-to-self (mu4e~draft-reply-all-p origmsg)))
- (old-msgid (plist-get origmsg :message-id))
- (subject (concat mu4e~draft-reply-prefix
- (message-strip-subject-re
+ (recipnum
+ (+ (length (mu4e~draft-create-to-lst origmsg))
+ (length (mu4e~draft-create-cc-lst origmsg t))))
+ ;; reply-to-self implies reply-all
+ (reply-all (or reply-to-self
+ (eq mu4e-compose-reply-recipients 'all)
+ (and (not (eq mu4e-compose-reply-recipients 'sender))
+ (mu4e~draft-reply-all-p origmsg))))
+ (old-msgid (plist-get origmsg :message-id))
+ (subject (concat mu4e~draft-reply-prefix
+ (message-strip-subject-re
(or (plist-get origmsg :subject) "")))))
(concat
(mu4e~draft-header "From" (or (mu4e~draft-from-construct) ""))
diff --git a/mu4e/mu4e-icalendar.el b/mu4e/mu4e-icalendar.el
new file mode 100644
index 0000000..84f5d58
--- /dev/null
+++ b/mu4e/mu4e-icalendar.el
@@ -0,0 +1,92 @@
+;;; mu4e-icalendar.el --- reply to iCalendar meeting requests
+
+;;; Commentary:
+
+;; To install:
+;; (require 'gnus-icalendar)
+;; (gnus-icalendar-setup)
+
+;; to enable optional iCalendar->Org sync functionality
+;; NOTE: both the capture file and the headline(s) inside must already exist
+;; (setq gnus-icalendar-org-capture-file "~/org/notes.org")
+;; (setq gnus-icalendar-org-capture-headline '("Calendar"))
+;; (gnus-icalendar-org-setup)
+
+(require 'mu4e)
+(require 'gnus-icalendar)
+
+(eval-when-compile (require 'cl))
+
+
+(defun mu4e-icalendar-setup ()
+ (gnus-icalendar-setup)
+ (cl-defmethod gnus-icalendar-event:inline-reply-buttons :around
+ ((event gnus-icalendar-event) handle)
+ (if (and (boundp 'mu4e~view-rendering)
+ (gnus-icalendar-event:rsvp event))
+ `(("Accept" mu4e-icalendar-reply (,handle accepted ,event))
+ ("Tentative" mu4e-icalendar-reply (,handle tentative ,event))
+ ("Decline" mu4e-icalendar-reply (,handle declined ,event)))
+ (cl-call-next-method event handle))))
+
+(defun mu4e-icalendar-reply (data)
+ "Reply to a text/calendar event."
+ ;; Based on `gnus-icalendar-reply'.
+ (let* ((handle (car data))
+ (status (cadr data))
+ (event (caddr data))
+ (reply (gnus-icalendar-with-decoded-handle handle
+ (gnus-icalendar-event-reply-from-buffer
+ (current-buffer) status (gnus-icalendar-identities))))
+ (msg (mu4e-message-at-point 'noerror)))
+
+ (when reply
+ (cl-labels
+ ((fold-icalendar-buffer
+ ()
+ (goto-char (point-min))
+ (while (re-search-forward "^\\(.\\{72\\}\\)\\(.+\\)$" nil t)
+ (replace-match "\\1\n \\2")
+ (goto-char (line-beginning-position)))))
+ (let ((subject (concat (capitalize (symbol-name status))
+ ": " (gnus-icalendar-event:summary event))))
+
+ (with-current-buffer (get-buffer-create gnus-icalendar-reply-bufname)
+ (delete-region (point-min) (point-max))
+ (insert reply)
+ (fold-icalendar-buffer)
+ (mu4e-icalendar-reply-with-buffer msg subject (buffer-name)))
+
+ ;; Back in article buffer
+ (setq-local gnus-icalendar-reply-status status)
+ (when gnus-icalendar-org-enabled-p
+ (gnus-icalendar--update-org-event event status)
+ ;; refresh article buffer to update the reply status
+ (with-current-buffer mu4e~headers-buffer-name
+ (mu4e-headers-rerun-search))))))))
+
+(defun mu4e~icalendar-delete-citation ()
+ (delete-region (point-min) (point-max)))
+
+(defun mu4e-icalendar-reply-with-buffer (original-msg subject buffer-name)
+ (let ((message-signature nil))
+ (let ((mu4e-compose-cite-function #'mu4e~icalendar-delete-citation)
+ (mu4e-sent-messages-behavior 'delete)
+ (mu4e-compose-reply-recipients 'sender))
+ ;; FIXME: only reply to the original sender (do not ask)
+ (mu4e~compose-handler 'reply original-msg))
+ (message-goto-body)
+ (insert "\n\n")
+ (mml-insert-multipart "alternative")
+ (mml-insert-empty-tag 'part 'type "text/plain")
+ (mml-attach-buffer buffer-name "text/calendar; method=REPLY; charset=UTF-8")
+ (message-goto-subject)
+ (delete-region (line-beginning-position) (line-end-position))
+ (insert "Subject: " subject)
+; (message-send-and-exit)
+ ))
+
+
+
+(provide 'mu4e-icalendar)
+;;; mu4e-icalendar.el ends here
diff --git a/mu4e/mu4e-vars.el b/mu4e/mu4e-vars.el
index afae182..5a0dd0f 100644
--- a/mu4e/mu4e-vars.el
+++ b/mu4e/mu4e-vars.el
@@ -405,6 +405,14 @@ predicate function. A value of nil keeps all the addresses."
(repeat string))
:group 'mu4e-compose)
+(defcustom mu4e-compose-reply-recipients 'ask
+ "Which recipients to use when replying to a message.
+May be 'ask, 'all, 'sender."
+ :type '(choice ask
+ all
+ sender)
+ :group 'mu4e-compose)
+
(defcustom mu4e-compose-reply-to-address nil
"The Reply-To address.
Useful when this is not equal to the From: address."
diff --git a/mu4e/mu4e-view.el b/mu4e/mu4e-view.el
index 0da6e0a..3f4bcc2 100644
--- a/mu4e/mu4e-view.el
+++ b/mu4e/mu4e-view.el
@@ -381,7 +381,8 @@ article-mode."
gnus-summary-buffer (get-buffer-create " *appease-gnus*")
gnus-original-article-buffer (current-buffer))
(run-hooks 'gnus-article-decode-hook)
- (let ((max-specpdl-size mu4e-view-max-specpdl-size))
+ (let ((mu4e~view-rendering t) ; customize gnus in mu4e
+ (max-specpdl-size mu4e-view-max-specpdl-size))
(gnus-article-prepare-display))
(mu4e-view-mode)
(setq mu4e~view-message msg)