]> git.cworth.org Git - notmuch-wiki/blobdiff - emacstips.mdwn
news/release-0.31.2.mdwn: attempt to sort w/ time
[notmuch-wiki] / emacstips.mdwn
index 24ed641be39b9b0375a2957b5f7c14ba27349799..7baa679a3d125513d0f287173fd3ee2789e4f64e 100644 (file)
@@ -18,7 +18,7 @@ or
 
 to your .emacs file.
 
 
 to your .emacs file.
 
-## Controlling external handlers for attachements
+## Controlling external handlers for attachments
 
 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:
 
 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:
@@ -94,7 +94,7 @@ above. To get this behaviour on 0.17+ do the following:
         (define-key notmuch-search-mode-map "S"
           (lambda (&optional beg end)
             "mark thread as spam"
         (define-key notmuch-search-mode-map "S"
           (lambda (&optional beg end)
             "mark thread as spam"
-            (interactive (notmuch-search-interactive-region))
+            (interactive (notmuch-interactive-region))
             (notmuch-search-tag (list "+spam" "-inbox") beg end)))
 
 The analogous functionality in notmuch-tree is currently missing.
             (notmuch-search-tag (list "+spam" "-inbox") beg end)))
 
 The analogous functionality in notmuch-tree is currently missing.
@@ -156,11 +156,15 @@ 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)
 
         (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:
+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)
 
 
         (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)
 
+And in tree mode:
+
+        (define-key notmuch-tree-mode-map "r" (notmuch-tree-close-message-pane-and #'notmuch-show-reply))
+        (define-key notmuch-tree-mode-map "R" (notmuch-tree-close-message-pane-and #'notmuch-show-reply-sender))
 
 ## How to do FCC/BCC...
 
 
 ## How to do FCC/BCC...
 
@@ -218,7 +222,7 @@ displaying the count for the saved-search. For example
         (setq notmuch-saved-searches '((:name "inbox"
                                         :query "tag:inbox"
                                         :count-query "tag:inbox and tag:unread"
         (setq notmuch-saved-searches '((:name "inbox"
                                         :query "tag:inbox"
                                         :count-query "tag:inbox and tag:unread"
-                                        :sort-order 'oldest-first)))
+                                        :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
 
 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
@@ -245,6 +249,21 @@ 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.
 
 an external browser. This can be done by `(notmuch-show-view-part)`, bound to
 `. v` by default.
 
+This command will try to view the message part the point is on with an
+external viewer. The mime-type of the part will determine what viewer
+will be used. Typically a 'text/html' part will be send to your
+browser. 
+
+The configuration for this is kept in so called `mailcap`
+files. (typically the file is `~/.mailcap` or `/etc/mailcap`) If the
+wrong viewer is started or something else goes wrong, there's a good
+chance something needs to be adapted in the mailcap configuration.
+
+For Example: The `copiousoutput` setting in mailcap files needs to be
+removed for some mime-types to prevent immediate removal of tempory
+files so the configured viewer can access them.
+
+
 ## msmtp, message mode and multiple accounts
 
 As an alternative to running a mail server such as sendmail or postfix
 ## msmtp, message mode and multiple accounts
 
 As an alternative to running a mail server such as sendmail or postfix
@@ -274,10 +293,72 @@ 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.
 
 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
+
+<!-- By default message mode will use the system `sendmail` command to send
+mail. However, on a typical desktop machine there may not be local SMTP
+daemon running (nor it is configured to send mail outside of the system). -->
+
+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)
+
+
 ## <span id="address_completion">Address completion when composing</span>
 
 There are currently three solutions to this:
 
 ## <span id="address_completion">Address completion when composing</span>
 
 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
 ### bbdb
 
 [bbdb](http://bbdb.sourceforge.net) is a contact database for emacs
@@ -300,7 +381,7 @@ available:
         git clone https://github.com/aperezdc/notmuch-addrlookup-c
         cd notmuch-addrlookup-c
         make
         git clone https://github.com/aperezdc/notmuch-addrlookup-c
         cd notmuch-addrlookup-c
         make
-        
+
   * The vala-based
     [addrlookup](http://github.com/spaetz/vala-notmuch) The addrlookup binary needs to be compiled.
     Grab
   * The vala-based
     [addrlookup](http://github.com/spaetz/vala-notmuch) The addrlookup binary needs to be compiled.
     Grab
@@ -310,7 +391,7 @@ available:
             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).
             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
+    This tools maintains its 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/)
     files notmuch knows and search from that "database" is done by `fgrep(1)`.
 
   * python/sqlite combination [notmuch-abook](https://github.com/guyzmo/notmuch-abook/)
@@ -318,7 +399,7 @@ available:
     from notmuch.  It also includes a vim plugin.
 
 You can perform tab-completion using any of these programs.
     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_init_file):
+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")
 
         (require 'notmuch-address)
         (setq notmuch-address-command "/path/to/address_fetching_program")
@@ -352,7 +433,7 @@ Enter the cloned repository and create a build directory:
 You will find the akonadimailsearch binary in the build/src directory. Copy it to ~/bin .
 
 You can now add the following settings to your
 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_init_file):
+[notmuch init file](/notmuch-emacs#notmuch_init_file):
 
         (require 'notmuch-address)
         (setq notmuch-address-command "~/bin/akonadimailsearch")
 
         (require 'notmuch-address)
         (setq notmuch-address-command "~/bin/akonadimailsearch")
@@ -375,7 +456,7 @@ address.
 
 ## How to sign/encrypt messages with gpg
 
 
 ## How to sign/encrypt messages with gpg
 
-Messages can by signed using gpg by invoking
+Messages can be 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
 `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
@@ -383,6 +464,7 @@ These functions are available via the standard `message-mode` keybindings
 
         ;; 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)
+        (setq mml-secure-openpgp-sign-with-sender t)
 
 This inserts the required `<#part sign=pgpmime>` into the beginning
 of the mail text body and will be converted into a pgp signature
 
 This inserts the required `<#part sign=pgpmime>` into the beginning
 of the mail text body and will be converted into a pgp signature
@@ -393,6 +475,42 @@ 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.
 
 of `mml-secure-sign-pgpmime` to sign the whole message instead of just one
 part.
 
+If you want to automatically encrypt outgoing messages if the keyring
+contains a public key for every recipient, you can add something like
+that to your `.emacs` file:
+
+    (defun message-recipients ()
+      "Return a list of all recipients in the message, looking at TO, CC and BCC.
+
+    Each recipient is in the format of `mail-extract-address-components'."
+      (mapcan (lambda (header)
+                (let ((header-value (message-fetch-field header)))
+                  (and
+                   header-value
+                   (mail-extract-address-components header-value t))))
+              '("To" "Cc" "Bcc")))
+
+    (defun message-all-epg-keys-available-p ()
+      "Return non-nil if the pgp keyring has a public key for each recipient."
+      (require 'epa)
+      (let ((context (epg-make-context epa-protocol)))
+        (catch 'break
+          (dolist (recipient (message-recipients))
+            (let ((recipient-email (cadr recipient)))
+              (when (and recipient-email (not (epg-list-keys context recipient-email)))
+                (throw 'break nil))))
+          t)))
+
+    (defun message-sign-encrypt-if-all-keys-available ()
+      "Add MML tag to encrypt message when there is a key for each recipient.
+
+    Consider adding this function to `message-send-hook' to
+    systematically send encrypted emails when possible."
+      (when (message-all-epg-keys-available-p)
+        (mml-secure-message-sign-encrypt)))
+
+    (add-hook 'message-send-hook #'message-sign-encrypt-if-all-keys-available
+
 ### Troubleshooting message-mode gpg support
 
 - If you have trouble with expired subkeys, you may have encountered
 ### Troubleshooting message-mode gpg support
 
 - If you have trouble with expired subkeys, you may have encountered
@@ -401,17 +519,26 @@ part.
   installed, it will shadow the fixed version of easypg included with
   emacs.
 
   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:
 
 ## Reading and verifying encrypted and signed messages
 
 Encrypted and signed mime messages can be read and verified with:
 
-        (notmuch-crypto-process-mime t)
+        (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:
+Decrypting inline pgp messages can be done by selecting an the inline pgp area
+and using:
 
         M-x epa-decrypt-region RET
 
 
         M-x epa-decrypt-region RET
 
+Verifying of inline pgp messages is not supported directly ([reasons
+here](https://dkg.fifthhorseman.net/notes/inline-pgp-harmful/)). You can still
+verify a part using
+
+        M-x notmuch-show-pipe-part RET gpg --verify RET
+
 ## Multiple identities using gnus-alias
 
 [gnus-alias](http://www.emacswiki.org/emacs/GnusAlias) allows you to
 ## Multiple identities using gnus-alias
 
 [gnus-alias](http://www.emacswiki.org/emacs/GnusAlias) allows you to
@@ -457,8 +584,8 @@ Here is an example configuration.
         ;; Use "home" identity by default
         (setq gnus-alias-default-identity "home")
         ;; Define rules to match work identity
         ;; 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"))
+        (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)
 
         ;; Determine identity when message-mode loads
         (add-hook 'message-setup-hook 'gnus-alias-determine-identity)
 
@@ -479,9 +606,20 @@ The last two do the same thing.
 
 See also the **Usage:** section in `gnus-alias.el`.
 
 
 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
 
 ## Resending (or bouncing) messages
 
-Add the following to your [notmuch init file](#notmuch_init_file) to be able
+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"
 to resend the current message in show mode.
 
         (define-key notmuch-show-mode-map "b"
@@ -493,7 +631,7 @@ to resend the current message in show mode.
 
 ## `notmuch-hello` refresh status message
 
 
 ## `notmuch-hello` refresh status message
 
-Add the following to your [notmuch init file](#notmuch_init_file) to get a
+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.
 
 status message about the change in the number of messages in the mail store
 when refreshing the `notmuch-hello` buffer.
 
@@ -523,7 +661,7 @@ when refreshing the `notmuch-hello` buffer.
 
 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
 
 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_init_file) to replace
+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 ()
 tabs with spaces in subject lines:
 
         (defun notmuch-show-subject-tabs-to-spaces ()
@@ -552,7 +690,7 @@ I like to have an inbox saved search, but only show unread messages when they
 view a thread. This takes two steps:
 
 1. Apply
 view a thread. This takes two steps:
 
 1. Apply
-[this patch from Mark Walters](http://notmuchmail.org/pipermail/notmuch/2012/010817.html)
+[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:
 
 to add the `notmuch-show-filter-thread` function.
 1. Add the following hook to your emacs configuration:
 
@@ -606,6 +744,13 @@ In Debian and derivatives,
 
     (add-to-list 'load-path "/usr/share/org-mode/lisp")
 
 
     (add-to-list 'load-path "/usr/share/org-mode/lisp")
 
+In NixOS, using `emacsWithPackages (epkgs: [ epkgs.orgPackages.org-plus-contrib ])`,
+
+    (loop for p in load-path
+          do (if (file-accessible-directory-p p)
+                 (let ((m (directory-files-recursively p "^org-notmuch.el$")))
+                      (if m (add-to-list 'load-path (file-name-directory (car m)))))))
+
 Then
 
     (require 'org-notmuch)
 Then
 
     (require 'org-notmuch)
@@ -614,6 +759,9 @@ In general it is nice to have a key for org-links (not just for notmuch). For ex
 
     (define-key global-map "\C-cl" 'org-store-link)
 
 
     (define-key global-map "\C-cl" 'org-store-link)
 
+Note the package was renamed from `org-notmuch` to `ol-notmuch` in recent
+versions of org-mode, and you might want to `(require 'ol-notmuch)` instead.
+
 ## Viewing diffs in notmuch
 
 The following code allows you to view an inline patch in diff-mode
 ## Viewing diffs in notmuch
 
 The following code allows you to view an inline patch in diff-mode
@@ -624,22 +772,105 @@ refine, next hunk etc all work.
       "View the the current message as a patch."
       (interactive)
       (let* ((id (notmuch-show-get-message-id))
       "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)))
              (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-kill-this-buffer)
+        (define-key map "q" 'notmuch-bury-or-kill-this-buffer)
         (switch-to-buffer buf)
         (let ((inhibit-read-only t))
           (erase-buffer)
           (insert subject)
         (switch-to-buffer buf)
         (let ((inhibit-read-only t))
           (erase-buffer)
           (insert subject)
-          (insert (notmuch-get-bodypart-internal id 1 nil)))
+          (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))))
 
         (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 into the keymap with something like
-
-    (define-key 'notmuch-show-mode-map "D" 'my-notmuch-show-view-as-patch)
+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 <the-project> -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` appropriately. 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}"))))
+
+## Never forget attachments
+
+Very often we forget to actually attach the file when we send an email
+that's supposed to have an attachment. Did this never happen to you?
+If not, then it will.
+
+There is a hook out there that checks the content of the email for
+keywords and warns you before the email is sent out if there's no
+attachment. This is currently work in progress, but you can already
+add the hook to your `~/.emacs.d/notmuch-config.el` file to test
+it. Details available (and feedback welcome) in the [relevant
+discussion](https://notmuchmail.org/pipermail/notmuch/2018/026414.html).
+
+## Applying patches to git repositories
+
+The `notmuch-extract-thread-patches` and
+`notmuch-extract-message-patches` commands from the `elpa-mailscripts`
+package in Debian (and its derivatives) can do this for you.