#+title: MU QUERY * NAME mu query language -- a language for finding messages in *mu* databases. * DESCRIPTION The mu query language is a language used by *mu find* and *mu4e* to find messages in *mu*'s Xapian databases. The language is quite similar to Xapian's default query-parser, but is an independent implementation that is customized for the mu/mu4e use-case. In this article, we give a structured but informal overview of the query language and provide examples. As a companion to this, we recommend the *mu fields* and *mu flags* commands to get an up-to-date list of the available fields and flags. *NOTE:* if you use queries on the command-line (say, for *mu find*), you need to quote any characters that would otherwise be interpreted by the shell, such as *""*, *(* and *)* and whitespace. * TERMS The basic building blocks of a query are *terms*; these are just normal words like 'banana' or 'hello', or words prefixed with a field-name which make them apply to just that field. See *mu find* for all the available fields. Some example queries: #+begin_example vacation subject:capybara maildir:/inbox #+end_example Terms without an explicit field-prefix, (like 'vacation' above) are interpreted like: #+begin_example to:vacation or subject:vacation or body:vacation or ... #+end_example The language is case-insensitive for terms and attempts to 'flatten' any diacritics, so =angtrom= matches =Ångström=. If terms contain whitespace, they need to be quoted: #+begin_example subject:"hi there" #+end_example This is a so-called =phrase query=, which means that we match against subjects that contain the literal phrase "hi there". Remember that you need to escape those quotes when using this from the command-line: #+begin_example mu find subject:\\"hi there\\" #+end_example * LOGICAL OPERATORS We can combine terms with logical operators -- binary ones: *and*, *or*, *xor* and the unary *not*, with the conventional rules for precedence and association, and are case-insensitive. You can also group things with *(* and *)*, so you can do things like: #+begin_example (subject:beethoven or subject:bach) and not body:elvis #+end_example If you do not explicitly specify an operator between terms, *and* is implied, so the queries #+begin_example subject:chip subject:dale #+end_example #+begin_example subject:chip AND subject:dale #+end_example are equivalent. For readability, we recommend the second version. Note that a =pure not= - e.g. searching for *not apples* is quite a 'heavy' query. * REGULAR EXPRESSIONS AND WILDCARDS The language supports matching regular expressions that follow ECMAScript; for details, see http://www.cplusplus.com/reference/regex/ECMAScript/ Regular expressions are enclosed in *//*. Some examples: #+begin_example subject:/h.llo/ # match hallo, hello, ... subject:/ #+end_example Note the difference between 'maildir:/foo' and 'maildir:/foo/'; the former matches messages in the '/foo' maildir, while the latter matches all messages in all maildirs that match 'foo', such as '/foo', '/bar/cuux/foo', '/fooishbar' etc. Wildcards are an older mechanism for matching where a term with a rightmost *** (and =only= in that position) matches any term that starts with the part before the ***; they are supported for backward compatibility and *mu* translates them to regular expressions internally: #+begin_example foo* #+end_example is equivalent to #+begin_example /foo.*/ #+end_example As a note of caution, certain wild-cards and regular expression can take quite a bit longer than 'normal' queries. * FIELDS We already saw a number of search fields, such as *subject:* and *body:*. For the full table, see *mu-fields(1)*. #+begin_example bcc,h Bcc (blind-carbon-copy) recipient(s) body,b Message body cc,c Cc (carbon-copy) recipient(s) changed,k Last change to message file (range) date,d Send date (range) embed,e Search inside embedded text parts file,j Attachment filename flag,g Message Flags from,f Message sender list,v Mailing list (e.g. the List-Id value) maildir,m Maildir mime,y MIME-type of one or more message parts msgid,i Message-ID prio,p Message priority (=low=, =normal= or =high=) size,z Message size range subject,s Message subject tag,x Tags for the message thread,w Thread a message belongs to to,t To: recipient(s) #+end_example The shortcut character can be used instead of the full name: #+begin_example f:foo@bar #+end_example is the same as #+begin_example from:foo@bar #+end_example For queries that are not one-off, we would recommend the longer name for readability. There are also the special fields *contact:*, which matches all contact-fields (=from=, =to=, =cc= and =bcc=), and *recip*, which matches all recipient-fields (=to=, =cc= and =bcc=). Hence, for instance, #+begin_example contact:fnorb@example.com #+end_example is equivalent to #+begin_example (from:fnorb@example.com or to:fnorb@example.com or cc:from:fnorb@example.com or bcc:fnorb@example.com) #+end_example * DATE RANGES The *date:* field takes a date-range, expressed as the lower and upper bound, separated by *..*. Either lower or upper (but not both) can be omitted to create an open range. Dates are expressed in local time and using ISO-8601 format (YYYY-MM-DD HH:MM:SS); you can leave out the right part, and *mu* adds the rest, depending on whether this is the beginning or end of the range (e.g., as a lower bound, '2015' would be interpreted as the start of that year; as an upper bound as the end of the year). You can use '/' , '.', '-' and 'T' to make dates more human readable. Some examples: #+begin_example date:20170505..20170602 date:2017-05-05..2017-06-02 date:..2017-10-01T12:00 date:2015-06-01.. date:2016..2016 #+end_example You can also use the special 'dates' *now* and *today*: #+begin_example date:20170505..now date:today.. #+end_example Finally, you can use relative 'ago' times which express some time before now and consist of a number followed by a unit, with units *s* for seconds, *M* for minutes, *h* for hours, *d* for days, *w* for week, *m* for months and *y* for years. Some examples: #+begin_example date:3m.. date:2017.01.01..5w #+end_example * SIZE RANGES The *size* or *z* field allows you to match =size ranges= -- that is, match messages that have a byte-size within a certain range. Units (b (for bytes), K (for 1000 bytes) and M (for 1000 * 1000 bytes) are supported). Some examples: #+begin_example size:10k..2m size:10m.. #+end_example * FLAG FIELD The *flag/g* field allows you to match message flags. The following fields are available: #+begin_example a,attach Message with attachment d,draft Draft Message f,flagged Flagged l,list Mailing-list message n,new New message (in new/ Maildir) p,passed Passed ('Handled') r,replied Replied s,seen Seen t,trashed Marked for deletion u,unread new OR NOT seen x,encrypted Encrypted message z,signed Signed message #+end_example Some examples: #+begin_example flag:attach flag:replied g:x #+end_example Encrypted messages may be signed as well, but this is only visible after decrypting and thus invisible to *mu*. * PRIORITY FIELD The message priority field (*prio:*) has three possible values: *low*, *normal* or *high*. For instance, to match high-priority messages: #+begin_example prio:high #+end_example * MAILDIR The Maildir field describes the directory path starting *after* the Maildir-base path, and before the =/cur/= or =/new/= part. So for example, if there's a message with the file name =~/Maildir/lists/running/cur/1234.213:2,=, you could find it (and all the other messages in the same maildir) with: #+begin_example maildir:/lists/running #+end_example Note the starting '/'. If you want to match mails in the 'root' maildir, you can do with a single '/': #+begin_example maildir:/ #+end_example If you have maildirs (or any fields) that include spaces, you need to quote them, ie. #+begin_example maildir:"/Sent Items" #+end_example Note that from the command-line, such queries must be quoted: #+begin_example mu find 'maildir:"/Sent Items"' #+end_example * MORE EXAMPLES Here are some simple examples of *mu* queries; you can make many more complicated queries using various logical operators, parentheses and so on, but in the author's experience, it's usually faster to find a message with a simple query just searching for some words. Find all messages with both 'bee' and 'bird' (in any field) #+begin_example bee AND bird #+end_example Find all messages with either Frodo or Sam: #+begin_example Frodo OR Sam #+end_example Find all messages with the 'wombat' as subject, and 'capybara' anywhere: #+begin_example subject:wombat and capybara #+end_example Find all messages in the 'Archive' folder from Fred: #+begin_example from:fred and maildir:/Archive #+end_example Find all unread messages with attachments: #+begin_example flag:attach and flag:unread #+end_example Find all messages with PDF-attachments: #+begin_example mime:application/pdf #+end_example Find all messages with attached images: #+begin_example mime:image/* #+end_example * CAVEATS With current Xapian versions, the apostroph character is considered part of a word. Thus, you cannot find =D'Artagnan= by searching for =Artagnan=. So, include the apostroph in search or use a regexp search. Matching on spaces has changed compared to the old query-parser; this applies e.g. to Maildirs that have spaces in their name, such as =Sent Items=. See *MAILDIR* above. #+include: "prefooter.inc" :minlevel 1 * SEE ALSO *mu-find(1)*, *mu-fields(1)*