aboutsummaryrefslogtreecommitdiffstats
path: root/_spacemacs.d/local/mu4e/mu4e-message.el
diff options
context:
space:
mode:
authorAaron LI <aaronly.me@gmail.com>2016-05-16 09:41:22 +0800
committerAaron LI <aaronly.me@gmail.com>2016-05-16 09:41:22 +0800
commit36750b13d1584f03d7a2c95f7f1c5332dc81723b (patch)
tree3462b4dd080d9b26cce5d6ba813590ea57f4671a /_spacemacs.d/local/mu4e/mu4e-message.el
parent7375bd3290dcb2b488efac8d53b7e8283f7adcf4 (diff)
downloaddotfiles-36750b13d1584f03d7a2c95f7f1c5332dc81723b.tar.bz2
_spacemacs.d/local: import mu4e git20160515
Diffstat (limited to '_spacemacs.d/local/mu4e/mu4e-message.el')
-rw-r--r--_spacemacs.d/local/mu4e/mu4e-message.el284
1 files changed, 284 insertions, 0 deletions
diff --git a/_spacemacs.d/local/mu4e/mu4e-message.el b/_spacemacs.d/local/mu4e/mu4e-message.el
new file mode 100644
index 0000000..e339077
--- /dev/null
+++ b/_spacemacs.d/local/mu4e/mu4e-message.el
@@ -0,0 +1,284 @@
+;;; mu4e-message.el -- part of mu4e, the mu mail user agent
+;;
+;; Copyright (C) 2012-2016 Dirk-Jan C. Binnema
+
+;; Author: Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
+;; Maintainer: Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
+
+;; This file is not part of GNU Emacs.
+;;
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; Functions to get data from mu4e-message plist structure
+
+;;; Code:
+(eval-when-compile (byte-compile-disable-warning 'cl-functions))
+
+(require 'mu4e-vars)
+(require 'mu4e-utils)
+
+(require 'cl)
+(require 'html2text)
+
+
+(defcustom mu4e-html2text-command
+ (if (fboundp 'shr-insert-document) 'mu4e-shr2text 'html2text)
+
+ "Either a shell command or a function that converts from html to plain text.
+
+If it is a shell-command, the command reads html from standard
+input and outputs plain text on standard output. If you use the
+htmltext program, it's recommended you use \"html2text -utf8
+-width 72\". Alternatives are the python-based html2markdown, w3m
+and on MacOS you may want to use textutil.
+
+It can also be a function, which takes the current buffer in html
+as input, and transforms it into html (like the `html2text'
+function).
+
+In both cases, the output is expected to be in UTF-8 encoding.
+
+Newer emacs has the shr renderer, and when its available,
+conversion defaults `mu4e-shr2text'; otherwise, the default is
+emacs' built-in `html2text' function."
+ :type '(choice string function)
+ :group 'mu4e-view)
+
+(defcustom mu4e-view-prefer-html nil
+ "Whether to base the body display on the html-version.
+If the e-mail message has no html-version the plain-text version
+is always used."
+ :type 'boolean
+ :group 'mu4e-view)
+
+(defcustom mu4e-view-html-plaintext-ratio-heuristic 5
+ "Ratio between the length of the html and the plain text part
+below which mu4e will consider the plain text part to be 'This
+messages requires html' text bodies."
+ :type 'integer
+ :group 'mu4e-view)
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+(defsubst mu4e-message-field-raw (msg field)
+ "Retrieve FIELD from message plist MSG.
+FIELD is one of :from, :to, :cc, :bcc, :subject, :data,
+:message-id, :path, :maildir, :priority, :attachments,
+:references, :in-reply-to, :body-txt, :body-html
+
+Returns `nil' if the field does not exist.
+
+A message plist looks something like:
+\(:docid 32461
+ :from ((\"Nikola Tesla\" . \"niko@example.com\"))
+ :to ((\"Thomas Edison\" . \"tom@example.com\"))
+ :cc ((\"Rupert The Monkey\" . \"rupert@example.com\"))
+ :subject \"RE: what about the 50K?\"
+ :date (20369 17624 0)
+ :size 4337
+ :message-id \"6BDC23465F79238C8233AB82D81EE81AF0114E4E74@123213.mail.example.com\"
+ :path \"/home/tom/Maildir/INBOX/cur/133443243973_1.10027.atlas:2,S\"
+ :maildir \"/INBOX\"
+ :priority normal
+ :flags (seen)
+ :attachments
+ ((:index 2 :name \"photo.jpg\" :mime-type \"image/jpeg\" :size 147331)
+ (:index 3 :name \"book.pdf\" :mime-type \"application/pdf\" :size 192220))
+ :references (\"6BDC23465F79238C8384574032D81EE81AF0114E4E74@123213.mail.example.com\"
+ \"6BDC23465F79238203498230942D81EE81AF0114E4E74@123213.mail.example.com\")
+ :in-reply-to \"6BDC23465F79238203498230942D81EE81AF0114E4E74@123213.mail.example.com\"
+ :body-txt \"Hi Tom, ...\"
+\)).
+Some notes on the format:
+- The address fields are lists of pairs (NAME . EMAIL), where NAME can be nil.
+- The date is in format emacs uses in `current-time'
+- Attachments are a list of elements with fields :index (the number of
+ the MIME-part), :name (the file name, if any), :mime-type (the
+ MIME-type, if any) and :size (the size in bytes, if any).
+- Messages in the Headers view come from the database and do not have
+ :attachments, :body-txt or :body-html fields. Message in the
+ Message view use the actual message file, and do include these fields."
+ ;; after all this documentation, the spectacular implementation
+ (if msg
+ (plist-get msg field)
+ (mu4e-error "message must be non-nil")))
+
+(defsubst mu4e-message-field (msg field)
+ "Retrieve FIELD from message plist MSG.
+Like `mu4e-message-field-nil', but will sanitize `nil' values:
+- all string field except body-txt/body-html: nil -> \"\"
+- numeric fields + dates : nil -> 0
+- all others : return the value
+Thus, function will return nil for empty lists, non-existing body-txt or body-html."
+ (let ((val (mu4e-message-field-raw msg field)))
+ (cond
+ (val
+ val) ;; non-nil -> just return it
+ ((member field '(:subject :message-id :path :maildir :in-reply-to))
+ "") ;; string fields except body-txt, body-html: nil -> ""
+ ((member field '(:body-html :body-txt))
+ val)
+ ((member field '(:docid :size))
+ 0) ;; numeric type: nil -> 0
+ (t
+ val)))) ;; otherwise, just return nil
+
+(defsubst mu4e-message-has-field (msg field)
+ "Return t if MSG contains FIELD, nil otherwise."
+ (plist-member msg field))
+
+(defsubst mu4e-message-at-point (&optional noerror)
+ "Get the message s-expression for the message at point in either
+the headers buffer or the view buffer, or nil if there is no such
+message. If optional NOERROR is non-nil, do not raise an error when
+there is no message at point."
+ (let ((msg (or (get-text-property (point) 'msg) mu4e~view-msg)))
+ (if msg
+ msg
+ (unless noerror (mu4e-warn "No message at point")))))
+
+(defsubst mu4e-message-field-at-point (field)
+ "Get the field FIELD from the message at point.
+This is equivalent to:
+ (mu4e-message-field (mu4e-message-at-point) FIELD)."
+ (mu4e-message-field (mu4e-message-at-point) field))
+
+(defun mu4e-message-body-text (msg)
+ "Get the body in text form for this message.
+This is either :body-txt, or if not available, :body-html converted
+to text, using `mu4e-html2text-command' is non-nil, it will use
+that. Normally, thiss function prefers the text part, but this can
+be changed by setting `mu4e-view-prefer-html'."
+ (let* ((txt (mu4e-message-field msg :body-txt))
+ (html (mu4e-message-field msg :body-html))
+ (body
+ (cond
+ ;; does it look like some text? ie., if the text part is more than
+ ;; mu4e-view-html-plaintext-ratio-heuristic times shorter than the
+ ;; html part, it should't be used
+ ;; This is an heuristic to guard against 'This messages requires
+ ;; html' text bodies.
+ ((and (> (* mu4e-view-html-plaintext-ratio-heuristic
+ (length txt)) (length html))
+ ;; use html if it's prefered, unless there is no html
+ (or (not mu4e-view-prefer-html) (not html)))
+ txt)
+ ;; otherwise, it there some html?
+ (html
+ (with-temp-buffer
+ (insert html)
+ (cond
+ ((stringp mu4e-html2text-command)
+ (let* ((tmp-file (mu4e-make-temp-file "html")))
+ (write-region (point-min) (point-max) tmp-file)
+ (erase-buffer)
+ (call-process-shell-command mu4e-html2text-command tmp-file t t)
+ (delete-file tmp-file)))
+ ((functionp mu4e-html2text-command)
+ (funcall mu4e-html2text-command))
+ (t (mu4e-error "Invalid `mu4e-html2text-command'")))
+ (buffer-string))
+ )
+ (t ;; otherwise, an empty body
+ ""))))
+ ;; and finally, remove some crap from the remaining string; it seems
+ ;; esp. outlook lies about its encoding (ie., it says 'iso-8859-1' but
+ ;; really it's 'windows-1252'), thus giving us these funky chars. here, we
+ ;; either remove them, or replace with 'what-was-meant' (heuristically)
+ (with-temp-buffer
+ (insert body)
+ (goto-char (point-min))
+ (while (re-search-forward "[  ’]" nil t)
+ (replace-match
+ (cond
+ ((string= (match-string 0) "’") "'")
+ (t ""))))
+ (buffer-string))))
+
+(defun mu4e-message-contact-field-matches (msg cfield rx)
+ "Checks whether any of the of the contacts in field
+CFIELD (either :to, :from, :cc or :bcc, or a list of those) of
+msg MSG matches (with their name or e-mail address) regular
+expressions RX. If there is a match, return non-nil; otherwise
+return nil. RX can also be a list of regular expressions, in
+which case any of those are tried for a match."
+ (if (and cfield (listp cfield))
+ (or (mu4e-message-contact-field-matches msg (car cfield) rx)
+ (mu4e-message-contact-field-matches msg (cdr cfield) rx))
+ (when cfield
+ (if (listp rx)
+ ;; if rx is a list, try each one of them for a match
+ (find-if
+ (lambda (a-rx) (mu4e-message-contact-field-matches msg cfield a-rx))
+ rx)
+ ;; not a list, check the rx
+ (find-if
+ (lambda (ct)
+ (let ((name (car ct)) (email (cdr ct)))
+ (or
+ (and name (string-match rx name))
+ (and email (string-match rx email)))))
+ (mu4e-message-field msg cfield))))))
+
+(defun mu4e-message-contact-field-matches-me (msg cfield)
+ "Checks whether any of the of the contacts in field
+CFIELD (either :to, :from, :cc or :bcc) of msg MSG matches *me*,
+that is, any of the e-mail address in
+`mu4e-user-mail-address-list'. Returns the contact cell that
+matched, or nil."
+ (find-if
+ (lambda (cc-cell)
+ (member-if
+ (lambda (addr)
+ (string= (downcase addr) (downcase (cdr cc-cell))))
+ mu4e-user-mail-address-list))
+ (mu4e-message-field msg cfield)))
+
+(defsubst mu4e-message-part-field (msgpart field)
+ "Get some field in a message part; a part would look something like:
+ (:index 2 :name \"photo.jpg\" :mime-type \"image/jpeg\" :size 147331)."
+ (plist-get msgpart field))
+
+;; backward compatibility ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+(defalias 'mu4e-msg-field 'mu4e-message-field)
+(defalias 'mu4e-body-text 'mu4e-message-body-text) ;; backward compatibility
+
+(defun mu4e-field-at-point (field)
+ "Get FIELD (a symbol, see `mu4e-header-info') for the message at
+point in eiter the headers buffer or the view buffer."
+ (plist-get (mu4e-message-at-point) field))
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+
+(defun mu4e-shr2text ()
+ "Html to text using the shr engine; this can be used in
+`mu4e-html2text-command' in a new enough emacs. Based on code by
+Titus von der Malsburg."
+ (interactive)
+ (let ((dom (libxml-parse-html-region (point-min) (point-max)))
+ ;; When HTML emails contain references to remote images,
+ ;; retrieving these images leaks information. For example,
+ ;; the sender can see when I openend the email and from which
+ ;; computer (IP address). For this reason, it is preferrable
+ ;; to not retrieve images.
+ ;; See this discussion on mu-discuss:
+ ;; https://groups.google.com/forum/#!topic/mu-discuss/gr1cwNNZnXo
+ (shr-inhibit-images t))
+ (erase-buffer)
+ (shr-insert-document dom)
+ (goto-char (point-min))))
+
+(provide 'mu4e-message)