summaryrefslogtreecommitdiff
path: root/mu4e
diff options
context:
space:
mode:
authorPiyush <pshsrv@protonmail.com>2019-05-11 18:13:36 +0530
committerPiyush <pshsrv@protonmail.com>2019-05-11 18:13:36 +0530
commitc4a23bfb6687cb79014adebcc409a44f262cb77c (patch)
tree2dd279fb89bf67e293a040b3ccc1375f3a3d5e71 /mu4e
parentc4e037c16fb4705d3be5c9bd228540e81379b198 (diff)
parent7563b89c9cda397d43dd3d8d985a677bb3c8495f (diff)
Merge branch 'master' of github:djcb/mu
Diffstat (limited to 'mu4e')
-rw-r--r--mu4e/mu4e-draft.el39
-rw-r--r--mu4e/mu4e-proc.el420
-rw-r--r--mu4e/mu4e-utils.el163
-rw-r--r--mu4e/mu4e-vars.el273
-rw-r--r--mu4e/mu4e.texi93
5 files changed, 474 insertions, 514 deletions
diff --git a/mu4e/mu4e-draft.el b/mu4e/mu4e-draft.el
index f514b01..998a3ca 100644
--- a/mu4e/mu4e-draft.el
+++ b/mu4e/mu4e-draft.el
@@ -262,6 +262,45 @@ message. Return nil if there are no recipients for the particular field."
(otherwise
(mu4e-error "Unsupported field")))))
+;;; RFC2822 handling of phrases in mail-addresses
+;;; The optional display-name contains a phrase, it sits before the angle-addr
+;;; as specified in RFC2822 for email-addresses in header fields.
+;;; contributed by jhelberg
+
+(defun mu4e~rfc822-phrase-type (ph)
+ "Return either atom, quoted-string, a corner-case or nil. This
+ checks for empty string first. Then quotes around the phrase
+ (returning 'rfc822-quoted-string). Then whether there is a quote
+ inside the phrase (returning 'rfc822-containing-quote).
+ The reverse of the RFC atext definition is then tested.
+ If it matches, nil is returned, if not, it is an 'rfc822-atom, which
+ is returned."
+ (cond
+ ((= (length ph) 0) 'rfc822-empty)
+ ((= (aref ph 0) ?\")
+ (if (string-match "\"\\([^\"\\\n]\\|\\\\.\\|\\\\\n\\)*\"" ph)
+ 'rfc822-quoted-string
+ 'rfc822-containing-quote)) ; starts with quote, but doesn't end with one
+ ((string-match-p "[\"]" ph) 'rfc822-containing-quote)
+ ((string-match-p "[\000-\037()\*<>@,;:\\\.]+" ph) nil)
+ (t 'rfc822-atom)))
+
+(defun mu4e~rfc822-quoteit (ph)
+ "Quote RFC822 phrase only if necessary.
+ Atoms and quoted strings don't need quotes. The rest do. In
+ case a phrase contains a quote, it will be escaped."
+ (let ((type (mu4e~rfc822-phrase-type ph)))
+ (cond
+ ((eq type 'rfc822-atom) ph)
+ ((eq type 'rfc822-quoted-string) ph)
+ ((eq type 'rfc822-containing-quote)
+ (format "\"%s\""
+ (replace-regexp-in-string "\"" "\\\\\"" ph)))
+ (t (format "\"%s\"" ph)))))
+
+
+
+
(defun mu4e~draft-from-construct ()
"Construct a value for the From:-field of the reply to MSG,
diff --git a/mu4e/mu4e-proc.el b/mu4e/mu4e-proc.el
index 9190ab2..7ddbe80 100644
--- a/mu4e/mu4e-proc.el
+++ b/mu4e/mu4e-proc.el
@@ -1,6 +1,6 @@
;; mu4e-proc.el -- part of mu4e, the mu mail user agent
;;
-;; Copyright (C) 2011-2017 Dirk-Jan C. Binnema
+;; Copyright (C) 2011-2019 Dirk-Jan C. Binnema
;; Author: Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
;; Maintainer: Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
@@ -37,13 +37,11 @@
;; dealing with the length cookie that precedes expressions
(defconst mu4e~cookie-pre "\376"
- "Each expression we get from the backend (mu server) starts with
-a length cookie:
- <`mu4e~cookie-pre'><length-in-hex><`mu4e~cookie-post'>.")
+ "Each expression starts with a length cookie:
+<`mu4e~cookie-pre'><length-in-hex><`mu4e~cookie-post'>.")
(defconst mu4e~cookie-post "\377"
- "Each expression we get from the backend (mu server) starts with
-a length cookie:
- <`mu4e~cookie-pre'><length-in-hex><`mu4e~cookie-post'>.")
+ "Each expression starts with a length cookie:
+<`mu4e~cookie-pre'><length-in-hex><`mu4e~cookie-post'>.")
(defconst mu4e~cookie-matcher-rx
(concat mu4e~cookie-pre "\\([[:xdigit:]]+\\)" mu4e~cookie-post)
"Regular expression matching the length cookie.
@@ -56,12 +54,11 @@ Match 1 will be the length (in hex).")
(defvar mu4e~proc-process nil
"The mu-server process.")
-
(defun mu4e~proc-running-p ()
"Whether the mu process is running."
(when (and mu4e~proc-process
- (memq (process-status mu4e~proc-process)
- '(run open listen connect stop)))
+ (memq (process-status mu4e~proc-process)
+ '(run open listen connect stop)))
t))
(defsubst mu4e~proc-eat-sexp-from-buf ()
@@ -76,36 +73,37 @@ removed."
;; mu4e~cookie-matcher-rx:
;; (concat mu4e~cookie-pre "\\([[:xdigit:]]+\\)]" mu4e~cookie-post)
(let ((b (string-match mu4e~cookie-matcher-rx mu4e~proc-buf))
- (sexp-len) (objcons))
+ (sexp-len) (objcons))
(when b
- (setq sexp-len (string-to-number (match-string 1 mu4e~proc-buf) 16))
- ;; does mu4e~proc-buf contain the full sexp?
- (when (>= (length mu4e~proc-buf) (+ sexp-len (match-end 0)))
- ;; clear-up start
- (setq mu4e~proc-buf (substring mu4e~proc-buf (match-end 0)))
- ;; note: we read the input in binary mode -- here, we take the part
- ;; that is the sexp, and convert that to utf-8, before we interpret
- ;; it.
- (setq objcons (read-from-string
- (decode-coding-string
- (substring mu4e~proc-buf 0 sexp-len)
- 'utf-8 t)))
- (when objcons
- (setq mu4e~proc-buf (substring mu4e~proc-buf sexp-len))
- (car objcons)))))))
+ (setq sexp-len (string-to-number (match-string 1 mu4e~proc-buf) 16))
+ ;; does mu4e~proc-buf contain the full sexp?
+ (when (>= (length mu4e~proc-buf) (+ sexp-len (match-end 0)))
+ ;; clear-up start
+ (setq mu4e~proc-buf (substring mu4e~proc-buf (match-end 0)))
+ ;; note: we read the input in binary mode -- here, we take the part
+ ;; that is the sexp, and convert that to utf-8, before we interpret
+ ;; it.
+ (setq objcons (read-from-string
+ (decode-coding-string
+ (substring mu4e~proc-buf 0 sexp-len)
+ 'utf-8 t)))
+ (when objcons
+ (setq mu4e~proc-buf (substring mu4e~proc-buf sexp-len))
+ (car objcons)))))))
(defun mu4e~proc-filter (proc str)
- "A process-filter for the 'mu server' output.
-It accumulates the strings into valid sexps by checking of the
-';;eox' end-of-sexp marker, and then evaluating them.
+ "Filter string STR from PROC.
+This process the the 'mu server' output. It accumulates the
+strings into valid sexps by checking of the ';;eox' `end-of-sexp'
+marker, and then evaluating them.
The server output is as follows:
1. an error
(:error 2 :message \"unknown command\")
;; eox
- => this will be passed to `mu4e-error-func'.
+ => passed to `mu4e-error-func'.
2a. a message sexp looks something like:
\(
@@ -156,92 +154,93 @@ The server output is as follows:
(let ((sexp (mu4e~proc-eat-sexp-from-buf)))
(with-local-quit
(while sexp
- (mu4e-log 'from-server "%S" sexp)
- (cond
- ;; a header plist can be recognized by the existence of a :date field
- ((plist-get sexp :date)
- (funcall mu4e-header-func sexp))
-
- ;; the found sexp, we receive after getting all the headers
- ((plist-get sexp :found)
- (funcall mu4e-found-func (plist-get sexp :found)))
-
- ;; viewing a specific message
- ((plist-get sexp :view)
- (funcall mu4e-view-func (plist-get sexp :view)))
-
- ;; receive an erase message
- ((plist-get sexp :erase)
- (funcall mu4e-erase-func))
-
- ;; receive a :sent message
- ((plist-get sexp :sent)
- (funcall mu4e-sent-func
- (plist-get sexp :docid)
- (plist-get sexp :path)))
-
- ;; received a pong message
- ((plist-get sexp :pong)
- (funcall mu4e-pong-func
- (plist-get sexp :props)))
-
- ;; received a contacts message
- ;; note: we use 'member', to match (:contacts nil)
- ((plist-member sexp :contacts)
- (funcall mu4e-contacts-func
- (plist-get sexp :contacts)))
-
- ;; something got moved/flags changed
- ((plist-get sexp :update)
+ (mu4e-log 'from-server "%S" sexp)
+ (cond
+ ;; a header plist can be recognized by the existence of a :date field
+ ((plist-get sexp :date)
+ (funcall mu4e-header-func sexp))
+
+ ;; the found sexp, we receive after getting all the headers
+ ((plist-get sexp :found)
+ (funcall mu4e-found-func (plist-get sexp :found)))
+
+ ;; viewing a specific message
+ ((plist-get sexp :view)
+ (funcall mu4e-view-func (plist-get sexp :view)))
+
+ ;; receive an erase message
+ ((plist-get sexp :erase)
+ (funcall mu4e-erase-func))
+
+ ;; receive a :sent message
+ ((plist-get sexp :sent)
+ (funcall mu4e-sent-func
+ (plist-get sexp :docid)
+ (plist-get sexp :path)))
+
+ ;; received a pong message
+ ((plist-get sexp :pong)
+ (funcall mu4e-pong-func
+ (plist-get sexp :props)))
+
+ ;; received a contacts message
+ ;; note: we use 'member', to match (:contacts nil)
+ ((plist-member sexp :contacts)
+ (funcall mu4e-contacts-func
+ (plist-get sexp :contacts)
+ (plist-get sexp :tstamp)))
+
+ ;; something got moved/flags changed
+ ((plist-get sexp :update)
(funcall mu4e-update-func
- (plist-get sexp :update)
- (plist-get sexp :move)
- (plist-get sexp :maybe-view)))
-
- ;; a message got removed
- ((plist-get sexp :remove)
- (funcall mu4e-remove-func (plist-get sexp :remove)))
-
- ;; start composing a new message
- ((plist-get sexp :compose)
- (funcall mu4e-compose-func
- (plist-get sexp :compose)
- (plist-get sexp :original)
- (plist-get sexp :include)))
-
- ;; do something with a temporary file
- ((plist-get sexp :temp)
- (funcall mu4e-temp-func
- (plist-get sexp :temp) ;; name of the temp file
- (plist-get sexp :what) ;; what to do with it
- ;; (pipe|emacs|open-with...)
- (plist-get sexp :docid) ;; docid of the message
- (plist-get sexp :param)));; parameter for the action
-
- ;; get some info
- ((plist-get sexp :info)
- (funcall mu4e-info-func sexp))
-
- ;; receive an error
- ((plist-get sexp :error)
- (funcall mu4e-error-func
- (plist-get sexp :error)
- (plist-get sexp :message)))
-
- (t (mu4e-message "Unexpected data from server [%S]" sexp)))
-
- (setq sexp (mu4e~proc-eat-sexp-from-buf))))))
+ (plist-get sexp :update)
+ (plist-get sexp :move)
+ (plist-get sexp :maybe-view)))
+
+ ;; a message got removed
+ ((plist-get sexp :remove)
+ (funcall mu4e-remove-func (plist-get sexp :remove)))
+
+ ;; start composing a new message
+ ((plist-get sexp :compose)
+ (funcall mu4e-compose-func
+ (plist-get sexp :compose)
+ (plist-get sexp :original)
+ (plist-get sexp :include)))
+
+ ;; do something with a temporary file
+ ((plist-get sexp :temp)
+ (funcall mu4e-temp-func
+ (plist-get sexp :temp) ;; name of the temp file
+ (plist-get sexp :what) ;; what to do with it
+ ;; (pipe|emacs|open-with...)
+ (plist-get sexp :docid) ;; docid of the message
+ (plist-get sexp :param)));; parameter for the action
+
+ ;; get some info
+ ((plist-get sexp :info)
+ (funcall mu4e-info-func sexp))
+
+ ;; receive an error
+ ((plist-get sexp :error)
+ (funcall mu4e-error-func
+ (plist-get sexp :error)
+ (plist-get sexp :message)))
+
+ (t (mu4e-message "Unexpected data from server [%S]" sexp)))
+
+ (setq sexp (mu4e~proc-eat-sexp-from-buf))))))
(defun mu4e~escape (str)
- "Escape STRING for transport -- put it in quotes, and escape
-existing quotation. In particular, backslashes and
-double-quotes."
+ "Escape string STR for transport.
+Put it in quotes, and escape existing quotation. In particular,
+backslashes and double-quotes."
(let ((esc (replace-regexp-in-string "\\\\" "\\\\\\\\" str)))
(format "\"%s\"" (replace-regexp-in-string "\"" "\\\\\"" esc))))
(defun mu4e~proc-send-command (frm &rest args)
- "Send as command to the mu server process.
+ "Send string from FRM and ARGS to the mu server process.
Start the process if needed."
(unless (mu4e~proc-running-p)
(mu4e~proc-start))
@@ -254,13 +253,13 @@ Start the process if needed."
(unless (file-executable-p mu4e-mu-binary)
(mu4e-error (format "`mu4e-mu-binary' (%S) not found" mu4e-mu-binary)))
(let* ((process-connection-type nil) ;; use a pipe
- (args '("server"))
- (args (append args (when mu4e-mu-home
- (list (concat "--muhome=" mu4e-mu-home))))))
+ (args '("server"))
+ (args (append args (when mu4e-mu-home
+ (list (concat "--muhome=" mu4e-mu-home))))))
(setq mu4e~proc-buf "")
(setq mu4e~proc-process (apply 'start-process
- mu4e~proc-name mu4e~proc-name
- mu4e-mu-binary args))
+ mu4e~proc-name mu4e~proc-name
+ mu4e-mu-binary args))
;; register a function for (:info ...) sexps
(unless mu4e~proc-process
(mu4e-error "Failed to start the mu4e backend"))
@@ -272,14 +271,14 @@ Start the process if needed."
(defun mu4e~proc-kill ()
"Kill the mu server process."
(let* ((buf (get-buffer mu4e~proc-name))
- (proc (and (buffer-live-p buf) (get-buffer-process buf))))
+ (proc (and (buffer-live-p buf) (get-buffer-process buf))))
(when proc
(let ((delete-exited-processes t))
- ;; the mu server signal handler will make it quit after 'quit'
- (mu4e~proc-send-command "cmd:quit"))
- ;; try sending SIGINT (C-c) to process, so it can exit gracefully
+ ;; the mu server signal handler will make it quit after 'quit'
+ (mu4e~proc-send-command "cmd:quit"))
+ ;; try sending SIGINT (C-c) to process, so it can exit gracefully
(ignore-errors
- (signal-process proc 'SIGINT))))
+ (signal-process proc 'SIGINT))))
(setq
mu4e~proc-process nil
mu4e~proc-buf nil))
@@ -288,29 +287,29 @@ Start the process if needed."
;;(defconst mu4e-xapian-empty 19 "Error code: xapian is empty/non-existent")
(defun mu4e~proc-sentinel (proc msg)
- "Function that will be called when the mu-server process terminates."
+ "Function called when the server process PROC terminates with MSG."
(let ((status (process-status proc)) (code (process-exit-status proc)))
(setq mu4e~proc-process nil)
(setq mu4e~proc-buf "") ;; clear any half-received sexps
(cond
((eq status 'signal)
- (cond
- ((or(eq code 9) (eq code 2)) (message nil))
- ;;(message "the mu server process has been stopped"))
- (t (error (format "mu server process received signal %d" code)))))
+ (cond
+ ((or(eq code 9) (eq code 2)) (message nil))
+ ;;(message "the mu server process has been stopped"))
+ (t (error (format "mu server process received signal %d" code)))))
((eq status 'exit)
- (cond
- ((eq code 0)
- (message nil)) ;; don't do anything
- ((eq code 11)
- (error "Database is locked by another process"))
- ((eq code 15)
- (error "Database needs upgrade; try `mu index --rebuild'"))
- ((eq code 19)
- (error "Database empty; try indexing some messages"))
- (t (error "mu server process ended with exit code %d" code))))
+ (cond
+ ((eq code 0)
+ (message nil)) ;; don't do anything
+ ((eq code 11)
+ (error "Database is locked by another process"))
+ ((eq code 15)
+ (error "Database needs upgrade; try `mu index --rebuild'"))
+ ((eq code 19)
+ (error "Database empty; try indexing some messages"))
+ (t (error "Mu server process ended with exit code %d" code))))
(t
- (error "Something bad happened to the mu server process")))))
+ (error "Something bad happened to the mu server process")))))
(defun mu4e~docid-msgid-param (docid-or-msgid)
"Construct a backend parameter based on DOCID-OR-MSGID."
@@ -319,15 +318,15 @@ Start the process if needed."
(format "docid:%d" docid-or-msgid)))
(defun mu4e~proc-find (query threads sortfield sortdir maxnum skip-dups
- include-related)
- "Start a database query for QUERY.
+ include-related)
+ "Run QUERY with THREADS SORTFIELD SORTDIR MAXNUM SKIP-DUPS INCLUDE-RELATED.
If THREADS is non-nil, show results in threaded fasion, SORTFIELD
is a symbol describing the field to sort by (or nil); see
`mu4e~headers-sortfield-choices'. If SORT is `descending', sort
-Z->A, if it's `ascending', sort A->Z. MAXNUM determines the maximum
-number of results to return, or nil for 'unlimited'. If SKIP-DUPS
-is non-nil, show only one of duplicate messages (see
-`mu4e-headers-skip-duplicates'). If INCLUDE-RELATED is non-nil,
+Z->A, if it's `ascending', sort A->Z. MAXNUM determines the
+maximum number of results to return, or nil for 'unlimited'. If
+SKIP-DUPS is non-nil, show only one of duplicate messages (see
+`mu4e-headers-skip-duplicates'). If INCLUDE-RELATED is non-nil,
include messages related to the messages matching the search
query (see `mu4e-headers-include-related').
@@ -351,9 +350,9 @@ or an error."
(if include-related "true" "false")))
(defun mu4e~proc-move (docid-or-msgid &optional maildir flags no-view)
- "Move message identified by DOCID-OR-MSGID to optional MAILDIR
-and optionally setting FLAGS. If MAILDIR is nil, message will be
-moved within the same maildir.
+ "Move message identified by DOCID-OR-MSGID.
+Optionally to MAILDIR and optionally setting FLAGS. If MAILDIR is
+nil, message will be moved within the same maildir.
At least one of MAILDIR and FLAGS must be specified. Note that
even when MAILDIR is nil, this is still a filesystem move, since
@@ -386,19 +385,19 @@ Returns either (:update ... ) or (:error ) sexp, which are handled my
(unless (or maildir flags)
(mu4e-error "At least one of maildir and flags must be specified"))
(unless (or (not maildir)
- (file-exists-p (concat mu4e-maildir "/" maildir "/")))
+ (file-exists-p (concat mu4e-maildir "/" maildir "/")))
(mu4e-error "Target dir does not exist"))
(let* ((idparam (mu4e~docid-msgid-param docid-or-msgid))
- (flagstr
- (when flags
- (concat " flags:"
- (if (stringp flags) flags (mu4e-flags-to-string flags)))))
- (path
- (when maildir
- (format " maildir:%s" (mu4e~escape maildir))))
- (rename
- (if (and maildir mu4e-change-filenames-when-moving)
- "true" "false")))
+ (flagstr
+ (when flags
+ (concat " flags:"
+ (if (stringp flags) flags (mu4e-flags-to-string flags)))))
+ (path
+ (when maildir
+ (format " maildir:%s" (mu4e~escape maildir))))
+ (rename
+ (if (and maildir mu4e-change-filenames-when-moving)
+ "true" "false")))
(mu4e~proc-send-command "cmd:move %s %s %s %s %s"
idparam
(or flagstr "")
@@ -407,15 +406,20 @@ Returns either (:update ... ) or (:error ) sexp, which are handled my
(format "noview:%s" (if no-view "true" "false")))))
(defun mu4e~proc-index (path my-addresses cleanup lazy-check)
- "Update the message database for filesystem PATH, which should
-point to some maildir directory structure. MY-ADDRESSES is a list
-of 'my' email addresses (see `mu4e-user-mail-address-list')."
+ "Index messages on PATH with possible CLEANUP and LAZY-CHECK.
+PATH should point to some maildir directory structure.
+MY-ADDRESSES is a list of 'my' email addresses (see
+`mu4e-user-mail-address-list')."
(let ((path (mu4e~escape path))
- (addrs (when my-addresses (mapconcat 'identity my-addresses ","))))
+ (addrs (when my-addresses (mapconcat 'identity my-addresses ","))))
(if addrs
(mu4e~proc-send-command
- "cmd:index path:%s my-addresses:%s cleanup:%s lazy-check:%s"
- path addrs (if cleanup "true" : "false") (if lazy-check "true"))
+ "cmd:index path:%s my-addresses:%s cleanup:%s lazy-check:%s contacts:%s"
+ path
+ addrs
+ (if cleanup "true" : "false")
+ (if lazy-check "true")
+ (if mu4e-compose-complete-addresses "true"))
(mu4e~proc-send-command "cmd:index path:%s" path))))
(defun mu4e~proc-add (path maildir)
@@ -441,12 +445,12 @@ e.g. '/drafts'.
(defun mu4e~proc-compose (type decrypt &optional docid)
- "Start composing a message of certain TYPE (a symbol, either
-`forward', `reply', `edit', `resend' or `new', based on an
-original message (ie, replying to, forwarding, editing,
-resending) with DOCID or nil for type `new'.
+ "Compose a message of TYPE, DECRYPT it and use DOCID.
+TYPE is a symbol, either `forward', `reply', `edit', `resend' or
+`new', based on an original message (ie, replying to, forwarding,
+editing, resending) with DOCID or nil for type `new'.
-The result will be delivered to the function registered as
+The result is delivered to the function registered as
`mu4e-compose-func'."
(unless (member type '(forward reply edit resend new))
(mu4e-error "Unsupported compose-type %S" type))
@@ -461,54 +465,55 @@ The result will be delivered to the function registered as
(mu4e~proc-send-command "cmd:mkdir path:%s" (mu4e~escape path)))
(defun mu4e~proc-extract (action docid partidx decrypt
- &optional path what param)
- "Extract an attachment with index PARTIDX from message with DOCID
-and perform ACTION on it (as symbol, either `save', `open', `temp') which
-mean:
- * save: save the part to PARAM1 (a path) (non-optional for save)$
- * open: open the part with the default application registered for doing so
- * temp: save to a temporary file, then respond with
+ &optional path what param)
+ "Perform ACTION on part with DOCID PARTIDX DECRYPT PATH WHAT PARAM.
+Use a message with DOCID and perform ACTION on it (as symbol,
+either `save', `open', `temp') which mean: * save: save the part
+to PATH (a path) (non-optional for save)$ * open: open the part
+with the default application registered for doing so * temp: save
+to a temporary file, then respond with
(:temp <path> :what <what> :param <param>)."
(let ((cmd
- (concat "cmd:extract "
- (cl-case action
- (save
- (format "action:save docid:%d index:%d path:%s extract-encrypted:%s use-agent:true"
- docid partidx (mu4e~escape path) (if decrypt "true" "false")))
- (open (format "action:open docid:%d index:%d extract-encrypted:%s use-agent:true"
- docid partidx (if decrypt "true" "false")))
- (temp
- (format "action:temp docid:%d index:%d what:%s%s extract-encrypted:%s use-agent:true"
- docid partidx what
- (if param
- (if (stringp param)
- (format " param:%s" (mu4e~escape param))
- (format " param:%S" param)) "") (if decrypt "true" "false")))
- (otherwise (mu4e-error "Unsupported action %S" action))))
- ))
+ (concat "cmd:extract "
+ (cl-case action
+ (save
+ (format "action:save docid:%d index:%d path:%s extract-encrypted:%s use-agent:true"
+ docid partidx (mu4e~escape path) (if decrypt "true" "false")))
+ (open (format "action:open docid:%d index:%d extract-encrypted:%s use-agent:true"
+ docid partidx (if decrypt "true" "false")))
+ (temp
+ (format "action:temp docid:%d index:%d what:%s%s extract-encrypted:%s use-agent:true"
+ docid partidx what
+ (if param
+ (if (stringp param)
+ (format " param:%s" (mu4e~escape param))
+ (format " param:%S" param)) "") (if decrypt "true" "false")))
+ (otherwise (mu4e-error "Unsupported action %S" action))))
+ ))
(mu4e~proc-send-command "%s" cmd)))
-
(defun mu4e~proc-ping ()
"Sends a ping to the mu server, expecting a (:pong ...) in response."
(mu4e~proc-send-command "cmd:ping"))
-(defun mu4e~proc-contacts (personal after)
- "Sends the contacts command to the mu server.
-A (:contacts (<list>)) is expected in response. If PERSONAL is
-non-nil, only get personal contacts, if AFTER is non-nil, get
-only contacts seen AFTER (the time_t value)."
+(defun mu4e~proc-contacts (personal after tstamp)
+ "Ask for contacts with PERSONAL AFTER TSTAMP.
+S-expression (:contacts (<list>) :tstamp \"<tstamp>\") is expected in
+response. If PERSONAL is non-nil, only get personal contacts, if
+AFTER is non-nil, get only contacts seen AFTER (the time_t
+value)."
(mu4e~proc-send-command
- "cmd:contacts personal:%s after:%d"
+ "cmd:contacts personal:%s after:%d tstamp:%s"
(if personal "true" "false")
- (or after 0)))
+ (or after 0)
+ (or tstamp "0")))
(defun mu4e~proc-view (docid-or-msgid &optional images decrypt)
- "Get one particular message based on its DOCID-OR-MSGID.
+ "Get a message DOCID-OR-MSGID.
Optionally, if IMAGES is non-nil, backend will any images
-attached to the message, and return them as temp files.
-The result will be delivered to the function registered as
-`mu4e-view-func'."
+attached to the message, and return them as temp files. DECRYPT
+if necessary. The result will be delivered to the function
+registered as `mu4e-view-func'."
(mu4e~proc-send-command
"cmd:view %s extract-images:%s extract-encrypted:%s use-agent:true"
(mu4e~docid-msgid-param docid-or-msgid)
@@ -516,11 +521,11 @@ The result will be delivered to the function registered as
(if decrypt "true" "false")))
(defun mu4e~proc-view-path (path &optional images decrypt)
- "View message at PATH (keyword argument).
+ "View message at PATH..
Optionally, if IMAGES is non-nil, backend will any images
attached to the message, and return them as temp files. The
result will be delivered to the function registered as
-`mu4e-view-func'."
+`mu4e-view-func'. Optionally DECRYPT."
(mu4e~proc-send-command
"cmd:view path:%s extract-images:%s extract-encrypted:%s use-agent:true"
(mu4e~escape path)
@@ -528,12 +533,11 @@ result will be delivered to the function registered as
(if decrypt "true" "false")))
(defun mu4e~proc-remove (docid)
- "Remove message identified by docid.
-The results are reporter through either (:update ... ) or (:error)
-sexp, which are handled my `mu4e-error-func', respectively."
+ "Remove message with DOCID.
+The results are reporter through either (:update ... )
+or (:error) sexp, which are handled my `mu4e-error-func',
+respectively."
(mu4e~proc-send-command "cmd:remove docid:%d" docid))
-
(provide 'mu4e-proc)
-
-;; End of mu4e-proc.el
+;;; mu4e-proc.el ends here
diff --git a/mu4e/mu4e-utils.el b/mu4e/mu4e-utils.el
index 72fe2c7..ae43a33 100644
--- a/mu4e/mu4e-utils.el
+++ b/mu4e/mu4e-utils.el
@@ -1,7 +1,6 @@
;;; mu4e-utils.el -- part of mu4e, the mu mail user agent
;;
-;; Copyright (C) 2011-2017 Dirk-Jan C. Binnema
-;; Copyright (C) 2013 Tibor Simko
+;; Copyright (C) 2011-2019 Dirk-Jan C. Binnema
;; Author: Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
;; Maintainer: Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
@@ -666,7 +665,8 @@ process."
"Indexing completed; processed %d, updated %d, cleaned-up %d"
(plist-get info :processed) (plist-get info :updated)
(plist-get info :cleaned-up))
- (unless (zerop (plist-get info :updated))
+ (unless (and (not (string= mu4e~contacts-tstamp "0"))
+ (zerop (plist-get info :updated)))
(mu4e~request-contacts-maybe)
(run-hooks 'mu4e-index-updated-hook)))))
((plist-get info :message)
@@ -680,121 +680,39 @@ process."
(t (error "Error %d: %s" errcode errmsg))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;; RFC2822 handling of phrases in mail-addresses
-;;; The optional display-name contains a phrase, it sits before the angle-addr
-;;; as specified in RFC2822 for email-addresses in header fields.
-;;; contributed by jhelberg
-
-(defun mu4e~rfc822-phrase-type (ph)
- "Return either atom, quoted-string, a corner-case or nil. This
- checks for empty string first. Then quotes around the phrase
- (returning 'rfc822-quoted-string). Then whether there is a quote
- inside the phrase (returning 'rfc822-containing-quote).
- The reverse of the RFC atext definition is then tested.
- If it matches, nil is returned, if not, it is an 'rfc822-atom, which
- is returned."
- (cond
- ((= (length ph) 0) 'rfc822-empty)
- ((= (aref ph 0) ?\")
- (if (string-match "\"\\([^\"\\\n]\\|\\\\.\\|\\\\\n\\)*\"" ph)
- 'rfc822-quoted-string
- 'rfc822-containing-quote)) ; starts with quote, but doesn't end with one
- ((string-match-p "[\"]" ph) 'rfc822-containing-quote)
- ((string-match-p "[\000-\037()\*<>@,;:\\\.]+" ph) nil)
- (t 'rfc822-atom)))
-
-(defun mu4e~rfc822-quoteit (ph)
- "Quote RFC822 phrase only if necessary.
- Atoms and quoted strings don't need quotes. The rest do. In
- case a phrase contains a quote, it will be escaped."
- (let ((type (mu4e~rfc822-phrase-type ph)))
- (cond
- ((eq type 'rfc822-atom) ph)
- ((eq type 'rfc822-quoted-string) ph)
- ((eq type 'rfc822-containing-quote)
- (format "\"%s\""
- (replace-regexp-in-string "\"" "\\\\\"" ph)))
- (t (format "\"%s\"" ph)))))
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-(defsubst mu4e~process-contact (contact)
- "Process CONTACT, and either return nil when it should not be included,
-or (rfc822-string . CONTACT) otherwise."
- (when mu4e-contact-rewrite-function
- (setq contact (funcall mu4e-contact-rewrite-function contact)))
- (when contact
- (let ((name (plist-get contact :name))
- (mail (plist-get contact :mail))
- (ignore-rx (or mu4e-compose-complete-ignore-address-regexp "$^")))
- (when (and mail (not (string-match ignore-rx mail)))
- (cons
- (if name (format "%s <%s>" (mu4e~rfc822-quoteit name) mail) mail)
- contact)))))
-
-
-(defun mu4e~sort-contacts (contacts)
- "Destructively sort contacts (only for cycling) in order of
- 'mostly likely contact'.t See the code for the detail"
- (let* ((now (+ (float-time) 3600)) ;; allow for clock diffs
- (recent (- (float-time) (* 15 24 3600))))
- (cl-sort contacts
- (lambda (c1 c2)
- (let* ( (c1 (cdr c1)) (c2 (cdr c2))
- (personal1 (plist-get c1 :personal))
- (personal2 (plist-get c2 :personal))
- ;; note: freq, tstamp can only be missing if the rewrite
- ;; function removed them. If the rewrite function changed the
- ;; contact somehow, we guess it's important.
- (freq1 (or (plist-get c1 :freq) 500))
- (freq2 (or (plist-get c2 :freq) 500))
- (tstamp1 (or (plist-get c1 :tstamp) now))
- (tstamp2 (or (plist-get c2 :tstamp) now)))
- ;; only one is personal? if so, that one comes first
- (if (not (equal personal1 personal2))
- (if personal1 t nil)
- ;; only one is recent? that one comes first
- (if (not (equal (> tstamp1 recent) (> tstamp2 recent)))
- (> tstamp1 tstamp2)
- ;; otherwise, use the frequency
- (> freq1 freq2))))))))
-
-(defun mu4e~sort-contacts-for-completion (contacts)
- "Takes CONTACTS, which is a list of RFC-822 addresses, and sort them based
-on the ranking in `mu4e~contacts.'"
- (cl-sort contacts
- (lambda (c1 c2)
- (let ((rank1 (gethash c1 mu4e~contacts))
- (rank2 (gethash c2 mu4e~contacts)))
- (< rank1 rank2)))))
-
-;; start and stopping
-(defun mu4e~fill-contacts (contact-data)
- "We receive a list of contacts, which each contact of the form
- (:me NAME :mail EMAIL :tstamp TIMESTAMP :freq FREQUENCY) and
-fill the hash `mu4e~contacts' with it, with each contact mapped
-to an integer for their ranking.
+(defvar mu4e~contacts-tstamp "0"
+ "Timestamp for the most recent contacts update." )
+
+(defun mu4e~update-contacts (contacts &optional tstamp)
+ "Rceive a sorted list of CONTACTS.
+Each of the contacts has the form
+ (FULL_EMAIL_ADDRESS . RANK) and fill the hash
+`mu4e~contacts' with it, with each contact mapped to an integer
+for their ranking.
This is used by the completion function in mu4e-compose."
- (let ((contacts) (rank 0))
- (dolist (contact contact-data)
- (let ((contact-maybe (mu4e~process-contact contact)))
- ;; note, this gives cells (rfc822-address . contact)
- (when contact-maybe (push contact-maybe contacts))))
- (setq contacts (mu4e~sort-contacts contacts))
- ;; now, we have our nicely sorted list, map them to a list
- ;; of increasing integers. We use that map in the composer
- ;; to sort them there. It would have been so much easier if emacs
- ;; allowed us to use the sorted-list as-is, but no such luck.
- (setq mu4e~contacts (make-hash-table :test 'equal :weakness nil
- :size (length contacts)))
+ ;; We have our nicely sorted list, map them to a list
+ ;; of increasing integers. We use that map in the composer
+ ;; to sort them there. It would have been so much easier if emacs
+ ;; allowed us to use the sorted-list as-is, but no such luck.
+ (let ((n 0))
+ (unless mu4e~contacts
+ (setq mu4e~contacts (make-hash-table :test 'equal :weakness nil
+ :size (length contacts))))
(dolist (contact contacts)
- (puthash (car contact) rank mu4e~contacts)
- (incf rank))
- (mu4e-index-message "Contacts received: %d"
- (hash-table-count mu4e~contacts))))
+ (incf n)
+ (let ((address
+ (if (functionp mu4e-contact-process-function)
+ (funcall mu4e-contact-process-function (car contact))
+ (car contact))))
+ (when address
+ (puthash address (cdr contact) mu4e~contacts))))
+
+ (setq mu4e~contacts-tstamp (or tstamp "0"))
+ (mu4e-index-message "Contacts updated: %d; total %d"
+ n (hash-table-count mu4e~contacts))))
(defun mu4e~check-requirements ()
"Check for the settings required for running mu4e."
@@ -855,21 +773,21 @@ Checks whether the server process is live."
the list of contacts we use for autocompletion; otherwise, do
nothing."
(when mu4e-compose-complete-addresses
- (setq mu4e-contacts-func 'mu4e~fill-contacts)
+ (setq mu4e-contacts-func 'mu4e~update-contacts)
(mu4e~proc-contacts
mu4e-compose-complete-only-personal
(when mu4e-compose-complete-only-after
- (float-time
- (apply 'encode-time
- (mu4e-parse-time-string mu4e-compose-complete-only-after)))))))
+ (float-time
+ (apply 'encode-time
+ (mu4e-parse-time-string mu4e-compose-complete-only-after))))
+ mu4e~contacts-tstamp)))
(defun mu4e~start (&optional func)
"If `mu4e-contexts' have been defined, but we don't have a
context yet, switch to the matching one, or none matches, the
-first.
-If mu4e is already running, execute function FUNC (if non-nil).
-Otherwise, check various requirements, then start mu4e. When
-successful, call FUNC (if non-nil) afterwards."
+first. If mu4e is already running, execute function FUNC (if
+non-nil). Otherwise, check various requireme`'nts, then start mu4e.
+When successful, call FUNC (if non-nil) afterwards."
;; if we're already running, simply go to the main view
(if (mu4e-running-p) ;; already running?
(when func (funcall func)) ;; yes! run func if defined
@@ -905,7 +823,8 @@ successful, call FUNC (if non-nil) afterwards."
"Clear any cached resources."
(setq
mu4e-maildir-list nil
- mu4e~contacts nil))
+ mu4e~contacts nil
+ mu4e~contacts-tstamp "0"))
(defun mu4e~stop ()
"Stop the mu4e session."
diff --git a/mu4e/mu4e-vars.el b/mu4e/mu4e-vars.el
index 5b4dee1..8704ae8 100644
--- a/mu4e/mu4e-vars.el
+++ b/mu4e/mu4e-vars.el
@@ -1,6 +1,6 @@
;;; mu4e-vars.el -- part of mu4e, the mu mail user agent
;;
-;; Copyright (C) 2011-2018 Dirk-Jan C. Binnema
+;; Copyright (C) 2011-2019 Dirk-Jan C. Binnema
;; Author: Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
;; Maintainer: Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
@@ -37,7 +37,7 @@
"Location of the mu homedir, or nil for the default."
:group 'mu4e
:type '(choice (const :tag "Default location" nil)
- (directory :tag "Specify location"))
+ (directory :tag "Specify location"))
:safe 'stringp)
(defcustom mu4e-mu-binary (executable-find "mu")
@@ -111,7 +111,7 @@ faster." :type 'boolean :group 'mu4e :safe 'booleanp)
If nil, don't update automatically. Note, changes in
`mu4e-update-interval' only take effect after restarting mu4e."
:type '(choice (const :tag "No automatic update" nil)
- (integer :tag "Seconds"))
+ (integer :tag "Seconds"))
:group 'mu4e
:safe 'integerp)
@@ -199,27 +199,27 @@ where QUERY is a string with a mu query, DESCRIPTION is a short
description of the query (this will show up in the UI), and KEY
is a shortcut key for the query."
:type '(repeat (list (string :tag "Query")
- (string :tag "Description")
- character))
+ (string :tag "Description")
+ character))
:group 'mu4e)
(defvar mu4e-bookmarks
`( ,(make-mu4e-bookmark
- :name "Unread messages"
- :query "flag:unread AND NOT flag:trashed"
- :key ?u)
+ :name "Unread messages"
+ :query "flag:unread AND NOT flag:trashed"
+ :key ?u)
,(make-mu4e-bookmark
- :name "Today's messages"
- :query "date:today..now"
- :key ?t)
+ :name "Today's messages"
+ :query "date:today..now"
+ :key ?t)
,(make-mu4e-bookmark
- :name "Last 7 days"
- :query "date:7d..now"
- :key ?w)
+ :name "Last 7 days"
+ :query "date:7d..now"
+ :key ?w)
,(make-mu4e-bookmark
- :name "Messages with images"
- :query "mime:image/*"
- :key ?p))
+ :name "Messages with images"
+ :query "mime:image/*"
+ :key ?p))
"A list of pre-defined queries.
Each query is represented by a mu4e-bookmark structure with
parameters @t{:name} with the name of the bookmark, @t{:query}
@@ -236,15 +236,15 @@ A symbol which is either:
* `horizontal': split horizontally (headers on top)
* `vertical': split vertically (headers on the left).
* `single-window': view and headers in one window (mu4e will try not to
- touch your window layout), main view in minibuffer
+ touch your window layout), main view in minibuffer
* anything else: don't split (show either headers or messages,
- not both)
+ not both)
Also see `mu4e-headers-visible-lines'
and `mu4e-headers-visible-columns'."
:type '(choice (const :tag "Split horizontally" horizontal)
- (const :tag "Split vertically" vertical)
- (const :tag "Single window" single-window)
- (const :tag "Don't split" nil))
+ (const :tag "Split vertically" vertical)
+ (const :tag "Single window" single-window)
+ (const :tag "Don't split" nil))
:group 'mu4e-headers)
(defcustom mu4e-view-max-specpdl-size 4096
@@ -301,12 +301,12 @@ contexts match, we have the following choices:
Also see `mu4e-compose-context-policy'."
:type '(choice
- (const :tag "Always ask what context to use, even if one matches"
- 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))
+ (const :tag "Always ask what context to use, even if one matches"
+ 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))
:group 'mu4e)
;; crypto
@@ -326,8 +326,8 @@ The setting is a symbol:
* `ask': ask before decrypting anything
* nil: don't try to decrypt anything."
:type '(choice (const :tag "Try to decrypt automatically" t)
- (const :tag "Ask before decrypting anything" ask)
- (const :tag "Don't try to decrypt anything" nil))
+ (const :tag "Ask before decrypting anything" ask)
+ (const :tag "Don't try to decrypt anything" nil))
:group 'mu4e-crypto)
;; completion; we put them here rather than in mu4e-compose, as mu4e-utils needs
@@ -353,7 +353,7 @@ addresses)."
:type 'boolean
:group 'mu4e-compose)
-(defcustom mu4e-compose-complete-only-after "2010-01-01"
+(defcustom mu4e-compose-complete-only-after "2014-01-01"
"Consider only contacts last seen after this date.
Date must be a string, in a format parseable by
`org-parse-time-string'. This excludes really old contacts.
@@ -370,42 +370,39 @@ Set to nil to not have any time-based restriction."
It is used as the identity function for converting contacts to
their canonical counterpart; useful as an example."
(let ((name (plist-get contact :name))
- (mail (plist-get contact :mail)))
+ (mail (plist-get contact :mail)))
(list :name name :mail mail)))
-(defcustom mu4e-contact-rewrite-function nil
- "Function for rewriting or removing contacts.
+(make-obsolete-variable 'mu4e-contacts-rewrite-function
+ "mu4e-contact-process-function (see docstring)" "mu4e 1.3.2")
+(make-obsolete-variable 'mu4e-compose-complete-ignore-address-regexp
+ "mu4e-contact-process-function (see docstring)" "mu4e 1.3.2")
-If the function receives the contact as a list of the form
- (:name NAME :mail EMAIL ... other properties ... )
- (other properties may be there as well)
+(defcustom mu4e-contact-process-function nil
+ "Function for processing contact information for use in auto-completion.
-The function should return either:
- - nil: remove this contact, or
-- the rewritten cell, or
-- the existing cell as-is
+The function receives the contact as a string, e.g
+ \"Foo Bar <foo.bar@example.com>\"
+ \"cuux@example.com\"
-For rewriting, it is recommended to use `plist-put' to set the
-changed parameters, so the other properties stay in place. Those
-are needed for sorting the contacts."
+The function should return either:
+- nil: do not use this contact for completion
+- the (possibly rewritten) address, which must be
+an RFC-2822-compatible e-mail address."
:type 'function
:group 'mu4e-compose)
-(defcustom mu4e-compose-complete-ignore-address-regexp "no-?reply"
- "Ignore any e-mail addresses for completion if they match this regexp."
- :type 'string
- :group 'mu4e-compose)
-
-(defcustom mu4e-compose-reply-ignore-address message-dont-reply-to-names
+(defcustom mu4e-compose-reply-ignore-address
+message-dont-reply-to-names
"Addresses to prune when doing wide replies.
-This can be a regexp matching the address, a list of regexps
-or a predicate function. A value of nil keeps all the addresses."
+This can be a regexp matching the address, a list of regexps or a
+predicate function. A value of nil keeps all the addresses."
:type '(choice
- (const nil)
- function
- string
- (repeat string))
+ (const nil)
+ function
+ string
+ (repeat string))
:group 'mu4e-compose)
(defcustom mu4e-compose-reply-to-address nil
@@ -448,8 +445,8 @@ parameter refers to the original message being replied to / being
forwarded / re-edited and is nil otherwise. `mu4e-drafts-folder'
is only evaluated once."
:type '(choice
- (string :tag "Folder name")
- (function :tag "Function return folder name"))
+ (string :tag "Folder name")
+ (function :tag "Function return folder name"))
:group 'mu4e-folders)
(defcustom mu4e-refile-folder "/archive"
@@ -459,8 +456,8 @@ function that takes a message (a msg plist, see
`mu4e-message-field'), and returns a folder. Note that the
message parameter refers to the message-at-point."
:type '(choice
- (string :tag "Folder name")
- (function :tag "Function return folder name"))
+ (string :tag "Folder name")
+ (function :tag "Function return folder name"))
:group 'mu4e-folders)
(defcustom mu4e-sent-folder "/sent"
@@ -471,8 +468,8 @@ function that takes a message (a msg plist, see
message parameter refers to the original message being replied to
/ being forwarded / re-edited, and is nil otherwise."
:type '(choice
- (string :tag "Folder name")
- (function :tag "Function return folder name"))
+ (string :tag "Folder name")
+ (function :tag "Function return folder name"))
:group 'mu4e-folders)
(defcustom mu4e-trash-folder "/trash"
@@ -487,8 +484,8 @@ message-at-point. When using it when composing a message (see
message being replied to / being forwarded / re-edited, and is
nil otherwise."
:type '(choice
- (string :tag "Folder name")
- (function :tag "Function return folder name"))
+ (string :tag "Folder name")
+ (function :tag "Function return folder name"))
:group 'mu4e-folders)
(defcustom mu4e-maildir-shortcuts nil
@@ -714,113 +711,113 @@ mu4e-compose-mode."
(defconst mu4e-header-info
'( (:attachments .
( :name "Attachments"
- :shortname "Atts"
- :help "Message attachments"
- :require-full t
- :sortable nil))
+ :shortname "Atts"
+ :help "Message attachments"
+ :require-full t
+ :sortable nil))
(:bcc .
( :name "Bcc"
- :shortname "Bcc"
- :help "Blind Carbon-Copy recipients for the message"
- :sortable t))
+ :shortname "Bcc"
+ :help "Blind Carbon-Copy recipients for the message"
+ :sortable t))
(:cc .
( :name "Cc"
- :shortname "Cc"
- :help "Carbon-Copy recipients for the message"
- :sortable t))
+ :shortname "Cc"
+ :help "Carbon-Copy recipients for the message"
+ :sortable t))
(:date .
( :name "Date"
- :shortname "Date"
- :help "Date/time when the message was written"
- :sortable t))
+ :shortname "Date"
+ :help "Date/time when the message was written"
+ :sortable t))
(:human-date .
( :name "Date"
- :shortname "Date"
- :help "Date/time when the message was written."
- :sortable :date))
+ :shortname "Date"
+ :help "Date/time when the message was written."
+ :sortable :date))
(:flags .
( :name "Flags"
- :shortname "Flgs"
- :help "Flags for the message"
- :sortable nil))
+ :shortname "Flgs"
+ :help "Flags for the message"
+ :sortable nil))
(:from .
( :name "From"
- :shortname "From"
- :help "The sender of the message"
- :sortable t))
+ :shortname "From"
+ :help "The sender of the message"
+ :sortable t))
(:from-or-to .
( :name "From/To"
- :shortname "From/To"
- :help "Sender of the message if it's not me; otherwise the recipient"
- :sortable nil))
+ :shortname "From/To"
+ :help "Sender of the message if it's not me; otherwise the recipient"
+ :sortable nil))
(:maildir .
( :name "Maildir"
- :shortname "Maildir"
- :help "Maildir for this message"
- :sortable t))
+ :shortname "Maildir"
+ :help "Maildir for this message"
+ :sortable t))
(:list .
( :name "List-Id"
- :shortname "List"
- :help "Mailing list id for this message"
- :sortable t))
+ :shortname "List"
+ :help "Mailing list id for this message"
+ :sortable t))
(:mailing-list .
( :name "List"
- :shortname "List"
- :help "Mailing list friendly name for this message"
- :sortable :list))
+ :shortname "List"
+ :help "Mailing list friendly name for this message"
+ :sortable :list))
(:message-id .
( :name "Message-Id"
- :shortname "MsgID"
- :help "Message-Id for this message"
- :sortable nil))
+ :shortname "MsgID"
+ :help "Message-Id for this message"
+ :sortable nil))
(:path .
( :name "Path"
- :shortname "Path"
- :help "Full filesystem path to the message"
- :sortable t))
+ :shortname "Path"
+ :help "Full filesystem path to the message"
+ :sortable t))
(:signature .
( :name "Signature"
- :shortname "Sgn"
- :help "Check for the cryptographic signature"
- :require-full t
- :sortable nil))
+ :shortname "Sgn"
+ :help "Check for the cryptographic signature"
+ :require-full t
+ :sortable nil))
(:decryption .
( :name "Decryption"
- :shortname "Dec"
- :help "Check the cryptographic decryption status"
- :require-full t
- :sortable nil))
+ :shortname "Dec"
+ :help "Check the cryptographic decryption status"
+ :require-full t
+ :sortable nil))
(:size .
( :name "Size"
- :shortname "Size"
- :help "Size of the message"
- :sortable t))
+ :shortname "Size"
+ :help "Size of the message"
+ :sortable t))
(:subject .
( :name "Subject"
- :shortname "Subject"
- :help "Subject of the message"
- :sortable t))
+ :shortname "Subject"
+ :help "Subject of the message"
+ :sortable t))
(:tags .
( :name "Tags"
- :shortname "Tags"
- :help "Tags for the message"
- :sortable nil))
+ :shortname "Tags"
+ :help "Tags for the message"
+ :sortable nil))
(:thread-subject .
( :name "Subject"
- :shortname "Subject"
- :help "Subject of the thread"
- :sortable :subject))
+ :shortname "Subject"
+ :help "Subject of the thread"
+ :sortable :subject))
(:to .
( :name "To"
- :shortname "To"
- :help "Recipient of the message"
- :sortable t))
+ :shortname "To"
+ :help "Recipient of the message"
+ :sortable t))
(:user-agent .
( :name "User-Agent"
- :shortname "UA"
- :help "Program used for writing this message"
- :require-full t
- :sortable t)))
+ :shortname "UA"
+ :help "Program used for writing this message"
+ :require-full t
+ :sortable t)))
"An alist of all possible header fields and information about them.
This is used in the user-interface (the column headers in the header list, and
the fields the message view).
@@ -845,13 +842,13 @@ Note, `:sortable' is not supported for custom header fields.")
(defvar mu4e-header-info-custom
'( (:recipnum .
( :name "Number of recipients"
- :shortname "Recip#"
- :help "Number of recipients for this message"
- :function
- (lambda (msg)
- (format "%d"
- (+ (length (mu4e-message-field msg :to))
- (length (mu4e-message-field msg :cc))))))))
+ :shortname "Recip#"
+ :help "Number of recipients for this message"
+ :function
+ (lambda (msg)
+ (format "%d"
+ (+ (length (mu4e-message-field msg :to))
+ (length (mu4e-message-field msg :cc))))))))
"A list of custom (user-defined) headers.
The format is similar
to `mu4e-header-info', but adds a :function property, which
diff --git a/mu4e/mu4e.texi b/mu4e/mu4e.texi
index f70fd1a..d9a9f6e 100644
--- a/mu4e/mu4e.texi
+++ b/mu4e/mu4e.texi
@@ -1120,16 +1120,16 @@ An example message view:
Date: Mon 19 Jan 2004 09:39:42 AM EET
Maildir: /inbox
Attachments(2): [1]DSCN4961.JPG(1.3M), [2]DSCN4962.JPG(1.4M)
-
+
Hi Julia,
-
+
Some pics from our trip to Cerin Amroth. Enjoy!
-
+
All the best,
Randy.
-
+
On Sun 21 Dec 2003 09:06:34 PM EET, Julia wrote:
-
+
[....]
@end verbatim
@end cartouche
@@ -1571,9 +1571,9 @@ functionality is available, as well some @t{mu4e}-specifics. Its major mode is
To: Wally the Walrus <wally@example.com>
Subject: Re: Eau-qui d'eau qui?
--text follows this line--
-
+
On Mon 16 Jan 2012 10:18:47 AM EET, Wally the Walrus wrote:
-
+
> Hi Rupert,
>
> Dude - how are things?
@@ -2574,8 +2574,8 @@ when starting; see the discussion in the previous section.
:leave-func (lambda () (mu4e-message "Leaving Private context"))
;; we match based on the contact-fields of the message
:match-func (lambda (msg)
- (when msg
- (mu4e-message-contact-field-matches msg
+ (when msg
+ (mu4e-message-contact-field-matches msg
:to "aliced@@home.example.com")))
:vars '( ( user-mail-address . "aliced@@home.example.com" )
( user-full-name . "Alice Derleth" )
@@ -2615,12 +2615,12 @@ when starting; see the discussion in the previous section.
;; set `mu4e-context-policy` and `mu4e-compose-policy` to tweak when mu4e should
;; guess or ask the correct context, e.g.
- ;; start with the first (default) context;
+ ;; start with the first (default) context;
;; default is to ask-if-none (ask when there's no context yet, and none match)
;; (setq mu4e-context-policy 'pick-first)
;; compose with the current context is no context matches;
- ;; default is to ask
+ ;; default is to ask
;; (setq mu4e-compose-context-policy nil)
@end lisp
@@ -2629,25 +2629,25 @@ A couple of notes about this example:
@item You can manually switch the context use @code{M-x mu4e-context-switch},
by default bound to @kbd{;} in headers, view and main mode.
The current context appears in the mode-line.
-@item Normally, @code{M-x mu4e-context-switch} does not call the enter or
+@item Normally, @code{M-x mu4e-context-switch} does not call the enter or
leave functions if the 'new' context is the same as the old one.
However, with a prefix-argument (@kbd{C-u}), you can force @t{mu4e} to
invoke those function even in that case.
-@item The function @code{mu4e-context-current} returns the current-context;
+@item The function @code{mu4e-context-current} returns the current-context;
the current context is also visible in the mode-line when in
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} are
not changeable after they have been set without quitting @t{mu4e} 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
context we are entering.
@item @code{enter-func} (if defined) is invoked before setting the variables.
@item @code{match-func} (if defined) is invoked just before @code{mu4e-compose-pre-hook}.
@item See the variables @code{mu4e-context-policy} and
-@code{mu4e-compose-context-policy} to tweak what @t{mu4e} should do when
+@code{mu4e-compose-context-policy} to tweak what @t{mu4e} should do when
no context matches (or if you always want to be asked).
-@item Finally, be careful to get the quotations right --- backticks, single quotes
+@item Finally, be careful to get the quotations right --- backticks, single quotes
and commas and note the '.' between variable name and its value.
@end itemize
@@ -3128,41 +3128,42 @@ As a fairly useless example, suppose we insist on reading @t{mu4e} as
@node Contact functions
@section Contact functions
-It can sometimes be useful to rewrite the contact information that
-@t{mu4e} provides, for example to convert them to some standardized
-format, or to fix spelling errors. And sometimes, you may want to remove
-certain contacts altogether.
+It can sometimes be useful to discard or rewrite the contact
+information that @t{mu4e} provides, for example to fix spelling
+errors, or omit unwanted contacts.
-For this, @t{mu4e} provides @code{mu4e-contact-rewrite-function}, which
-passes each contact to a user-provided function, which is expected to
-return either the possibly rewritten contact or @code{nil} to remove the
-contact from the list --- note that the latter can also be achieved using
-@code{mu4e-compose-complete-ignore-address-regexp}.
+To handle this, @t{mu4e} provides
+@code{mu4e-contact-process-function}, which, if defined, is applied to
+each contact. If the result is @t{nil}, the contact is discarded,
+otherwise the (modified or not) contact information is used.
-Each of the contacts are property-lists (`plists'), with properties
-@code{:name} (which may be @code{nil}), and @code{:mail}, and a number
-of other properties which you should return unchanged.
+Each contact is a full e-mail address as you would see in a
+contact-field of an e-mail message, e.g.,
+@verbatim
+"Foo Bar" <foo.bar@example.com>
+@end verbatim
+or
+@verbatim
+cuux@example.com
+@end verbatim
-Let's look at an example:
+An example @code{mu4e-contact-process-function} might look like:
@lisp
-(defun my-rewrite-function (contact)
- (let ((name (or (plist-get contact :name) ""))
- (mail (plist-get contact :mail)))
- (cond
- ;; jonh smiht --> John Smith
- ((string= "jonh smiht" name)
- (plist-put contact :name "John C. Smith")
- contact)
- ;; remove evilspammer from the contacts list
- ((string= "evilspammer@@example.com" mail) nil)
- ;; others stay as the are
- (t contact))))
-
-(setq mu4e-contact-rewrite-function 'my-rewrite-function)
+(defun my-contact-processor (contact)
+ (cond
+ ;; remove unwanted
+ ((string-match-p "evilspammer@@example.com" contact) nil)
+ ((string-match-p "noreply" contact) nil)
+ ;;
+ ;; jonh smiht --> John Smith
+ ((string-match "jonh smiht" contact)
+ (replace-regexp-in-string "jonh smiht" "John Smith" contact))
+ (t contact)))
+
+(setq mu4e-contact-process-function 'my-contact-processor)
@end lisp
-This function is called for each of your contacts.
@node Utility functions
@section Utility functions
@@ -3329,7 +3330,7 @@ such as @file{~/.emacs.d/init.el}) the following @emph{after} the
(setq mu4e-compose-complete-addresses nil)
(setq bbdb-mua-pop-up t)
(setq bbdb-mua-pop-up-window-size 5)
- (setq mu4e-view-show-addresses t)
+ (setq mu4e-view-show-addresses t)
@end lisp
@noindent