X-Git-Url: https://git.notmuchmail.org/git?p=notmuch-wiki;a=blobdiff_plain;f=emacstips.mdwn;h=f5b418c6700cec7588040ed85a4b80248ceb528e;hp=7a23293783bd467d99b8128b917b3d9c63bd4d8a;hb=0364b91f49267bb59ef4a70f78114673f9b3efb0;hpb=b925c865e943f1cf21dd19593f2b7fdcaf92bbc3 diff --git a/emacstips.mdwn b/emacstips.mdwn index 7a23293..f5b418c 100644 --- a/emacstips.mdwn +++ b/emacstips.mdwn @@ -1,145 +1,187 @@ [[!img notmuch-logo.png alt="Notmuch logo" class="left"]] -#Tips and Tricks for using notmuch with Emacs +# Tips and Tricks for using Notmuch with Emacs -The main Notmuch message reading client is **notmuch.el**, which is an -[emacs](http://www.gnu.org/software/emacs/) major mode, and is -included in the notmuch package. +Here are some tips and tricks for using Notmuch with Emacs. See the [[Notmuch +Emacs Interface|notmuch-emacs]] page for basics. -## Setup +[[!toc levels=2]] -To use the Notmuch emacs mode, first add the following line to your -`.emacs` rc file: +## Issues with Emacs 24 - (require 'notmuch) +If notmuch-show-mode behaves badly for you in emacs 24.x try adding one of -Then, either run "emacs -f notmuch", or execute the command `M-x -notmuch` from within a running emacs. + (setq gnus-inhibit-images nil) -## Navigating & reading mails +or -When first starting notmuch in emacs, you will be presented with the -notmuch "hello" page. From here you can do searches, see lists of -recent searches, saved searches, message tags, help information, etc. + (require 'gnus-art) -Executing a search will open a new buffer in `notmuch-search-mode` -displaying the search results. Each line in the search results -represents a message thread. Hitting the '?' key will show help for -this mode. +to your .emacs file. -In general, the 'q' will kill the current notmuch buffer and return -you to the previous buffer (sort of like a 'pop'). +## Controlling external handlers for attachements -In search mode, navigating to a thread and hitting return will then -open a new buffer in `notmuch-show-mode`, which will show the actual -message contents of the thread. +You can choose e.g. which pdf viewer to invoke from notmuch-show mode by +adding a .mailcap file in your home directory. Here is an example: -## Sending mail + application/pdf; /usr/bin/mupdf %s; test=test "$DISPLAY" != ""; description=Portable Document Format; nametemplate=%s.pdf + application/x-pdf; /usr/bin/mupdf %s; test=test "$DISPLAY" != ""; description=Portable Document Format; nametemplate=%s.pdf -In any notmuch mode, you can start a new message by hitting the 'm' -key. To reply to a message or thread, just hit the 'r' key. +## Overwriting the sender address -When composing new messages, you will be entered in emacs's -`message-mode`, which is a powerful mode for composing and sending -messages. When in message move, you can type `C-c ?` for help. +If you want to always use the same sender address, then the following +defadvice can help you. -If you would like to use address autocompletion when composing -messages, see [address completion](#address_completion). + (defadvice notmuch-mua-reply (around notmuch-fix-sender) + (let ((sender "Max Monster ")) + ad-do-it)) + (ad-activate 'notmuch-mua-reply) -When you are ready to send a message, type `C-c C-c`. By default -message mode will use your sendmail command to send mail, so make sure -that works. One annoying standard configuration of message mode is -that it will hide the sent mail in your emacs frame stack, but it will -not close it. If you type several mails in an emacs session they will -accumulate and make switching between buffers more annoying. You can -avoid that behavior by adding `(setq message-kill-buffer-on-exit t)` -in your `.emacs` file which will really close the mail window after -sending it. +## Initial cursor position in notmuch 0.15 hello window -## Attaching files +In notmuch version 0.15 emacs client the handling of cursor position in +notmuch hello window has been simplified to a version which suits best +most cases. -Using the `M-x mml-attach-file` command, you can attach any file to be -send with your mail. By default this command is bound to the menu item -*Attachments--Attach File* with the key binding `C-c C-a`. The -variable `mml-dnd-attach-options` (`M-x -customize-variablemml-dnd-attach-options`) can be set to allow -the prompting for various attachment options (such as -inline/attachment) if you want to do that. +Initially the cursor is positioned at the beginning of buffer. -For those who prefer a more graphical interface, you can also simply -drag and drop files from a file manager into a mail composition window -to have them attached. In Ubuntu this works without any modifications -if files are dragged from the file manager. +Some users liked the "ancient" version where cursor was moved to the +first `Saved searches` button. -And for those who prefer working from command line, the following -script opens new emacs window with empty message and attaches files -mentioned as script arguments. (Note: The script expects that you have -`(server-start)` in your .emacs) +Add the following code to your notmuch emacs configuration file in +case you want this behaviour: - #!/bin/sh - attach_cmds="" - while [ "$1" ]; do - fullpath=$(readlink --canonicalize $1) - attach_cmds="$attach_cmds (mml-attach-file \"$fullpath\")" - shift - done - emacsclient -a '' -c -e "(progn (compose-mail) $attach_cmds)" + (add-hook 'notmuch-hello-refresh-hook + (lambda () + (if (and (eq (point) (point-min)) + (search-forward "Saved searches:" nil t)) + (progn + (forward-line) + (widget-forward 1)) + (if (eq (widget-type (widget-at)) 'editable-field) + (beginning-of-line))))) +## Add a key binding to add/remove/toggle a tag ------ +The `notmuch-{search,show,tree}-tag` functions are very useful for +making quick tag key bindings. The arguments to these functions have +changed as notmuch has evolved but the following should work on all +versions of notmuch from 0.13 on. These functions take a list of +tag changes as argument. For example, an argument of (list "+spam" +"-inbox") adds the tag spam and deletes the tag inbox. Note the +argument must be a list even if there is only a single tag change +e.g., use (list "+deleted") to add the deleted tag. -# Advanced tips and tweaks +For instance, here's an example of how to make a key binding to add +the "spam" tag and remove the "inbox" tag in notmuch-show-mode: -## Add a key binding to add/remove/toggle a tag + (define-key notmuch-show-mode-map "S" + (lambda () + "mark message as spam" + (interactive) + (notmuch-show-tag (list "+spam" "-inbox")))) -The `notmuch-{search,show}-{add,remove}-tag` functions are very useful -for making quick tag key bindings. For instance, here's an example -of how to make a key binding to add the "spam" tag and remove the -"inbox" tag in notmuch-show-mode: +You can do the same for threads in `notmuch-search-mode` by just +replacing "show" with "search" in the keymap and called functions, or +for messages in `notmuch-tree-mode` by replacing "show" by "tree". If +you want to tag a whole thread in `notmuch-tree-mode` use +`notmuch-tree-tag-thread` instead of `notmuch-tree-tag`. - (define-key notmuch-show-mode-map "S" - (lambda () - "mark message as spam" - (interactive) - (notmuch-show-add-tag "spam") - (notmuch-show-remove-tag "inbox"))) +You may also want the function in search mode apply to the all threads +in the selected region (if there is one). For notmuch prior to 0.17 +this behaviour will occur automatically with the functions given +above. To get this behaviour on 0.17+ do the following: -You can do the same for threads in `notmuch-search-mode` by just -replacing "show" with "search" in the called functions. + (define-key notmuch-search-mode-map "S" + (lambda (&optional beg end) + "mark thread as spam" + (interactive (notmuch-search-interactive-region)) + (notmuch-search-tag (list "+spam" "-inbox") beg end))) + +The analogous functionality in notmuch-tree is currently missing. -The definition above makes use of a lambda function, but you could +The definitions above make use of a lambda function, but you could also define a separate function first: - (defun notmuch-show-tag-spam() - "mark message as spam" - (interactive) - (notmuch-show-add-tag "spam") - (notmuch-show-remove-tag "inbox"))) - (define-key notmuch-show-mode-map "S" 'notmuch-show-tag-spam) + (defun notmuch-show-tag-spam () + "mark message as spam" + (interactive) + (notmuch-show-add-tag (list "+spam" "-inbox"))) + + (define-key notmuch-show-mode-map "S" 'notmuch-show-tag-spam) Here's a more complicated example of how to add a toggle "deleted" key: - (define-key notmuch-show-mode-map "d" - (lambda () - "toggle deleted tag for message" - (interactive) - (if (member "deleted" (notmuch-show-get-tags)) - (notmuch-show-remove-tag "deleted") - (notmuch-show-add-tag "deleted")))) + (define-key notmuch-show-mode-map "d" + (lambda () + "toggle deleted tag for message" + (interactive) + (if (member "deleted" (notmuch-show-get-tags)) + (notmuch-show-tag (list "-deleted")) + (notmuch-show-tag (list "+deleted"))))) + +## Adding many tagging keybindings + +If you want to have have many tagging keybindings, you can save the typing +the few lines of boilerplate for every binding (for versions before 0.12, +you will need to change notmuch-show-apply-tag-macro). + + (eval-after-load 'notmuch-show + '(define-key notmuch-show-mode-map "`" 'notmuch-show-apply-tag-macro)) + + (setq notmuch-show-tag-macro-alist + (list + '("m" "+notmuch::patch" "+notmuch::moreinfo" "-notmuch::needs-review") + '("n" "+notmuch::patch" "+notmuch::needs-review" "-notmuch::pushed") + '("o" "+notmuch::patch" "+notmuch::obsolete" + "-notmuch::needs-review" "-notmuch::moreinfo") + '("p" "-notmuch::pushed" "-notmuch::needs-review" + "-notmuch::moreinfo" "+pending") + '("P" "-pending" "-notmuch::needs-review" "-notmuch::moreinfo" "+notmuch::pushed") + '("r" "-notmuch::patch" "+notmuch::review") + '("s" "+notmuch::patch" "-notmuch::obsolete" "-notmuch::needs-review" "-notmuch::moreinfo" "+notmuch::stale") + '("t" "+notmuch::patch" "-notmuch::needs-review" "+notmuch::trivial") + '("w" "+notmuch::patch" "+notmuch::wip" "-notmuch::needs-review"))) + + (defun notmuch-show-apply-tag-macro (key) + (interactive "k") + (let ((macro (assoc key notmuch-show-tag-macro-alist))) + (apply 'notmuch-show-tag-message (cdr macro)))) + +## Restore reply-to-all key binding to 'r' + +Starting from notmuch 0.12 the 'r' key is bound to reply-to-sender instead of +reply-to-all. Here's how to swap the reply to sender/all bindings in show mode: + + (define-key notmuch-show-mode-map "r" 'notmuch-show-reply) + (define-key notmuch-show-mode-map "R" 'notmuch-show-reply-sender) + +And in search mode: + + (define-key notmuch-search-mode-map "r" 'notmuch-search-reply-to-thread) + (define-key notmuch-search-mode-map "R" 'notmuch-search-reply-to-thread-sender) + ## How to do FCC/BCC... The Emacs interface to notmuch will automatically add an `Fcc` header to your outgoing mail so that any messages you send will also be saved in your mail store. You can control where this copy of the -message is saved by setting the variables `message-directory` (which -defines a base directory) and `notmuch-fcc-dirs` which defines the -subdirectory relative to `message-directory` in which to save the -mail. Enter a directory (without the maildir `/cur` ending which -will be appended automatically). To customize both variables at the -same time, use the fancy command: +message is saved by setting the variable `notmuch-fcc-dirs` which defines the +subdirectory relative to the `database.path` setting from your +notmuch configuration in which to save the mail. Enter a directory +(without the maildir `/cur` ending which will be appended +automatically). Additional information can be found as usual using: + + M-x describe-variable notmuch-fcc-dirs - M-x customize-apropos\(notmuch-fcc-dirs\)\|\(message-directory\) +An additional variable that can affect FCC settings in some cases is +`message-directory`. Emacs message-mode uses this variable for +postponed messages. + +To customize both variables at the same time, use the fancy command: + + M-x customize-apropos\(notmuch-fcc-dirs\)\|\(message-directory\) This mechanism also allows you to select different folders to be used for the outgoing mail depending on your selected `From` @@ -155,14 +197,37 @@ saved searches displayed can be modified directly from the notmuch interface (using the `[save]` button next to a previous search) or by customising the variable `notmuch-saved-searches`. -An example setting might be: +An example setting for notmuch versions up to 0.17.x might be: + + (setq notmuch-saved-searches '(("inbox" . "tag:inbox") + ("unread" . "tag:inbox AND tag:unread") + ("notmuch" . "tag:inbox AND to:notmuchmail.org"))) + +Starting from notmuch 0.18 the variable changed. It is backwards +compatible so the above will still work but the new style will be used +if you use customize and there are some new features available. The above would become + + (setq notmuch-saved-searches '((:name "inbox" :query "tag:inbox") + (:name "unread" :query "tag:inbox AND tag:unread") + (:name "notmuch" :query "tag:inbox AND to:notmuchmail.org"))) + +The additional features are the possibility to set the search order +for the search, and the possibility to specify a different query for +displaying the count for the saved-search. For example - (setq notmuch-saved-searches '(("inbox" . "tag:inbox") - ("unread" . "tag:inbox AND tag:unread") - ("notmuch" . "tag:inbox AND to:notmuchmail.org"))) + (setq notmuch-saved-searches '((:name "inbox" + :query "tag:inbox" + :count-query "tag:inbox and tag:unread" + :sort-order oldest-first))) + +specifies a single saved search for inbox, but the number displayed by +the search will be the number of unread messages in the inbox, and the +sort order for this search will be oldest-first. Of course, you can have any number of saved searches, each configured -with any supported search terms (see "notmuch help search-terms"). +with any supported search terms (see "notmuch help search-terms"), and +in the new style variable they can each have different count-queries +and sort orders. Some users find it useful to add `and not tag:delete` to those searches, as they use the `delete` tag to mark messages as @@ -172,49 +237,23 @@ useful to you. ## Viewing HTML messages with an external viewer -The emacs client can often display an HTML message inline, but it -sometimes fails for one reason or another, (or is perhaps inadequate -if you really need to see the graphical presentation of the HTML -message). - -In this case, it can be useful to display the message in an external -viewer, such as a web browser. Here's a little script that Keith -Packard wrote, which he calls `view-html`: - - #!/bin/sh - dir=3D`mktemp -d` - trap "rm -r $dir" 0 - cat "$@" > "$dir"/msg - if munpack -C "$dir" -t < "$dir"/msg 2>&1 | grep 'Did not find'; then - sed -n '/[Hh][Tt][Mm][Ll]/,$p' "$dir"/msg > $dir/part1.html - rm "$dir"/msg - fi - for i in "$dir"/part*; do - if grep -q -i -e '' -e 'text/html' "$i"; then - iceweasel "$i" & - sleep 3 - exit 0 - fi - done - -Save that script somewhere in your `${PATH}`, make it executable, -and change the invocation of `iceweasel` to any other HTML viewer if -necessary. Then within the emacs client, press '|' to pipe the -current message, then type "view-html". - -Keith mentions the following caveat, "Note that if iceweasel isn't -already running, it seems to shut down when the script exits. I -don't know why." +The Emacs client can generally display HTML messages inline using one of the +supported HTML renderers. This is controlled by the `mm-text-html-renderer` +variable. + +Sometimes it may be necessary to display the message, or a single MIME part, in +an external browser. This can be done by `(notmuch-show-view-part)`, bound to +`. v` by default. ## msmtp, message mode and multiple accounts -As an alternative to running a mail server such as sendmail or -postfix just to send email, it is possible to use -[msmtp](http://msmtp.sourceforge.net/). This small application will +As an alternative to running a mail server such as sendmail or postfix +just to send email, it is possible to use +[msmtp](http://msmtp.sourceforge.net/). This small application will look like `/usr/bin/sendmail` to a MUA such as emacs message mode, but -will just forward the email to an external SMTP server. It's fairly -easy to set up and it support several account for using different -SMTP servers. The msmtp pages have several examples. +will just forward the email to an external SMTP server. It's fairly +easy to set up and it supports several accounts for using different +SMTP servers. The msmtp pages have several examples. A typical scenario is that you want to use the company SMTP server for email coming from your company email address, and your personal @@ -235,50 +274,512 @@ With that in place, you need a `.msmtprc` with the accounts configured for the domains you want to send out using specific SMTP servers and the rest will go to the default account. +## sending mail using smtpmail + + + +If setting up local `sendmail` or `msmtp` is not feasible or desirable, +the Emacs `smtpmail` package can be used to send email by talking to remote +SMTP server via TCP connection. It is pretty easy to configure: + +1. Emacs variable `message-send-mail-function` has not been set + + Initially, Emacs variable `message-send-mail-function` has value of + `sendmail-query-once`. When (notmuch) message mode is about to send email, + `sendmail-query-once` will ask how emacs should send email. Typing `smtp` + will configure `smtpmail` and Emacs may prompt for SMTP settings. + +1. `M-x customize-group RET smtpmail` + + As a minimum, 'Smtpmail Smtp Server' needs to be set. + + After doing that, continue with `M-x load-library RET message` and + `M-x customize-variable RET message-send-mail-function`. + In the customization buffer select `message-smtpmail-send-it`. + +1. Set some variables in .emacs or in [notmuch init file](/notmuch-emacs#notmuch_init_file) + + (setq smtpmail-smtp-server "smtp.server.tld" ;; <-- edit this !!! + ;; smtpmail-smtp-service 25 ;; 25 is default -- uncomment and edit if needed + ;; smtpmail-stream-type 'starttls + ;; smtpmail-debug-info t + ;; smtpmail-debug-verb t + message-send-mail-function 'message-smtpmail-send-it) + +Note that emacs 24 or newer is required for `smtpmail-stream-type` +(and smtp authentication) to be effective. + +More information for smtpmail is available: + +* In Emacs: `M-x info-display-manual smtpmail` +* [EmacsWiki Page](http://www.emacswiki.org/emacs/SendingMail) + + ## Address completion when composing -There are currently two solutions to this: +There are currently three solutions to this: + +### notmuch address + +Starting with Notmuch 0.21, there is a builtin command to perform +autocompletion directly within Notmuch. Starting with 0.22, it is +configured by default, so if you have previously configured another +completion mechanism, you may want to try out the new internal +method. Use `M-x customize-variable RET notmuch-address-command` and +reset the value to "internal address completion" (`'internal` in +lisp). + +If you are not yet running 0.22, you can still use it by adding a +wrapper around the command called, say, `notmuch-address`: + + #!/bin/sh + exec notmuch address from:"$*" + +Then you can set the `notmuch-address-command` to `notmuch-address` +(if it is in your `$PATH` of course, otherwise use an absolute path). + +### bbdb [bbdb](http://bbdb.sourceforge.net) is a contact database for emacs that works quite nicely together with message mode, including address autocompletion. +### notmuch database as an address book + You can also use the notmuch database as a mail address book itself. To do this you need a command line tool that outputs likely address -candidates based on a search string. There are currently two +candidates based on a search string. There are currently four available: * The python tool `notmuch_address.py` (`git clone - http://jkr.acm.jhu.edu/git/notmuch_addresses.git`) (slower, but + http://commonmeasure.org/~jkr/git/notmuch_addresses.git`) (slower, but no compilation required so good for testing the setup) + * The C-based [notmuch-addrlookup](https://github.com/aperezdc/notmuch-addrlookup-c) by [Adrian Perez](http://perezdecastro.org/), which is faster but needs to be compiled. + + git clone https://github.com/aperezdc/notmuch-addrlookup-c + cd notmuch-addrlookup-c + make + * The vala-based - [addrlookup](http://github.com/spaetz/vala-notmuch) (faster, but - needs compiling). The addrlookup binary needs to be compiled. + [addrlookup](http://github.com/spaetz/vala-notmuch) The addrlookup binary needs to be compiled. Grab `http://github.com/spaetz/vala-notmuch/raw/static-sources/src/addrlookup.c` and build it with: - cc -o addrlookup addrlookup.c `pkg-config --cflags --libs gobject-2.0` -lnotmuch + cc -o addrlookup addrlookup.c `pkg-config --cflags --libs gobject-2.0` -lnotmuch + + * Shell/fgrep/perl combination [nottoomuch-addresses.sh](https://github.com/domo141/nottoomuch/blob/master/nottoomuch-addresses.rst). + This tools maintains it's own address "database" gathered from email + files notmuch knows and search from that "database" is done by `fgrep(1)`. + + * python/sqlite combination [notmuch-abook](https://github.com/guyzmo/notmuch-abook/) + This tools also maintains an address database in sqlite after harvesting + from notmuch. It also includes a vim plugin. + +You can perform tab-completion using any of these programs. +Just add the following to your [notmuch init file](/notmuch-emacs#notmuch_init_file): + + (require 'notmuch-address) + (setq notmuch-address-command "/path/to/address_fetching_program") + (notmuch-address-message-insinuate) + +### Google Contacts + +[GooBook](http://code.google.com/p/goobook/) is a command-line tool for +accessing Google Contacts. Install and set it up according to its documentation. + +To use GooBook with notmuch, use this wrapper script and set it up like the +programs above. + + #!/bin/sh + goobook query "$*" | sed 's/\(.*\)\t\(.*\)\t.*/\2 \<\1\>/' | sed '/^$/d' + +You can add the sender of a message to Google Contacts by piping the message +(`notmuch-show-pipe-message`) to `goobook add`. + +### Akonadi + + git clone https://github.com/mmehnert/akonadimailsearch + +Install the development packages for kdepim on your system. +Enter the cloned repository and create a build directory: + + mkdir build + cd build + cmake ..; make; + +You will find the akonadimailsearch binary in the build/src directory. Copy it to ~/bin . + +You can now add the following settings to your +[notmuch init file](/notmuch-emacs#notmuch_init_file): + + (require 'notmuch-address) + (setq notmuch-address-command "~/bin/akonadimailsearch") + (notmuch-address-message-insinuate) + +### Completion selection with helm + +An address query might return multiple possible matches from which you +will have to select one. To ease this task, several different +frameworks in emacs support completion selection. One of them is +[helm](https://github.com/emacs-helm/helm). The following snippet +improves the out-of-the-box support for helm in notmuch as it enables +the required-match option and also does not ignore the first returned +address. + + (setq notmuch-address-selection-function + (lambda (prompt collection initial-input) + (completing-read prompt (cons initial-input collection) nil t nil 'notmuch-address-history))) -EUDC is integrated into emacs and is needed for tab completion of -email addresses. See [this -mail](http://mid.gmane.org/87fx3uflkx.fsf@jhu.edu) -(id:87fx3uflkx.fsf@jhu.edu) for more information. ## How to sign/encrypt messages with gpg -Messages can by signed using gpg by invoking `M-x -mml-secure-sign-pgpmime` (or `M-x -mml-secure-encrypt-pgpmime`). These functions are available via the -standard `message-mode` keybindings `C-c C-m s p` and `C-c C-m c -p`. To sign outgoing mail by default, use the `message-setup-hook` -in your `.emacs` file: +Messages can by signed using gpg by invoking +`M-x mml-secure-sign-pgpmime` (or `M-x mml-secure-encrypt-pgpmime`). +These functions are available via the standard `message-mode` keybindings +`C-c C-m s p` and `C-c C-m c p`. To sign outgoing mail by default, use the +`message-setup-hook` in your `.emacs` file: - ;; Sign messages by default. - (add-hook 'message-setup-hook 'mml-secure-sign-pgpmime) + ;; Sign messages by default. + (add-hook 'message-setup-hook 'mml-secure-sign-pgpmime) This inserts the required `<#part sign=pgpmime>` into the beginning of the mail text body and will be converted into a pgp signature when sending (so one can just manually delete that line if signing is not required). + +Alternatively, you may prefer to use `mml-secure-message-sign-pgpmime` instead +of `mml-secure-sign-pgpmime` to sign the whole message instead of just one +part. + +### Troubleshooting message-mode gpg support + +- If you have trouble with expired subkeys, you may have encountered + emacs bug #7931. This is fixed in git commit 301ea744c on + 2011-02-02. Note that if you have the Debian package easypg + installed, it will shadow the fixed version of easypg included with + emacs. + +- If you wish `mml-secure-encrypt` to encrypt also for the sender, then + `M-x customize-variable mml2015-encrypt-to-self` might suit your need. + +## Reading and verifying encrypted and signed messages + +Encrypted and signed mime messages can be read and verified with: + + (setq notmuch-crypto-process-mime t) + +Decrypting or verifying inline pgp messages can be done by selecting +an the inline pgp area and and using: + + M-x epa-decrypt-region RET + +## Multiple identities using gnus-alias + +[gnus-alias](http://www.emacswiki.org/emacs/GnusAlias) allows you to +define multiple identities when using `message-mode`. You can specify +the from address, organization, extra headers (including *Bcc*), extra +body text, and signature for each identity. Identities are chosen +based on a set of rules. When you are in message mode, you can switch +identities using gnus-alias. + +### Installation + +- put `gnus-alias.el` on your load Emacs-Lisp load path (add new directory + to load path by writing `(add-to-list 'load-path "/some/load/path")` into + your `.emacs`. + +- Add the following to your `.emacs` + + (autoload 'gnus-alias-determine-identity "gnus-alias" "" t) + (add-hook 'message-setup-hook 'gnus-alias-determine-identity) + +Looking into `gnus-alias.el` gives a bit more information... + +### Example Configuration + +Here is an example configuration. + + ;; Define two identities, "home" and "work" + (setq gnus-alias-identity-alist + '(("home" + nil ;; Does not refer to any other identity + "John Doe " ;; Sender address + nil ;; No organization header + nil ;; No extra headers + nil ;; No extra body text + "~/.signature") + ("work" + nil + "John Doe " + "Example Corp." + (("Bcc" . "john.doe@example.com")) + nil + "~/.signature.work"))) + ;; Use "home" identity by default + (setq gnus-alias-default-identity "home") + ;; Define rules to match work identity + (setq gnus-alias-identity-rules) + '(("work" ("any" "john.doe@\\(example\\.com\\|help\\.example.com\\)" both) "work")) + ;; Determine identity when message-mode loads + (add-hook 'message-setup-hook 'gnus-alias-determine-identity) + +When `gnus-alias` has been loaded (using autoload, require, *M-x load-library* +or *M-x load-file* (load-file takes file path -- therefore it can be used +without any `.emacs` changes)) the following commands can be used to get(/set) +more information (some of these have "extensive documentation"): + + M-x describe-variable RET gnus-alias-identity-alist + M-x describe-variable RET gnus-alias-identity-rules + M-x describe-variable RET gnus-alias-default-identity + + M-x customize-group RET gnus-alias RET + or + M-x gnus-alias-customize RET + +The last two do the same thing. + +See also the **Usage:** section in `gnus-alias.el`. + +## Multiple identities (and more) with message-templ + +Another option for multiple identities is +[message-templ](http://pivot.cs.unb.ca/git?p=message-templ.git;a=summary) +(also a available in marmalade). This provides roughly the same +facilities as wanderlust's template facility. + +See +[example.emacs.el](http://pivot.cs.unb.ca/git?p=message-templ.git;a=blob;f=example.emacs.el;hb=HEAD) +for some simple examples of usage. + +## Resending (or bouncing) messages + +Add the following to your [notmuch init file](/notmuch-emacs#notmuch_init_file) to be able +to resend the current message in show mode. + + (define-key notmuch-show-mode-map "b" + (lambda (&optional address) + "Bounce the current message." + (interactive "sBounce To: ") + (notmuch-show-view-raw-message) + (message-resend address))) + +## `notmuch-hello` refresh status message + +Add the following to your [notmuch init file](/notmuch-emacs#notmuch_init_file) to get a +status message about the change in the number of messages in the mail store +when refreshing the `notmuch-hello` buffer. + + (defvar notmuch-hello-refresh-count 0) + + (defun notmuch-hello-refresh-status-message () + (unless no-display + (let* ((new-count + (string-to-number + (car (process-lines notmuch-command "count")))) + (diff-count (- new-count notmuch-hello-refresh-count))) + (cond + ((= notmuch-hello-refresh-count 0) + (message "You have %s messages." + (notmuch-hello-nice-number new-count))) + ((> diff-count 0) + (message "You have %s more messages since last refresh." + (notmuch-hello-nice-number diff-count))) + ((< diff-count 0) + (message "You have %s fewer messages since last refresh." + (notmuch-hello-nice-number (- diff-count))))) + (setq notmuch-hello-refresh-count new-count)))) + + (add-hook 'notmuch-hello-refresh-hook 'notmuch-hello-refresh-status-message) + +## Replacing tabs with spaces in subject and header + +Mailman mailing list software rewrites and rewraps long message subjects in +a way that causes TABs to appear in the middle of the subject and header +lines. Add this to your [notmuch init file](/notmuch-emacs#notmuch_init_file) to replace +tabs with spaces in subject lines: + + (defun notmuch-show-subject-tabs-to-spaces () + "Replace tabs with spaces in subject line." + (goto-char (point-min)) + (when (re-search-forward "^Subject:" nil t) + (while (re-search-forward "\t" (line-end-position) t) + (replace-match " " nil nil)))) + + (add-hook 'notmuch-show-markup-headers-hook 'notmuch-show-subject-tabs-to-spaces) + +And in header lines (this will only work with the yet to be released +notmuch version 0.15): + + (defun notmuch-show-header-tabs-to-spaces () + "Replace tabs with spaces in header line." + (setq header-line-format + (notmuch-show-strip-re + (replace-regexp-in-string "\t" " " (notmuch-show-get-subject))))) + + (add-hook 'notmuch-show-hook 'notmuch-show-header-tabs-to-spaces) + +## Hiding unread messages in notmuch-show + +I like to have an inbox saved search, but only show unread messages when they +view a thread. This takes two steps: + +1. Apply +[this patch from Mark Walters](https://notmuchmail.org/pipermail/notmuch/2012/010817.html) +to add the `notmuch-show-filter-thread` function. +1. Add the following hook to your emacs configuration: + + (defun expand-only-unread-hook () (interactive) + (let ((unread nil) + (open (notmuch-show-get-message-ids-for-open-messages))) + (notmuch-show-mapc (lambda () + (when (member "unread" (notmuch-show-get-tags)) + (setq unread t)))) + (when unread + (let ((notmuch-show-hook (remove 'expand-only-unread-hook notmuch-show-hook))) + (notmuch-show-filter-thread "tag:unread"))))) + + (add-hook 'notmuch-show-hook 'expand-only-unread-hook) + +## Changing the color of a saved search based on some other search + +I like to have a saved search for my inbox, but have it change color when there +are thread with unread messages in the inbox. I accomplish this with the +following code in my emacs config: + + (defun color-inbox-if-unread () (interactive) + (save-excursion + (goto-char (point-min)) + (let ((cnt (car (process-lines "notmuch" "count" "tag:inbox and tag:unread")))) + (when (> (string-to-number cnt) 0) + (save-excursion + (when (search-forward "inbox" (point-max) t) + (let* ((overlays (overlays-in (match-beginning 0) (match-end 0))) + (overlay (car overlays))) + (when overlay + (overlay-put overlay 'face '((:inherit bold) (:foreground "green"))))))))))) + (add-hook 'notmuch-hello-refresh-hook 'color-inbox-if-unread) + +## Linking to notmuch messages and threads from the Circe IRC client + +[Circe](https://github.com/jorgenschaefer/circe/wiki) is an IRC client for emacs. +To have clickable buttons for notmuch messages and threads, add the following to +`lui-buttons-list` (using, e.g. M-x customize-variable) + + ("\\(?:id\\|mid\\|thread\\):[0-9A-Za-z][0-9A-Za-z.@-]*" 0 notmuch-show 0) + +If you have notmuch-pick installed, it works fine for this as well. + +## Linking to notmuch messages from org-mode + +Support for linking to notmuch messages is distributed with org-mode, +but as a contrib file, so you might have to work a bit to load it. + +In Debian and derivatives, + + (add-to-list 'load-path "/usr/share/org-mode/lisp") + +Then + + (require 'org-notmuch) + +In general it is nice to have a key for org-links (not just for notmuch). For example + + (define-key global-map "\C-cl" 'org-store-link) + +## Viewing diffs in notmuch + +The following code allows you to view an inline patch in diff-mode +directly from notmuch. This means that normal diff-mode commands like +refine, next hunk etc all work. + + (defun my-notmuch-show-view-as-patch () + "View the the current message as a patch." + (interactive) + (let* ((id (notmuch-show-get-message-id)) + (msg (notmuch-show-get-message-properties)) + (part (notmuch-show-get-part-properties)) + (subject (concat "Subject: " (notmuch-show-get-subject) "\n")) + (diff-default-read-only t) + (buf (get-buffer-create (concat "*notmuch-patch-" id "*"))) + (map (make-sparse-keymap))) + (define-key map "q" 'notmuch-bury-or-kill-this-buffer) + (switch-to-buffer buf) + (let ((inhibit-read-only t)) + (erase-buffer) + (insert subject) + (insert (notmuch-get-bodypart-text msg part nil))) + (set-buffer-modified-p nil) + (diff-mode) + (lexical-let ((new-ro-bind (cons 'buffer-read-only map))) + (add-to-list 'minor-mode-overriding-map-alist new-ro-bind)) + (goto-char (point-min)))) + +and then this function needs to bound to `. d` in the keymap + + (define-key 'notmuch-show-part-map "d" 'my-notmuch-show-view-as-patch) + +## Interfacing with Patchwork + +[Patchwork](http://jk.ozlabs.org/projects/patchwork/) is a web-based system for +tracking patches sent to a mailing list. While the Notmuch project doesn't use +it, many other open source projects do. Having an easy way to get from a patch +email in your favorite mail client to the web page of the patch in the Patchwork +instance is a cool thing to have. Here's how to abuse the notmuch stash feature +to achieve this. (Don't know stash? See `notmuch-show-stash-mlarchive-link`, +bound to `c l` in `notmuch-show`.) + +The trick needed is turning the email Message-ID into a unique Patchwork ID +assigned by Patchwork. We'll use the `pwclient` command-line tool to achieve +this. You'll first need to get that working and configured for the Patchwork +instance you're using. That part is beyond this tip here; please refer to +Patchwork documentation. + +Check your configuration on the command-line, for example: + + /path/to/pwclient -p -n 5 -f "%{id}" + +Note that the -f format argument may require a reasonably new version of the +client. Once you have the above working, you can `M-x customize-variable RET +notmuch-show-stash-mlarchive-link-alist RET`. + +Add a new entry with "Function returning the URL:" set to: + + (lambda (message-id) + (concat "http://patchwork.example.com/patch/" + (nth 0 + (process-lines "/path/to/pwclient" "search" + "-p" "the-project" + "-m" (concat "<" message-id ">") + "-n" "1" + "-f" "%{id}")))) + +Replacing `http://patchwork.example.com/patch/`, `/path/to/pwclient`, and +`the-project` appropiately. You should now be able to stash the Patchwork URL +using `c l`. + +Going further, if the patch has been committed, you can get the commit hash with +this: + + (lambda (message-id) + (nth 0 + (process-lines "/path/to/pwclient" "search" + "-p" "the-project" + "-m" (concat "<" message-id ">") + "-n" "1" + "-f" "%{commit_ref}"))) + +And finally, if the project has a web interface to its source repository, you +can turn the commit hash into a URL pointing there, for example: + + (lambda (message-id) + (concat "http://cgit.example.com/the-project/commit/?id=" + (nth 0 + (process-lines "/path/to/pwclient" "search" + "-p" "the-project" + "-m" (concat "<" message-id ">") + "-n" "1" + "-f" "%{commit_ref}"))))