Notmuch includes Python bindings to the Notmuch shared library. Please refer to
the nice and extensive [Notmuch Python API
-documentation](http://notmuch.readthedocs.org/projects/notmuch-python/).
+documentation](https://notmuchmail.org/doc/latest/python-bindings.html).
The bindings are very simple to use. As an example, given you have the Python
bindings installed (or simply set your PYTHONPATH environment variable to point
to the .../bindings/python directory), this snippet will produce a list of mails
matching the given expression:
- >>> import notmuch
- >>> db = notmuch.Database()
- >>> query = db.create_query('tag:inbox AND NOT tag:killed')
- >>> list(query.search_messages()) # doctest:+ELLIPSIS
+ >>> from notmuch2 import Database
+ >>> db = Database()
+ >>> messages = list(db.messages('tag:inbox AND NOT tag:killed'))
[...]
-[The source](https://git.notmuchmail.org/git/notmuch/tree/HEAD:/bindings/python/)
+[The source](https://git.notmuchmail.org/git/notmuch/tree/HEAD:/bindings/python-cffi/)
## Ruby
[[!img notmuch-logo.png alt="Notmuch logo" class="left"]]
# Notmuch Email Corpus
-A corpus of about 108k messages is available for performance testing of
+A corpus of about 209k messages is available for performance testing of
notmuch (or other uses).
The contents are as follows
- massaged with scripts/unpack-enron.sh (in the corpus tarball)
+- `Mail/lkml`: lkml messages 1000000 to 1100000 from the gmane archive
+
The corpus is gpg signed by David Bremner with key fingerprint:
- 815B 6398 2A79 F8E7 C727 86C4 762B 57BB 7842 06AD
+ 7A18 807F 100A 4570 C596 8420 7E4E 65C8 720B 706B
You can download the corpus from
-- [notmuchmail.org](https://notmuchmail.org/releases/notmuch-email-corpus-0.3.tar.xz) [signature](https://notmuchmail.org/releases/notmuch-email-corpus-0.3.tar.xz.asc)
-- [UNB](http://tesseract.cs.unb.ca/notmuch/notmuch-email-corpus-0.3.tar.xz) [signature](http://tesseract.cs.unb.ca/notmuch/notmuch-email-corpus-0.3.tar.xz.asc)
+- [notmuchmail.org](https://notmuchmail.org/releases/notmuch-email-corpus-0.5.tar.xz) [signature](https://notmuchmail.org/releases/notmuch-email-corpus-0.5.tar.xz.asc)
[[!toc levels=2]]
-## Issues with Emacs 24 (unsupported since notmuch 0.31 (2020-09-05))
-
-If notmuch-show-mode behaves badly for you in emacs 24.x try adding one of
-
- (setq gnus-inhibit-images nil)
-
-or
-
- (require 'gnus-art)
-
-to your .emacs file.
-
## Controlling external handlers for attachments
You can choose e.g. which pdf viewer to invoke from notmuch-show mode by
`notmuch-fcc-dirs` in the customization window for how to arrange
this.
+The `notmuch-fcc-dirs` variable is only taken into account when mails
+are composed using `notmuch-mua-mail`. If you want to use the notmuch
+mail user agent by default, the `mail-user-agent` needs to be
+customized to use the `notmuch-user-agent`.
+
## How to customize `notmuch-saved-searches`
When starting notmuch, a list of saved searches and message counts is
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
+removed for some mime-types to prevent immediate removal of temporary
files so the configured viewer can access them.
(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):
+And in header lines:
(defun notmuch-show-header-tabs-to-spaces ()
"Replace tabs with spaces in header line."
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).
+Since version 0.29 Notmuch includes the `notmuch-mua-attachment-check`
+function. This function checks whether a message references an
+attachment and if it finds none it asks for confirmation before
+sending the message. The function is meant to be added to the
+`message-send-hook`, like so:
+
+ (add-hook 'message-send-hook 'notmuch-mua-attachment-check)
+
+The "customize"able variable `notmuch-mua-attachment-regexp` controls
+how reference to an attachment are identified. By default, it
+identifies English and French terms. For example, the following makes
+it recognise English and Portuguese terms:
+
+ (setq-default notmuch-mua-attachment-regexp
+ "\\b\\(attach\\|attachment\\|attached\\|anexo\\|anexado\\)\\b")
+
+
+## Avoid forgetting the subject
+
+It happens that we forget to enter the Subject line, particularly when
+we leave that to the end. It's easy to write a function that checks
+whether the Subject is empty, and add it to `message-send-hook` to get
+confirmation:
+
+ (defun my-notmuch-mua-empty-subject-check ()
+ "Request confirmation before sending a message with empty subject"
+ (when (and (null (message-field-value "Subject"))
+ (not (y-or-n-p "Subject is empty, send anyway? ")))
+ (error "Sending message cancelled: empty subject.")))
+ (add-hook 'message-send-hook 'my-notmuch-mua-empty-subject-check)
+
## Applying patches to git repositories
This would discourage text/html and multipart/related generally, but discourage
text/plain should the message be sent from whatever@mail.address.com.
+
+## See the recipient address instead of your address when listing sent messages
+
+If you like to see your sent messages in unthreaded view, by default you will
+see your address in the authors column, which is maybe not what you want. The
+following code allows for showing the recipients if your email address (an
+arbitrary address, whatever@mail.address.com in the example) is included in the
+From field.
+
+ (defun my/notmuch-unthreaded-show-recipient-if-sent (format-string result)
+ (let* ((headers (plist-get result :headers))
+ (to (plist-get headers :To))
+ (author (plist-get headers :From))
+ (face (if (plist-get result :match)
+ 'notmuch-tree-match-author-face
+ 'notmuch-tree-no-match-author-face)))
+ (propertize
+ (format format-string
+ (if (string-match "whatever@mail.address.com" author)
+ (concat "↦ " (notmuch-tree-clean-address to))
+ (notmuch-tree-clean-address to)
+ author))
+ 'face face)))
+
+ (setq notmuch-unthreaded-result-format
+ '(("date" . "%12s ")
+ (my/notmuch-unthreaded-show-recipient-if-sent . "%-20.20s")
+ ((("subject" . "%s"))
+ . " %-54s ")
+ ("tags" . "(%s)")))
+
+## Issues with Emacs 24 (unsupported since notmuch 0.31 (2020-09-05))
+
+If notmuch-show-mode behaves badly for you in emacs 24.x try adding one of
+
+ (setq gnus-inhibit-images nil)
+
+or
+
+ (require 'gnus-art)
+
+to your .emacs file.
In a [hook](https://notmuchmail.org/doc/latest/man5/notmuch-hooks.html)
- notmuch tag +muted $(notmuch search --output=threads tag:muted)"
+ notmuch tag +muted $(notmuch search --output=threads tag:muted)
-New messages in the thread get the muted tag. Make muted an excluded tag.
-To kill a thread, tag it with muted, run notmuch new.
+New messages in the thread get the muted tag. Make muted an excluded tag (see
+above). To kill a thread, tag it with muted, run notmuch new.
* [noservice](https://gitlab.com/noservice/noservice). Web interface, written in Clojure.
* [notmuchfs](https://github.com/tsto/notmuchfs), a virtual maildir file system for Notmuch queries.
* [epistula](https://github.com/emdete/epistula), a terminal MUA based on gpgme and gmime written in go and with tcell (alpha status).
+* [notmuch-email-client](https://github.com/inbasic/notmuch-email-client/), an [extension](https://add0n.com/notmuch-email-client.html) for using notmuch in web browsers
## Historical
* ner, a curses frontend written in C++ ([github mirror](https://github.com/pioto/ner)).
* [mutt-kz](https://github.com/karelzak/mutt-kz), a fork of [mutt](http://www.mutt.org/) with Notmuch as a backend (actually linked against lib notmuch). Deprecated in favour of neomutt.
* [jaro-mail](http://www.dyne.org/software/jaro-mail). Command line client emphasizing privacy. ([github mirror](https://github.com/dyne/JaroMail))
-* [notmuch-web](https://bitbucket.org/wuzzeb/notmuch-web) A web front end written in [Haskell](http://hackage.haskell.org/package/notmuch-web). Not active upstream since 2014.
+* [notmuch-web](https://github.com/afcady/notmuch-web) A web front end written in [Haskell](http://hackage.haskell.org/package/notmuch-web). Not active upstream since 2014.
## Tools based on Notmuch
* [[Searching]]
* [[Excluding and deleting messages|excluding]]
* [[Initial tagging|Initial_Tagging]]
- * Tips for using Notmuch with [[Emacs|emacstips]], [[Vim|vimtips]], and [[Mutt|mutttips]]
+ * Tips for using Notmuch with [[Emacs|emacstips]], [[Vim|vimtips]], [[Postfix & Dovecot|postfixdovecottips]] and [[Mutt|mutttips]]
* [[Emacs remote usage|remoteusage]]
* [[Performance|performance]]
* [[References|references]]
│tag │ and │ term │ yes │ yes │ yes │
├───────────┼─────────┼────────┼────────┼──────────┼───────┤
│thread │ or │ term │ yes │ yes │ yes │
- └───────────┴─────────┴────────┴────────┴──────────┴───────┘
-
+ ├───────────┼─────────┼────────┼────────┼──────────┼───────┤
│to │ and │ phrase │ yes │ yes │ no │
└───────────┴─────────┴────────┴────────┴──────────┴───────┘
</pre>
<h2>NOTES</h2>
<pre>
- [1] Technically macros impliment lazy evaluation and lexical scope.
+ [1] Technically macros implement lazy evaluation and lexical scope.
There is one top level scope containing all macro definitions, but
all parameter definitions are local to a given macro.
[4] a.k.a. boolean prefixes
- [5] Due to the implemention of phrase fields in Xapian, regex queries
+ [5] Due to the implementation of phrase fields in Xapian, regex queries
could only match individual words.
[6] Due the the way <b>body</b> is implemented in notmuch, this modifier is
# Using Notmuch with neomutt
-*Note*: This discussion was updated by a non-mutt user from talking about mutt-kz to
+*Note*: This discussion was updated by a non-mutt user from talking about mutt-kz to
[neomutt](https://neomutt.org/). Caveat lector!
"Sent" "notmuch://?query=tag:sent" # sets up queries for virtual folders
# notmuch bindings
macro index \\\\ "<vfolder-from-query>" # looks up a hand made query
- macro index A "<modify-labels>+archive -unread -inbox\\n" # tag as Archived
- macro index I "<modify-labels>-inbox -unread\\n" # removed from inbox
- macro index S "<modify-labels-then-hide>-inbox -unread +junk\\n" # tag as Junk mail
- macro index + "<modify-labels>+*\\n<sync-mailbox>" # tag as starred
- macro index - "<modify-labels>-*\\n<sync-mailbox>" # tag as unstarred
+ macro index A "<modify-labels>+archive -unread -inbox<enter>" # tag as Archived
+ macro index I "<modify-labels>-inbox -unread<enter>" # removed from inbox
+ macro index S "<modify-labels-then-hide>-inbox -unread +junk<enter>" # tag as Junk mail
+ macro index + "<modify-labels>+*<enter><sync-mailbox>" # tag as starred
+ macro index - "<modify-labels>-*<enter><sync-mailbox>" # tag as unstarred
# sidebar
set sidebar_width = 20
set sidebar_visible = yes # set to "no" to disable sidebar view at startup
You may have noticed in `neomutts`'s configuration that I set the `sendmail` variable
of mutt to a `nm_sendmail` script. This is for tagging outgoing mail each time I send
-a mail. Here is the content of the script (which may be used directly in mutt's
-variable, I did not try).
+a mail. Here is the content of the script (which may be used directly in mutt's
+variable, I did not try).
Source of `nm_sendmail`:
#!/bin/bash
- tee >(notmuch-deliver -t sent -f Sent) | sendmail $*
+ tee >(notmuch insert --folder=Sent +sent) | sendmail $*
## Mail filtering/tagging
-For mail tagging on arrival, I prefer to use a simple procmail delivery along with
-notmuch-delivery (which can be compiled in the `contrib/` directory of notmuch's sources).
+For mail tagging on arrival, I prefer to use a simple procmail delivery along with
+`notmuch insert`.
Of course, you could use formail or maildrop, instead of procmail, but it is flexible
enough for my needs, and here is an example of configuration that can be useful:
:0 Wh
| /usr/local/bin/notmuch_abook update
- NOINBOX="-r inbox"
+ NOINBOX="-inbox"
TAGS=""
# manage dynamic tagging, using the ' + ' token in mail addresses
* ^TO\/user\+[a-z0-9]+@fqdn\.tld
* MATCH ?? ^user\+\/[a-z0-9]+
{
- TAGS="-t ${MATCH}"
+ TAGS="+${MATCH}"
}
# match all mails from mailing-lists, don't let them go to inbox, but tag them with ml
:0:notmuch.lock
* ^List-[Ii][dD]:.*
{
- TAGS="${TAGS} -t ml -r inbox"
+ TAGS="${TAGS} +ml -inbox"
}
# tag all mails coming from mutt-kz mailing list
:0:notmuch.lock
* .*mutt-kz\.lists\.fedoraproject\.org.*
- | notmuch-deliver $TAGS -t mutt -t notmuch
+ | notmuch insert $TAGS +mutt +notmuch
# tag all mails coming from notmuch mailing list
:0:notmuch.lock
* .*notmuch\.notmuchmail\.org.*
- | notmuch-deliver $TAGS -t notmuch
+ | notmuch insert $TAGS +notmuch
# Mark all spams as junk mail
:0:notmuch.lock
* ^X-Spam-Status: Yes
- | notmuch-deliver -t junk
+ | notmuch insert +junk
:0:notmuch.lock
* ^Subject: .*SPAM.*
- | notmuch-deliver -t junk
+ | notmuch insert +junk
### All unmatched mails
:0:notmuch.lock
* .*
- | notmuch-deliver -v $TAGS
+ | notmuch insert $TAGS
there's a line that updates the addressbook with addresses of current mail, and you'll
be able to read more about it on the [[vimtips]] page.
Build
-----
-Catch one more occurence of "version" in the build system, which
+Catch one more occurrence of "version" in the build system, which
caused the file to be regenerated in the release tarball.
CLI
---
-Improve handling of leading/trailing punctation and space for
+Improve handling of leading/trailing punctuation and space for
configuration lists.
Only ignore `.notmuch` at the top level in `notmuch new`.
Don't add space to completion candidates, improves compatibility with
third party completion frameworks.
-Make citation formating more robust against whitespace.
+Make citation formatting more robust against whitespace.
Use `--excludes=false` when generating the 'All tags' section.
Add the `sexp` prefix to the infix (traditional) query parser. This
allows specific subqueries to be parsed by the sexp parser (with
-appropropriate quoting). See `notmuch-search-terms(7)` for details.
+appropriate quoting). See `notmuch-search-terms(7)` for details.
Add another heuristic to regexp fields to prevent phrase parsing of
bracketed sub-expressions.
Documentation
-------------
-Reorganize documention for `notmuch-config`. Add a few links from
+Reorganize documentation for `notmuch-config`. Add a few links from
other man pages.
Emacs
--- /dev/null
+[[!meta date="2022-08-21"]]
+
+Notmuch 0.37 (2022-08-21)
+=========================
+
+Library
+-------
+
+Fix uninitialized field in message objects.
+
+Improve exception handling and error propagation for message objects.
+
+Sexp Queries
+------------
+
+Add one sided lastmod ranges for sexp queries.
+
+Expand macro parameters inside regex and wildcard modifiers.
+
+Command Line Interface
+----------------------
+
+`notmuch help` now works for external commands.
+
+`NOTMUCH_CONFIG` is now passed to external commands and hooks.
+
+Promote the development tool `nmbug` to a user facing tool
+`notmuch-git`. See notmuch-git(1) for details.
+
+Emacs
+-----
+
+The function `notmuch-mua-mail` now moves point depending on the
+provided arguments.
+
+Restrict what mime types are inlined in replies and on refresh.
+
+The functions in notmuch-query.el are now obsolete and may be removed
+in a future version of Notmuch.
+
+Add some controls for lazy display of message bodies (See "Dealing
+with large messages and threads" in the notmuch-emacs documentation).
+
+Allow the user to select (with '%') a different duplicate message file
+to display.
+
+Use `message-dont-reply-to-names` in `notmuch-message-mode`.
+
+Support custom header-line format for notmuch-show mode.
--- /dev/null
+[[!meta date="2023-10-26"]]
+
+Notmuch 0.38.1 (2023-10-26)
+===========================
+
+CLI
+---
+
+Report parse errors in config files.
+
+Emacs
+-----
+
+Fix image toggling for Emacs >= 29.1.
+
+notmuch-mutt
+------------
+
+Fix syntax error in script.
--- /dev/null
+[[!meta date="2023-12-01"]]
+
+Notmuch 0.38.2 (2023-12-01)
+===========================
+
+Library
+-------
+
+Make sorting of string maps lexicographic on (key,value) pairs. This
+avoids some test failures due to variation in message property output
+order.
+
+Emacs
+-----
+
+Avoid extra separators after the last address in `notmuch-emacs-mua`.
--- /dev/null
+[[!meta date="2024-03-09"]]
+
+Notmuch 0.38.3 (2024-03-09)
+===========================
+
+CLI
+---
+
+Fix a bug in configuration code that caused the notmuch command to
+erroneously report "Error: could not locate database" under some
+circumstances.
--- /dev/null
+[[!meta date="2023-09-12"]]
+
+Notmuch 0.38 (2023-09-12)
+=========================
+
+General
+-------
+
+Support relative lastmod queries (see notmuch-sexp-queries(7) and
+notmuch-search-terms(7) for details).
+
+Support indexing of designated attachments as text (see
+notmuch-config(1) for details).
+
+CLI
+---
+
+Add options --offset and --limit to notmuch-show(1).
+
+Emacs
+-----
+
+New commands notmuch-search-edit-search and notmuch-tree-edit-search.
+
+Introduce notmuch-tree-outline-mode.
+
+Some compatibility fixes for Emacs 29. At least one issue (hiding
+images) remains in 0.38.
+
+Support completion when piping to external command.
+
+Fix regression in updating tag display introduced by 0.37.
+
+Library
+-------
+
+Fix bug creating database when database.path is not set.
+
+Incremental performance improvements for message deletion.
+
+Catch Xapian exceptions when deleting messages.
+
+Sync removed message properties to the database.
+
+Replace use of thread-unsafe Query::MatchAll in the infix query
+parser.
+
+Notmuch-Mutt
+------------
+
+Be more careful when clearing the results directory.
+
+Ruby
+----
+
+Use `database_open_with_config`, and provide compatible path search
+semantics.
+
+### Bugfix for query.get_sort
+
+Test Suite
+----------
+
+Support testing installed version of notmuch.
+
+Adapt to some breaking changes in glib handling of init files.
+
+Replace OpenPGP key used in test suite.
+
+Performance Tests
+-----------------
+
+Update signatures for performance test corpus.
<span class="hl kwa">print</span> <span class="hl str">'Generated: %s<br>'</span> <span class="hl opt">%</span> datetime<span class="hl opt">.</span>date<span class="hl opt">.</span><span class="hl kwd">today</span><span class="hl opt">()</span>
-<span class="hl kwa">print</span> <span class="hl str">'For more infomation see <a href="https://notmuchmail.org/nmbug">nmbug</a>'</span>
+<span class="hl kwa">print</span> <span class="hl str">'For more information see <a href="https://notmuchmail.org/nmbug">nmbug</a>'</span>
<span class="hl kwa">print</span> <span class="hl str">'<h3>Query</h3>'</span>
<span class="hl kwa">print</span> QUERY
One of the more popular Notmuch message reading clients is **notmuch.el**, or
`notmuch-mode`, an [Emacs](https://www.gnu.org/software/emacs/) major mode for
-interacting with Notmuch. It is included in the Notmuch package (`elpa-notmuch`
-in current Debian or `notmuch-emacs` in Debian 10 or prior). The
-[[screenshots|screenshots]] give a good overview of the mode.
+interacting with Notmuch. It is included in the Notmuch package (as
+`elpa-notmuch` within the `notmuch` package in current Debian or as
+`notmuch-emacs` in Debian 10 or prior). The [[screenshots|screenshots]] give a
+good overview of the mode.
This page is a basic guide for setting up and using Notmuch with Emacs. See also
the [[tips and tricks page|emacstips]] for more advanced details.
--- /dev/null
+Here are the results of "make time test" on a "12th Gen Intel(R)
+Core(TM) i7-12700" with NVME SSD. The file system is ext4. System was
+not completely idle, but no heavy computation or I/O was run at the
+same time.
+
+Notmuch is 0.37+71~ge9ff896f
+
+<pre>
+T00-new.sh: Testing notmuch new [0.5 large]
+Unpacking corpus
+....................................................................
+ Wall(s) Usr(s) Sys(s) Res(K) In/Out(512B)
+ Initial notmuch new 284.55 262.62 16.73 324816 1963992/18146064
+ notmuch new #2 0.01 0.00 0.00 10160 264/160
+ notmuch new #3 0.01 0.01 0.00 10116 0/8
+ notmuch new #4 0.01 0.00 0.01 10112 0/8
+ notmuch new #5 0.01 0.00 0.00 10192 0/8
+ notmuch new #6 0.00 0.00 0.00 10152 0/8
+ new (52374 mv) 232.60 161.81 66.64 240324 273704/6079784
+ new (52374 mv back) 227.73 160.67 66.35 241312 0/5974504
+ new (52374 rm) 79.60 57.73 20.90 398168 10432/8966656
+ new (52374 restore) 90.41 80.86 8.69 377412 0/8567616
+ new (52374 cp) 140.60 99.95 40.22 210936 0/4687776
+
+T01-dump-restore.sh: Testing dump and restore [0.5 large]
+ Wall(s) Usr(s) Sys(s) Res(K) In/Out(512B)
+ load nmbug tags 2.23 1.25 0.94 13296 600/66424
+ dump * 2.71 2.63 0.07 26548 0/27928
+ restore * 2.99 2.77 0.21 10112 0/0
+
+T02-tag.sh: Testing tagging [0.5 large]
+ Wall(s) Usr(s) Sys(s) Res(K) In/Out(512B)
+ tag * +new_tag 159.78 95.57 63.52 111608 16/1522752
+ tag * +existing_tag 0.00 0.00 0.00 9852 0/0
+ tag * -existing_tag 117.39 66.38 50.72 36636 0/1416928
+ tag * -missing_tag 0.00 0.00 0.00 9812 0/0
+
+T03-reindex.sh: Testing reindexing [0.5 large]
+ Wall(s) Usr(s) Sys(s) Res(K) In/Out(512B)
+ reindex * 322.18 298.32 10.56 481964 2394952/13304936
+ reindex * 302.69 293.20 9.27 480724 160/12683736
+ reindex * 309.10 299.98 8.87 480772 0/12762280
+ reindex (52374 mv) 272.50 262.54 9.16 453880 137016/12690920
+ reindex (52374 mv back)225.50 218.26 6.92 447908 40/10640696
+ reindex (52374 rm) 224.23 216.86 7.04 447952 0/10888088
+ reindex (52374 restore)222.33 215.35 6.71 447500 0/10797176
+ reindex (52374 cp) 222.81 215.56 7.02 449040 72/10732264
+
+T04-thread-subquery.sh: Testing thread subqueries [0.5 large]
+ Wall(s) Usr(s) Sys(s) Res(K) In/Out(512B)
+ search thread:{} ... 1.50 1.38 0.12 27332 0/144
+ search thread:{} ... 1.53 1.44 0.08 28860 0/144
+ search thread:{} ... 1.52 1.41 0.11 28412 0/144
+
+T05-ruby.sh: Testing ruby bindings [0.5 large]
+ Wall(s) Usr(s) Sys(s) Res(K) In/Out(512B)
+ print all messages 324.65 302.12 22.45 94748 8952/1912640
+
+T06-emacs.sh: Testing emacs operations [0.5 large]
+ Wall(s) Usr(s) Sys(s) Res(K) In/Out(512B)
+ Wall(s) GCs GC time(s)
+tag messages 2.05 0.60 0.01
+show warmup 1.96 12.40 0.25
+show thread #1 2.02 3.60 0.20
+depth bound #1 0.33 0.60 0.06
+height bound #1 0.34 0.40 0.04
+size bound #1 0.40 0.40 0.05
+show thread #2 0.87 0.80 0.09
+depth bound #2 0.37 0.40 0.05
+height bound #2 0.34 0.40 0.06
+size bound #2 0.31 0.40 0.05
+show thread #3 1.22 0.60 0.09
+depth bound #3 0.51 0.20 0.03
+height bound #3 0.49 0.20 0.03
+size bound #3 0.48 0.00 0.00
+show thread #4 9.69 1.80 0.35
+depth bound #4 0.76 0.20 0.05
+height bound #4 0.73 0.20 0.05
+size bound #4 0.95 0.40 0.11
+
+T07-git.sh: Testing notmuch-git [0.5 large]
+ Wall(s) Usr(s) Sys(s) Res(K) In/Out(512B)
+ init 0.05 0.04 0.00 16156 6624/264
+ commit --force 14.70 16.23 3.31 247192 2800/854568
+ commit 2.47 0.83 1.61 135040 0/8
+ commit 2.44 0.94 1.47 135100 0/8
+ checkout 2.49 0.91 1.54 134960 0/8
+ tag -inbox 159.53 95.26 63.85 110976 0/1545296
+ checkout --force 168.29 102.16 71.01 211480 0/5527376
+</pre>
+
--- /dev/null
+Here are the results of "make time test" on a "12th Gen Intel(R)
+Core(TM) i7-12700" with NVME SSD. The file system is ext4. System was
+not completely idle, but no heavy computation or I/O was run at the
+same time.
+
+Notmuch is 0.37+78~gb6f144ab
+
+<pre>
+
+T00-new.sh: Testing notmuch new [0.5 large]
+ Wall(s) Usr(s) Sys(s) Res(K) In/Out(512B)
+ Initial notmuch new 313.59 271.42 18.66 324600 7361464/19092656
+ notmuch new #2 0.01 0.00 0.00 9600 0/160
+ notmuch new #3 0.00 0.00 0.00 9920 0/8
+ notmuch new #4 0.00 0.00 0.00 9920 0/8
+ notmuch new #5 0.01 0.01 0.00 9760 0/8
+ notmuch new #6 0.01 0.00 0.00 9920 0/8
+ new (52374 mv) 227.44 160.81 65.97 240028 0/5864136
+ new (52374 mv back) 215.89 151.02 64.13 240776 0/6048104
+ new (52374 rm) 42.35 34.67 6.79 396680 0/8304096
+ new (52374 restore) 90.49 81.30 8.14 377472 0/8499120
+ new (52374 cp) 135.97 96.72 38.73 210384 0/4704208
+
+T01-dump-restore.sh: Testing dump and restore [0.5 large]
+ Wall(s) Usr(s) Sys(s) Res(K) In/Out(512B)
+ load nmbug tags 2.68 1.25 1.06 12780 600/32344
+ dump * 2.74 2.62 0.12 26528 0/27928
+ restore * 2.99 2.75 0.23 9628 0/0
+
+T02-tag.sh: Testing tagging [0.5 large]
+ Wall(s) Usr(s) Sys(s) Res(K) In/Out(512B)
+ tag * +new_tag 158.89 95.36 62.71 111184 0/1530176
+ tag * +existing_tag 0.00 0.00 0.00 9440 0/0
+ tag * -existing_tag 117.41 66.16 50.94 37016 0/1456544
+ tag * -missing_tag 0.00 0.00 0.00 9760 0/0
+
+T03-reindex.sh: Testing reindexing [0.5 large]
+ Wall(s) Usr(s) Sys(s) Res(K) In/Out(512B)
+ reindex * 303.88 294.12 9.23 481720 0/12625544
+ reindex * 300.98 291.86 8.84 480964 0/12393528
+ reindex * 300.93 292.11 8.43 480724 0/12655848
+ reindex (52374 mv) 265.73 256.50 8.97 453768 0/12677400
+ reindex (52374 mv back)224.48 217.32 6.73 447548 0/10269912
+ reindex (52374 rm) 225.40 218.02 7.13 448436 0/10632312
+ reindex (52374 restore)226.12 218.84 6.98 448832 8/10340920
+ reindex (52374 cp) 224.17 217.22 6.68 447324 0/10259528
+T04-thread-subquery.sh: Testing thread subqueries [0.5 large]
+ Wall(s) Usr(s) Sys(s) Res(K) In/Out(512B)
+ search thread:{} ... 1.50 1.43 0.06 28260 0/144
+ search thread:{} ... 1.51 1.43 0.08 29008 0/144
+ search thread:{} ... 1.49 1.40 0.08 28840 0/144
+
+T05-ruby.sh: Testing ruby bindings [0.5 large]
+ Wall(s) Usr(s) Sys(s) Res(K) In/Out(512B)
+ print all messages 324.61 302.98 21.43 93476 40/1912640
+
+T06-emacs.sh: Testing emacs operations [0.5 large]
+ Wall(s) Usr(s) Sys(s) Res(K) In/Out(512B)
+ Wall(s) GCs GC time(s)
+tag messages 1.54 0.60 0.01
+show warmup 1.92 12.40 0.23
+show thread #1 2.04 3.60 0.22
+depth bound #1 0.34 0.40 0.04
+height bound #1 0.36 0.60 0.06
+size bound #1 0.34 0.40 0.05
+show thread #2 0.88 0.80 0.09
+depth bound #2 0.37 0.40 0.06
+height bound #2 0.43 0.40 0.07
+size bound #2 0.31 0.20 0.03
+show thread #3 1.33 0.80 0.12
+depth bound #3 0.50 0.20 0.03
+height bound #3 0.48 0.00 0.00
+size bound #3 0.52 0.20 0.04
+show thread #4 9.65 1.60 0.31
+depth bound #4 0.89 0.40 0.10
+height bound #4 0.75 0.20 0.05
+size bound #4 0.76 0.40 0.11
+
+T07-git.sh: Testing notmuch-git [0.5 large]
+ Wall(s) Usr(s) Sys(s) Res(K) In/Out(512B)
+ init 0.05 0.04 0.00 16000 0/264
+ commit --force 14.94 16.44 3.25 248356 40/854568
+ commit 2.72 0.89 1.81 135160 0/8
+ commit 2.62 1.07 1.54 135164 0/8
+ checkout 2.65 0.90 1.75 135160 0/8
+ tag -inbox 159.01 95.46 63.12 110324 0/1537824
+ checkout --force 169.48 103.43 71.10 210860 0/5498304
+</pre>
+
--- /dev/null
+Here are the results of "make time-test" on a
+"13th Gen Intel(R) Core(TM) i7-1365U". File system is btrfs on lvm on luks.
+
+notmuch is 0.38.1-15-gbddeb201
+
+<pre>
+T00-new.sh: Testing notmuch new [0.5 large]
+Unpacking manifests
+Unpacking corpus
+....................................................................
+creating link farm
+ Wall(s) Usr(s) Sys(s) Res(K) In/Out(512B)
+ Initial notmuch new 313.22 289.82 20.82 325828 152/26600144
+ notmuch new #2 0.03 0.01 0.02 10272 0/8
+ notmuch new #3 0.03 0.00 0.03 10400 0/8
+ notmuch new #4 0.03 0.01 0.02 10396 0/8
+ notmuch new #5 0.03 0.00 0.03 10472 0/8
+ notmuch new #6 0.03 0.00 0.03 10436 0/8
+ new (52374 mv) 271.65 185.97 82.58 237540 0/18738520
+ new (52374 mv back) 274.10 185.69 84.51 238084 0/18789240
+ new (52374 rm) 52.22 40.45 8.39 394820 0/12076624
+ new (52374 restore) 117.57 98.02 11.64 387288 0/21043744
+ new (52374 cp) 167.01 112.94 48.69 214280 0/16791664
+
+T01-dump-restore.sh: Testing dump and restore [0.5 large]
+ Wall(s) Usr(s) Sys(s) Res(K) In/Out(512B)
+ load nmbug tags 5.82 1.80 1.86 13056 492584/65400
+ dump * 3.16 2.60 0.28 26792 1230896/27928
+ restore * 3.30 2.70 0.22 9916 123872/0
+
+T02-tag.sh: Testing tagging [0.5 large]
+ Wall(s) Usr(s) Sys(s) Res(K) In/Out(512B)
+ tag * +new_tag 187.51 96.93 77.36 111648 3961184/1866656
+ tag * +existing_tag 0.00 0.00 0.00 9728 0/0
+ tag * -existing_tag 126.16 65.23 60.76 37364 16/1513200
+ tag * -missing_tag 0.00 0.00 0.00 9728 0/0
+
+T03-reindex.sh: Testing reindexing [0.5 large]
+ Wall(s) Usr(s) Sys(s) Res(K) In/Out(512B)
+ reindex * 368.40 338.14 18.48 482844 3984864/34952728
+ reindex * 360.48 337.81 15.32 481516 264/34669112
+ reindex * 355.73 335.88 13.62 481512 768/34677832
+ reindex (52374 mv) 322.80 293.33 16.89 453880 0/37045544
+ reindex (52374 mv back)265.99 247.46 11.24 453380 0/27842152
+ reindex (52374 rm) 273.08 249.49 12.85 451644 0/27825720
+ reindex (52374 restore)265.34 246.61 11.60 452508 0/27851624
+ reindex (52374 cp) 274.16 249.05 12.75 453352 0/27823592
+
+T04-thread-subquery.sh: Testing thread subqueries [0.5 large]
+ Wall(s) Usr(s) Sys(s) Res(K) In/Out(512B)
+ search thread:{} ... 1.89 1.41 0.20 28316 832896/144
+ search thread:{} ... 1.49 1.43 0.05 28268 0/144
+ search thread:{} ... 1.48 1.38 0.10 27516 0/144
+
+T05-ruby.sh: Testing ruby bindings [0.5 large]
+ Wall(s) Usr(s) Sys(s) Res(K) In/Out(512B)
+ print all messages 349.10 320.61 24.01 100808 1299568/1912632
+
+T06-emacs.sh: Testing emacs operations [0.5 large]
+ Wall(s) Usr(s) Sys(s) Res(K) In/Out(512B)
+ Wall(s) GCs GC time(s)
+tag messages 1.60 0.40 0.00
+show warmup 0.75 13.00 0.22
+show thread #1 0.76 3.60 0.18
+depth bound #1 0.16 0.40 0.03
+height bound #1 0.18 0.60 0.05
+size bound #1 0.16 0.40 0.03
+show thread #2 0.46 1.00 0.09
+depth bound #2 0.16 0.40 0.04
+height bound #2 0.14 0.20 0.02
+size bound #2 0.17 0.40 0.05
+show thread #3 0.63 0.80 0.11
+depth bound #3 0.25 0.20 0.03
+height bound #3 0.25 0.20 0.03
+size bound #3 0.24 0.20 0.03
+show thread #4 2.01 1.80 0.32
+depth bound #4 0.27 0.20 0.04
+height bound #4 0.32 0.40 0.09
+size bound #4 0.28 0.20 0.05
+rm: cannot remove '/srv/exp/bremner/notmuch/performance-test/tmp.T06-emacs': Directory not empty
+
+T07-git.sh: Testing notmuch-git [0.5 large]
+ Wall(s) Usr(s) Sys(s) Res(K) In/Out(512B)
+ init 0.05 0.03 0.01 16000 592/304
+ commit --force 15.00 18.75 4.31 248000 1294176/907736
+ commit 2.79 0.87 1.92 135124 0/72
+ commit 2.75 0.86 1.89 135124 0/8
+ checkout 2.78 0.98 1.79 135124 0/8
+ tag -inbox 184.78 95.21 77.40 110456 2665376/1843104
+ checkout --force 178.42 100.71 81.53 211144 68064/8690016
+</pre>
--- /dev/null
+Here are the results of "make time-test" on a
+"13th Gen Intel(R) Core(TM) i7-1365U". File system is ext4 on lvm on luks.
+
+notmuch is 0.38.1-15-gbddeb201
+
+<pre>
+T00-new.sh: Testing notmuch new [0.5 large]
+ Wall(s) Usr(s) Sys(s) Res(K) In/Out(512B)
+ Initial notmuch new 359.70 294.83 20.58 325524 7127120/18533216
+ notmuch new #2 0.01 0.00 0.00 9984 0/160
+ notmuch new #3 0.00 0.00 0.00 10112 0/8
+ notmuch new #4 0.00 0.00 0.00 10112 0/8
+ notmuch new #5 0.00 0.00 0.00 10112 0/8
+ notmuch new #6 0.00 0.00 0.00 10112 0/8
+ new (52374 mv) 248.98 173.85 74.49 237060 304/6114280
+ new (52374 mv back) 250.19 174.82 74.79 238340 0/6045736
+ new (52374 rm) 45.87 37.05 7.75 388864 24/8765296
+ new (52374 restore) 99.77 89.63 9.24 381204 0/8388352
+ new (52374 cp) 150.42 106.02 43.98 211744 8/4667440
+
+T01-dump-restore.sh: Testing dump and restore [0.5 large]
+ Wall(s) Usr(s) Sys(s) Res(K) In/Out(512B)
+ load nmbug tags 2.76 1.14 1.42 13056 760/32248
+ dump * 2.67 2.55 0.12 26740 0/27928
+ restore * 2.89 2.68 0.21 10152 0/0
+
+T02-tag.sh: Testing tagging [0.5 large]
+ Wall(s) Usr(s) Sys(s) Res(K) In/Out(512B)
+ tag * +new_tag 168.91 95.08 73.30 111276 136/1576400
+ tag * +existing_tag 0.01 0.00 0.00 9856 0/0
+ tag * -existing_tag 124.70 65.10 59.32 37228 0/1601200
+ tag * -missing_tag 0.00 0.00 0.00 9856 0/0
+
+T03-reindex.sh: Testing reindexing [0.5 large]
+ Wall(s) Usr(s) Sys(s) Res(K) In/Out(512B)
+ reindex * 338.91 328.44 10.22 482332 8/13564952
+ reindex * 335.58 325.85 9.42 481152 0/13905656
+ reindex * 333.80 324.58 9.04 481276 0/13917480
+ reindex (52374 mv) 295.09 285.04 9.85 454384 32/13139592
+ reindex (52374 mv back)249.74 242.16 7.24 452172 0/11474632
+ reindex (52374 rm) 244.04 236.23 7.40 452884 0/10569496
+ reindex (52374 restore)247.86 240.15 7.53 451748 0/11424312
+ reindex (52374 cp) 253.09 244.48 8.04 452644 0/11601752
+
+T04-thread-subquery.sh: Testing thread subqueries [0.5 large]
+ Wall(s) Usr(s) Sys(s) Res(K) In/Out(512B)
+ search thread:{} ... 1.52 1.44 0.07 27676 8/144
+ search thread:{} ... 1.52 1.44 0.08 27204 0/144
+ search thread:{} ... 1.52 1.44 0.08 27528 0/144
+
+T05-ruby.sh: Testing ruby bindings [0.5 large]
+ Wall(s) Usr(s) Sys(s) Res(K) In/Out(512B)
+ print all messages 346.17 321.86 24.19 101072 1552/1912632
+
+T06-emacs.sh: Testing emacs operations [0.5 large]
+ Wall(s) Usr(s) Sys(s) Res(K) In/Out(512B)
+ Wall(s) GCs GC time(s)
+tag messages 2.10 0.40 0.01
+show warmup 0.75 13.00 0.22
+show thread #1 0.78 3.60 0.19
+depth bound #1 0.16 0.40 0.03
+height bound #1 0.18 0.60 0.05
+size bound #1 0.17 0.40 0.03
+show thread #2 0.46 1.00 0.10
+depth bound #2 0.16 0.40 0.04
+height bound #2 0.14 0.20 0.02
+size bound #2 0.17 0.40 0.05
+show thread #3 0.64 0.80 0.10
+depth bound #3 0.28 0.20 0.03
+height bound #3 0.27 0.20 0.03
+size bound #3 0.27 0.20 0.03
+show thread #4 2.01 1.80 0.33
+depth bound #4 0.27 0.20 0.04
+height bound #4 0.32 0.40 0.09
+size bound #4 0.28 0.20 0.05
+rm: cannot remove '/home/bremner/software/upstream/notmuch/performance-test/tmp.T06-emacs': Directory not empty
+
+T07-git.sh: Testing notmuch-git [0.5 large]
+ Wall(s) Usr(s) Sys(s) Res(K) In/Out(512B)
+ init 0.07 0.04 0.00 15872 4624/272
+ commit --force 14.21 18.34 3.50 248152 400/854584
+ commit 2.83 0.95 1.87 135128 0/8
+ commit 2.77 1.05 1.71 134996 0/8
+ checkout 2.76 0.95 1.80 135124 0/8
+ tag -inbox 176.95 100.30 76.17 110568 0/1560400
+ checkout --force 194.89 112.79 88.50 211364 8/5653888
+</pre>
--- /dev/null
+[[!img notmuch-logo.png alt="Notmuch logo" class="left"]]
+# Results from running the performance test suite
+
+[[!inline sort="age" reverse="no" show=0 archive="yes"
+ pages="perf-test-results/*"]]
+
* [Sebastian Spaeth](https://notmuchmail.org/pipermail/notmuch/2011/004048.html)
* [Pieter Praet](https://notmuchmail.org/pipermail/notmuch/2011/004175.html)
+
+## Performance test suite
+
+Notmuch ships with a [[performance test suite|perf-test]] which uses a downloadable
+[[corpus]] of email.
+
--- /dev/null
+[[!img notmuch-logo.png alt="Notmuch logo" class="left"]]
+
+Postfix can be used for delivering mail and Dovecot for making your maildir
+available using IMAP.
+
+Dovecot Pigeonhole Sieve can be used for filtering incoming mail and index it
+using notmuch.
+
+[[!toc levels=2]]
+
+# Configuration
+
+## Configure Postfix to use Dovecot Sieve
+
+Set `mailbox_command` to dovecot deliver:
+
+ postconf -e 'mailbox_command=/usr/libexec/dovecot/deliver -f "$SENDER" -a "$RECIPIENT"'
+
+## Configure Dovecot Sieve to allow running notmuch
+
+* Add `mail_plugins = sieve` to `/etc/dovecot/conf.d/15-lda.conf` to enable Sieve
+* Add `sieve_plugins = sieve_extprograms` to `/etc/dovecot/conf.d/90-sieve.conf` to allow running external programs
+* Add `sieve_extensions = +vnd.dovecot.pipe` to `/etc/dovecot/conf.d/90-sieve.conf` to allow pipe to external programs
+* Add `sieve_pipe_bin_dir = /usr/libexec/dovecot/sieve-pipe` to `/etc/dovecot/conf.d/90-sieve-extprograms.conf` to configure directory with allowed programs
+* Add `mail_location = maildir:~/Maildir` to `/etc/dovecot/conf.d/10-mail.conf` to use Maildir
+* Run `mkdir /usr/libexec/dovecot/sieve-pipe` to create the directory with allowed programs
+* Run `ln -s /usr/bin/notmuch /usr/libexec/dovecot/sieve-pipe/notmuch` to add a link to notmuch to the directory with allowed programs
+
+## Example Sieve configuration
+
+Create `~/.dovecot.sieve` with the following contents:
+
+ require ["fileinto", "vnd.dovecot.pipe"];
+ if header :contains "X-Spam-Flag" "YES" {
+ pipe "notmuch" [ "insert", "--folder=.spam", "--create-folder", "+spam" ];
+ } elsif anyof (header :matches "From" "notmuch@notmuchmail.org") {
+ pipe "notmuch" [ "insert", "--folder=.mailinglist", "--create-folder", "+mailinglist" ];
+ } else {
+ pipe "notmuch" [ "insert", "+notmuch-insert", "+inbox" ];
+ }
+
+# Notes
+
+## Postfix file size limit
+
+Postfix sets a `file size` ulimit before executing the `mailbox_command`. This
+also affects the notmuch index. Make sure `mailbox_size_limit` is at least the
+size of your largest notmuch index files.