#+TITLE: MU CFIND
#+MAN_CLASS_OPTIONS: :section-id "@SECTION_ID@" :date "@MAN_DATE@"
#+include: macros.inc

* NAME

mu-cfind - find contacts in the *mu* database and export them for use in other
programs.

* SYNOPSIS

*mu* [​_COMMON-OPTIONS_​] *cfind* [​_OPTIONS_​] [​_PATTERN_​]

* DESCRIPTION

*mu cfind* is the *mu* command for finding =contacts= (name and e-mail address of
people who were either an e-mail's sender or receiver). Different output formats
are available, e.g., for importing the contacts into other programs.

* SEARCHING CONTACTS

When you index your messages (see *mu index*), *mu* creates a list of unique e-mail
addresses found and the accompanying name, and caches this list. If the same
e-mail address is used with different names, the most recent non-empty name is
used. If that is not the desired name, see *CORRECTING* below.

*mu cfind* starts a search for contacts that match a =regular expression=. For
example:

#+begin_example
$ mu cfind '@gmail\.com'
#+end_example

finds all contacts with a gmail-address, while

#+begin_example
$ mu cfind Mary
#+end_example

lists all contacts with Mary in either name or e-mail address.

If you do not specify a search expression, *mu cfind* returns the full list of
contacts. *mu cfind* uses a cache with the e-mail information, which is populated
during the indexing process.

The regular expressions are basic case-insensitive PCRE, see {{{man-link(pcre,3)}}}.

* CFIND OPTIONS

** --format plain|mutt-alias|mutt-ab|wl|org-contact|bbdb|csv
Sets the output format to the given value. The following are available:

#+ATTR_MAN: :disable-caption t
| --format=   | description                       |
|-------------+-----------------------------------|
| plain       | default, simple list              |
| mutt-alias  | mutt alias-format                 |
| mutt-ab     | mutt external address book format |
| wl          | wanderlust address book format    |
| org-contact | org-mode org-contact format       |
| bbdb        | BBDB format                       |
| csv         | comma-separated values [1]        |
| json        | JSON format                       |


[1] *CSV* is not fully standardized, but *mu cfind* follows some common practices:
any double-quote is replaced by a double-double quote (thus, "hello" become
""hello"", and fields with commas are put in double-quotes. Normally, this
should only apply to name fields.

** -p, --personal
Only show addresses seen in messages where at least one of personal e-mail
addresses was seen in any of the address fields; this is to exclude addresses
only seen in mailing-list messages. See the *--personal-address* parameter to *mu
init* for specifying your personal e-mail addresses.

** --after _timestamp_
Only show addresses last seen after _timestamp_. _timestamp_ is a UNIX
*time_t* value, the number of seconds since 1970-01-01 (in UTC).

From the command line, you can use the *date* command to get this value. For
example, only consider addresses last seen after 2020-06-01, you could specify
#+begin_example
  --after=$(date +%s --date='2020-06-01')
#+end_example

#+include: "muhome.inc" :minlevel 2

#+include: "common-options.inc" :minlevel 1

* JSON FORMAT

With *--format=json*, the matching contacts come out as a JSON array, e.g.,
#+begin_example
[
  {
    "email"         : "syb@example.com",
    "name"          : "Sybil Gerard",
    "display"       : "Sybil Gerard <syb@example.com>",
    "last-seen"     : 1075982687,
    "last-seen-iso" : "2004-02-05T14:04:47Z",
    "personal"      : false,
    "frequency"     : 14
  },
  {
    "email"         : "ed@example.com",
    "name"          : "Mallory, Edward",
    "display"       : "\"Mallory, Edward\" <ed@example.com>",
    "last-seen"     : 1425991805,
    "last-seen-iso" : "2015-03-10T14:50:05Z",
    "personal"      : true,
    "frequency"     : 2
  }
]
#+end_example

Each contact has the following fields:

#+ATTR_MAN: :disable-caption t
| property      | description                                                              |
|---------------+--------------------------------------------------------------------------|
| ~email~         | the email-address                                                        |
| ~name~          | the name (or ~none~)                                                       |
| ~display~       | the combination name and e-mail address for display purposes             |
| ~last-seen~     | date of most recent message with this contact (Unix time)                |
| ~last-seen-iso~ | ~last-seen~ represented as an ISO-8601 timestamp                           |
| ~personal~      | whether the email was seen in a message together with a personal address |
| ~frequency~     | approximation of the number of times this contact was seen in messages   |

The JSON format is useful for further processing, e.g. using the {{{man-link(jq,1)}}} tool:

List display names, sorted by their last-seen date:
#+begin_example
$ mu cfind --format=json --personal | jq -r '.[] | ."last-seen-iso" + " " + .display' | sort
#+end_example

* INTEGRATION WITH MUTT

You can use *mu cfind* as an external address book server for *mutt*.
For this to work, add the following to your _muttrc_:

#+begin_example
set query_command = "mu cfind --format=mutt-ab '%s'"
#+end_example

Now, in mutt, you can search for e-mail addresses using the *query*-command, which
is (by default) accessible by pressing *Q*.

* ENCODING

*mu cfind* output is encoded according to the current locale except for
*--format=bbdb*. This is hard-coded to UTF-8, and as such specified in the
output-file, so emacs/bbdb can handle things correctly, without guessing.


* CORRECTING

If you want to correct the name for a given contact, one trick is to manual
create an e-mail message with some future date that has all the correct name /
e-mail address combinations, and put this in the Maildir you use.


#+include: "exit-code.inc" :minlevel 1

#+include: "bugs.inc" :minlevel 1

#+include: "author.inc" :minlevel 1

#+include: "copyright.inc" :minlevel 1

* SEE ALSO

{{{man-link(mu,1)}}},
{{{man-link(mu-index,1)}}},
{{{man-link(mu-find,1)}}},
{{{man-link(pcre,3)}}},
{{{man-link(jq,1)}}}
