I want to find all emails in my IMAP folders that contain a certain text (namely: that are sent to a certain email address). I already found out I can do so by using grep like so:

grep -rnw '~/users/example' -e "my@example.com"

This returns either the matched text or the name of the file (with -l). But what I really need for my task is to know the "Title" of the email file that was found.


So, I somehow need to find the files based on the grep above, but the result that is listed should be a different part of that same file (maybe with regex?).

How can I go about this?

  • can you add an example how the file looks when there is match? one idea is to pass matched files to another program... grep -rFwlZ '~/users/example' -e 'my@example.com' | xargs -0 <some command> or may be use find+awk combo.. -F option for literal string matching, no regex here – Sundeep Apr 7 '17 at 5:09
  • grep is not the right tool for this, since both the address and the text can be encoded in various ways. You could use a mail client such as mutt, but that's only good for interactive use. You need to write a program (perhaps in Perl or Python) around an IMAP client. – Satō Katsura Apr 7 '17 at 5:47
  • @Sundeep I added an example output with -l – F.P Apr 7 '17 at 7:14

Using formail (shipped with procmail):

find ~/users/example -type f -exec sh -c '
  for email do
    formail -x to -x cc < "$email" |
      grep -qF my@example.com &&
      formail -cx subject < "$email"
  done' sh {} +

That is, for each email file

  • extract the To and Cc headers
  • search for my@example.com in there
  • if found, extract the Subject header and print it on one line (with -c).
| improve this answer | |
  • This works if you want to search messages by addresses, but not if you want to search the body (since formail doesn't decode attachments etc.). – Satō Katsura Apr 8 '17 at 10:14
  • @SatoKatsura. True, if the OP had a different question, that would call for a different answer. Not sure it's worth going into the details on how to parse and decode emails. Given the subject of the question, formail already goes beyond what is asked. – Stéphane Chazelas Apr 8 '17 at 11:01
  • This works perfectly fine for my needs. Thanks a lot :) – F.P Apr 10 '17 at 6:04

What is the "Title" of a file, the path or name? Use the --files-with-matches option or -l to list matched filenames. If you search only fixed strings instead of regular expressions, speed up the process with -F

grep -F -r -l my@example.com ~/users/example

Do match other content of the file, grep the list of found files (fgrep is the same as grep -F):

fgrep -rl my@example.com ~/users/example | xargs grep '^Subject:'

Hint: many commands stops the parsing of options at the first argument without minus-character. So all options are should be called first.

| improve this answer | |
  • This doesn't work, since the headers can be encoded (cf. RFC 2047 and RFC 2231). – Satō Katsura Apr 8 '17 at 10:16

With mutt:

muff -f ~/users/example/.Archives.2013

(assuming that's a maildir folder). And within mutt, type l (lowercase L).

At the Limit to messages matching: prompt, enter:

~C my@example.com

(though strictly speaking, as it's a regexp, it should be ~C 'my@example\.com' for the . to be matched literally).

Or start mutt as:

mutt -f ~/users/example/.Archives.2013 -e 'push "l ~C my@example.com"'

~C searches in the To: and Cc: headers.

Check the manual for the search syntax.

To search in more than one mailbox at once, there are several mail indexers that you can use (within mutt or not). See https://dev.mutt.org/trac/wiki/UseCases/SearchingMail for instance.

| improve this answer | |
  • This is fine if you want to get the results interactively, but it isn't useful from a script. – Satō Katsura Apr 8 '17 at 10:09

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.