* automatic mail retrieval (WIP-2):

- mu4e-main.el: mu4e-update-mail-show-window retrieves mail / updates
    database, show output in split window (actual work is done by...:)
  - mu4e.el: mu4e-update-mail retrieves mail, updates database,
    asynchronously. Optionally, show output in a buffer
    when `mu4e-update-interval' is non-nil and some integer, it calls
    mu4e-update-mail every so many seconds.
  - mu4e.texi: document this
  - TODO: updated
This commit is contained in:
Dirk-Jan C. Binnema
2012-02-28 22:34:22 +02:00
parent d6a53ebee2
commit 253d03aaaa
4 changed files with 170 additions and 82 deletions

View File

@ -4,19 +4,15 @@
** Bugs
*** database locks (solved?)
*** sometimes +S-u-n does not seem to work?
** Features i
*** documentation
*** mu4e-get-sub-maildirs
*** auto-mail check
*** extract mailing list name
*** mark thread
*** bounce support
*** sorting
*** tool bars
*** colorize cited parts in view
*** refiling-by-pattern
*** window management
*** inspect message (muile)
@ -62,6 +58,10 @@
** make links clickable
** integrate with org-contacts
** forward should take the attachments from the original
** auto-mail check
** colorize cited parts in view
** documentation
** sometimes +S-u-n does not seem to work?
# Local Variables:
# mode: org; org-startup-folded: nil

View File

@ -31,6 +31,7 @@
(defconst mu4e-main-buffer-name "*mu4e-main*"
"*internal* Name of the mm main buffer.")
(defvar mu4e-main-mode-map
(let ((map (make-sparse-keymap)))
@ -42,7 +43,7 @@
(define-key map "m" 'mu4e-toggle-mail-sending-mode)
(define-key map "f" 'smtpmail-send-queued-mail)
(define-key map "U" 'mu4e-retrieve-mail-update-db)
(define-key map "U" 'mu4e-update-mail-show-window)
(define-key map "H" 'mu4e-display-manual)
map)
@ -124,7 +125,7 @@ clicked."
(propertize " Misc\n\n" 'face 'mu4e-title-face)
(mu4e-action-str "\t* [U]pdate email & database\n"
'mu4e-retrieve-mail-update-db)
'mu4e-update-mail-show-window)
;; show the queue functions if `smtpmail-queue-dir' is defined
(if (file-directory-p smtpmail-queue-dir)
@ -148,10 +149,28 @@ clicked."
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Interactive functions
(defun mu4e-retrieve-mail-update-db ()
"Get new mail and update the database."
(defconst mu4e-update-buffer-name "*mu4e-update*"
"*internal* Name of the buffer for message retrieval / database
updating.")
(defun mu4e-update-mail-show-window ()
"Try to retrieve mail (using the user-provided shell command),
and update the database afterwards, and show the progress in a
split-window."
(interactive)
(mu4e-proc-retrieve-mail-update-db))
(unless mu4e-get-mail-command
(error "`mu4e-get-mail-command' is not defined"))
(let ((buf (get-buffer-create mu4e-update-buffer-name))
(win
(split-window (selected-window)
(- (window-height (selected-window)) 8))))
(with-selected-window win
(switch-to-buffer buf)
(set-window-dedicated-p win t)
(erase-buffer)
(insert "\n") ;; FIXME -- needed so output starts
(mu4e-update-mail buf))))
(defun mu4e-toggle-mail-sending-mode ()
"Toggle sending mail mode, either queued or direct."
@ -160,9 +179,8 @@ clicked."
(error "`smtp-queue-dir' does not exist"))
(setq smtpmail-queue-mail (not smtpmail-queue-mail))
(message
(if smtpmail-queue-mail
"Outgoing mail will now be queued"
"Outgoing mail will now be sent directly"))
(concat "Outgoing mail will now be "
(if smtpmail-queue-mail "queued" "sent directly")))
(mu4e-main-view))
(provide 'mu4e-main)

View File

@ -69,6 +69,15 @@ PATH, you can specify the full path."
:group 'mu4e
:safe 'stringp)
(defcustom mu4e-update-interval nil
"Number of seconds between automatic calls to retrieve mail and
update the database. If nil, don't update automatically. Note,
changes in `mu4e-update-interval' only take effect after restarting
mu4d."
:type 'integer
:group 'mu4e
:safe 'integerp)
(defcustom mu4e-attachment-dir (expand-file-name "~/")
"Default directory for saving attachments."
:type 'string
@ -90,7 +99,6 @@ limiting search results speeds up searches significantly, it's
useful to limit this. Note, to ignore the limit, use a prefix
argument (C-u) before invoking the search.")
(defvar mu4e-debug nil
"When set to non-nil, log debug information to the *mu4e-log* buffer.")
@ -152,16 +160,17 @@ designated shortcut character for the maildir.")
(defcustom mu4e-headers-fields
'( (:date . 25)
(:flags . 6)
(:from . 22)
(:subject . nil))
'( (:date . 25)
(:flags . 6)
(:from . 22)
(:subject . nil))
"A list of header fields to show in the headers buffer, and their
respective widths in characters. A width of `nil' means
'unrestricted', and this is best reserved fo the rightmost (last)
field. For the complete list of available headers, see `mu4e-header-names'"
:type (list 'symbol)
:group 'mu4e-headers)
field. For the complete list of available headers, see
`mu4e-header-names'"
:type (list 'symbol)
:group 'mu4e-headers)
(defcustom mu4e-headers-date-format "%x %X"
"Date format to use in the headers view, in the format of
@ -170,11 +179,12 @@ designated shortcut character for the maildir.")
:group 'mu4e-headers)
(defcustom mu4e-headers-leave-behavior 'ask
"What do to when user leaves the headers view (e.g. quit or doing
a new search). Value is one of the following symbols:
- ask (ask the user whether to ignore the marks)
- apply (automatically apply the marks before doing anything else)
- ignore (automatically ignore the marks without asking)."
"What to do when user leaves the headers view (e.g. quits,
refreshes or does a new search). Value is one of the following
symbols:
- ask (ask the user whether to ignore the marks)
- apply (automatically apply the marks before doing anything else)
- ignore (automatically ignore the marks without asking)."
:type 'symbol
:group 'mu4e-headers)
@ -394,6 +404,9 @@ dir already existed, or has been created, nil otherwise."
(unless (mu4e-create-maildir-maybe path)
(error "%s (%S) does not exist" path var)))))
(defvar mu4e-update-timer nil
"*internal* The mu4e update timer.")
(defun mu4e ()
"Start mm. We do this by sending a 'ping' to the mu server
process, and start the main view if the 'pong' we receive from the
@ -413,10 +426,26 @@ server has the expected values."
(error "mu server has version %s, but we need %s"
version mu4e-mu-version))
(mu4e-main-view)
(when mu4e-update-interval
(setq mu4e-update-timer
(run-at-time
0 mu4e-update-interval
'mu4e-update-mail)))
(message "Started mu4e with %d message%s in store"
doccount (if (= doccount 1) "" "s"))))
(mu4e-proc-ping)))))
(defun mu4e-quit()
"Quit the mm session."
(interactive)
(when (y-or-n-p "Are you sure you want to quit? ")
(message nil)
(when mu4e-update-timer
(cancel-timer mu4e-update-timer))
(mu4e-kill-proc)
(kill-buffer)))
(defun mu4e-get-maildirs (parentdir)
"List the maildirs under PARENTDIR." ;; TODO: recursive?
(let* ((files (directory-files parentdir))
@ -521,9 +550,7 @@ message files; flags are symbols draft, flagged, new, passed,
replied, seen, trashed and the string is the concatenation of the
uppercased first letters of these flags, as per [1]. Other flags
than the ones listed here are ignored.
Also see `mu4e-flags-to-string'.
\[1\]: http://cr.yp.to/proto/maildir.html"
(when flags
(let ((kar (case (car flags)
@ -612,40 +639,29 @@ function prefers the text part, but this can be changed by setting
;; and finally, remove some crap from the remaining string.
(replace-regexp-in-string "[
 ]" " " body nil nil nil)))
(defconst mu4e-get-mail-name "*mu4e-get-mail*"
(defconst mu4e-update-mail-name "*mu4e-update-mail*"
"*internal* Name of the process to update mail")
(defun mu4e-retrieve-mail-update-db-proc (buf)
"Try to retrieve mail (using `mu4e-get-mail-command'), with
output going to BUF if not nil, or discarded if nil. After
(defun mu4e-update-mail (&optional buf)
"Update mail (retrieve using `mu4e-get-mail-command' and update
the database afterwards), with output going to BUF if not nil, or
discarded if nil. After retrieving mail, update the database. Note,
function is asynchronous, returns (almost) immediately, and all the
processing takes part in the background, unless buf is non-nil."
(unless mu4e-get-mail-command
(error "`mu4e-get-mail-command' is not defined"))
(message "Retrieving mail...")
(let* ((proc (start-process-shell-command
(error "`mu4e-get-mail-command' is not defined"))
(let* ((process-connection-type t)
(proc (start-process-shell-command
mu4e-update-mail-name buf mu4e-get-mail-command)))
(message "Retrieving mail...")
(set-process-sentinel proc
(lambda (proc msg)
(message nil)
(mu4e-proc-index mu4e-maildir)
(let ((buf (process-buffer proc)))
(when (buffer-live-p buf)
(mu4e-proc-index mu4e-maildir)
(kill-buffer buf)))))))
(defun mu4e-retrieve-mail-update-db ()
"Try to retrieve mail (using the user-provided shell command),
and update the database afterwards"
(interactive)
(unless mu4e-get-mail-command
(error "`mu4e-get-mail-command' is not defined"))
(let ((buf (get-buffer-create mu4e-update-buffer-name))
(win
(split-window (selected-window)
(- (window-height (selected-window)) 8))))
(with-selected-window win
(switch-to-buffer buf)
(set-window-dedicated-p win t)
(erase-buffer)
(let ((buf (process-buffer proc)))
(when (buffer-live-p buf)
(kill-buffer buf)))))
(set-process-query-on-exit-flag proc t)))
@ -658,15 +674,6 @@ top level if there is none."
('mu4e-hdrs-mode "(mu4e)Headers view")
('mu4e-view-mode "(mu4e)Message view")
(t "mu4e"))))
(defun mu4e-quit()
"Quit the mm session."
(interactive)
(when (y-or-n-p "Are you sure you want to quit? ")
(message nil)
(mu4e-kill-proc)
(kill-buffer)))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

View File

@ -37,7 +37,7 @@ tested on Debian GNU/Linux.
* Getting started::
* Running mu4e::
* Searching mail::
* Org-mode support::
* Interaction with other tools::
* Example configuration::
* FAQ - Frequently Anticipated Questions::
* Known issues / missing features::
@ -180,6 +180,17 @@ of googling should be able to provide you with the details; also there is full
example of setting @t{mu4e} up with @t{offlineimap} and Gmail; @pxref{Gmail
configuration}.
You can do all of the mail retrieval @emph{outside} of @t{emacs}/@t{mu4e}, but
you can also do it from the @t{mu4e}. For that, set the variable
@code{mu4e-get-mail-command} to the command you want to use for retrieving
mail, which you can then access from the @ref{Main view}.
You can also have this command run periodically (in the background), by
setting the variable @code{mu4e-update-interval} to the number of seconds
between such updates. If set to @code{nil}, it will not update at all. Note
that if you make changes to @code{mu4e-update-interval}, @code{mu4e} must be
restarted before the change will take effect.
@node Indexing your messages
@section Indexing your messages
@ -405,8 +416,7 @@ Finally, there are some @emph{Misc} actions:
@itemize
@item @t{[U]pdate email & database} will execute whatever is in
the variable @code{mu4e-get-mail-command}, and afterwards update the @t{mu}
database; @pxref{Indexing your messages}. This is a synchronous command - you
have to wait for it to finish.
database; @pxref{Indexing your messages}. See @ref{Getting mail} for details.
@item @t{toggle [m]ail sending mode (direct)} will toggle between sending
mail directly, and queuing it first (for example, when you are offline), and
@t{[f]lush queued mail} will flush any queued mail. This item is visible only
@ -487,6 +497,12 @@ The two-step mark-execute sequence is similar to what for example @t{dired}
does; @inforef{(emacs) Dired} - it tries to be as fast as possible while still
trying to protect the user from accidents.
When you try to do a new search, or refresh the headers buffer while you still
have marked messages, by default you will be asked what to do with those marks
-- whether to @emph{apply} them before leaving, @emph{ignore} them or to
@emph{cancel} the operation. This behavior can be influenced with the variable
@code{mu4e-headers-leave-behavior} -- see its documentation.
@node Message view
@section Message view
@ -794,22 +810,20 @@ The same shortcuts are used by the function @code{mu4e-mark-for-move}; so for
example, if you want to move a message the @t{/archive} folder, you can do so
by typing @key{ma}.
@node Org-mode support
@chapter Org-mode support
@node Interaction with other tools
@chapter Interaction with other tools
Many emacs-users use @t{org-mode} for their note-taking, agenda, to-do list
and many other things, so it is useful to integrate e-mail with this as well.
@t{mu4e} support @t{org-mode}-links, and the @t{org-mode}-address book,
@t{org-contact}.
In this chapter we discuss some ways in ways in which @t{mu4e} can cooperate
with other tools.
@menu
* Org-mode links::
* Org-contacts::
* Creating org-mode links::
* Maintaining an address-book with org-contacts::
* Getting new mail notifications with Sauron::
@end menu
@node Org-mode links
@section Org-mode links
@node Creating org-mode links
@section Creating org-mode links
It can be useful to include links to e-mail messages or even search queries in
your org-mode files. @t{mu4e} supports this with the @t{org-mu4e} module; you
can set it up by adding it to your configuration:
@ -826,8 +840,8 @@ org-insert-link}. Then, you can go to the query or message the link points to
with either @t{M-x org-agenda-open-link} in agenda buffers, or @t{M-x
org-open-at-point} elsewhere - both are typically bound to @kbd{C-c C-o}.
@node Org-contacts
@section Org-contacts
@node Maintaining an address-book with org-contacts
@section Maintaining an address-book with org-contacts
To manage your addresses using @t{org-mode}, there is
@t{org-contacts}@footnote{@url{http://julien.danjou.info/software/org-contacts.el}}.
@ -844,7 +858,55 @@ You can use it with a @t{capture}-template:
@end verbatim
After setting this up, you can use @t{M-x org-capture RET c} to get a template
for a new contact based on the 'From:' address.
for a new contact based on` the 'From:' address.
@node Getting new mail notifications with Sauron
@section Getting new mail notifications with Sauron
The emacs-package Sauron@footnote{Sauron can be found at
@url{https://github.com/djcb/sauron}, or in the Marmalade package-repository
at @url{http://http://marmalade-repo.org/}.} (by the same author) can be used
to get notifications about new mails.
If you put something like the below script in your @t{crontab} (or have some
other way of having it execute every @emph{n} minutes, you will receive
notifications in the sauron-buffer when new messages arrive.
@verbatim
#!/bin/sh
# put the path to your Inbox folder here
CHECKDIR="/home/$LOGNAME/Maildir/Inbox"
sauron-msg () {
DBUS_COOKIE="/home/$LOGNAME/.sauron-dbus"
if test "x$DBUS_SESSION_BUS_ADDRESS" = "x"; then
if test -e $DBUS_COOKIE; then
export DBUS_SESSION_BUS_ADDRESS="`cat $DBUS_COOKIE`"
fi
fi
if test -n "x$DBUS_SESSION_BUS_ADDRESS"; then
dbus-send --session \
--dest="org.gnu.Emacs" \
"/org/gnu/Emacs/Sauron" \
"org.gnu.Emacs.Sauron.AddMsgEvent" \
string:shell uint32:3 string:"$1"
fi
}
for f in `find $CHECKDIR -mmin -2 -a -type f`; do
subject=`$MU view $f | grep '^Subject:' | sed 's/^Subject://'`
sauron-msg "mail: $subject"
done
@end verbatim
Note, you should put something like:
@lisp
(setq sauron-dbus-cookie t)
@end lisp
in your setup, which allows the script to find the D-Bus session bus.
@node Example configuration
@chapter Example configuration
@ -1105,7 +1167,8 @@ select ('mark' in emacs-speak) the messages; the actions you then take (e.g.,
@key{DEL} for delete, @key{m} for move and @key{t} for trash) will apply to
@emph{all} selected messages
@item @emph{How can I use @t{BBDB}?} Currently, there is no built-in for
address management with @t{BBDB}; we recommend using @ref{Org-contacts} for now.
address management with @t{BBDB}; instead, we recommend @ref{Maintaining an
address-book with org-contacts} for now.
@item @emph{mu4e only seems to return a subset of all matches - how can I get
all?}. Yes, for speed reasons (and because, if you are like the author, you
usually don't need thousands of matches), @t{mu4e} returns only up to the