Lets say I have 5 messages in /var/mail/ and I want to read one message at a time and then do some string search in that mail before moving on to the next message. Is there a command that I can use to parse one message at a time ?

I am looking to write a bash script which will read all messages in an mbox file & then read them one at a time so that I can then extract Subject, To, From & Status of the message(bounceback code). My plan was to use grepmail to get count of emails in the file and then use this count in a for loop to get one mail at a time and them perform operation on the text. Something like:

$count = grepmail -r . /var/mail/user | awk '{print $2}'
for($i=1;$i<=$count;$i++) {
    $content = *GetMessage* -number $i /var/mail/user
    Do string operation on this message & save to $DelimitedData

I can't figure out how to pickup single message at a time to perform string operation on them. Can someone please guide me which command/program can help me do this non interactively.

  • 1
    I'm guessing you mostly work with powershell? – jesse_b Aug 9 '19 at 19:11
  • @Jesse_b Yes I mostly script in powershell. I have a script that does exactly what I want, but we are moving to a linux box for some of the emails and I want to make sure that I get the reports. – OjasP Aug 9 '19 at 19:16
  • You can install powershell on linux, but hopefully someone can also help you with a shell solution as it will be faster. – jesse_b Aug 9 '19 at 19:20
  • @Gilles formail answer is good, but it's also worth knowing that the "beginning of message" marker in an mbox format file is a line beginning with From ("From" and a space character). This can reliably be used to split mbox files into individual messages, with the regexp ^From as it is guaranteed NOT to be within the headers or body of the message (any body lines that would have started with "From " are changed when saved into an mbox, usually to ">From " or similar). See en.wikipedia.org/wiki/Mbox – cas Aug 10 '19 at 1:24

The formail tool from procmail (available in any distribution, it's a classic) is designed precisely for this purpose.

Basic usage:

formail -s myprogram --option

runs myprogram --option on each mail in turn. The program receives each mail on its standard input.

  • Not sure that formail can pick up the Nth message in an existing spool file, though Can it? – roaima Aug 9 '19 at 23:10
  • @roaima I don't think it's needed (the OP had that loop because they didn't know how to process messages in an mbox one-by-one), but formail has a +skip option, and a -total option (the "skip" in the +skip is the number of messages to skip, and the "total" in -total is the total number of msgs to output - so +5 -1 would output only the 6th message). – cas Aug 10 '19 at 1:15
  • Thanks for the comment @Gilles. I can't figure out how to use the stream from formail in a shell script. In my test script I am just reading input from formail -s command & displaying it but i don't get any output & the script waits until I press Ctrl+C. Here's my script: #!/bin/sh print $1 read -p message </dev/tty echo "${message}" I am calling it by formail -s test.sh -d – OjasP Aug 12 '19 at 13:56
  • 1
    @OjasP formail reads from standard input, so e.g. formail </var/mail/bob -s test.sh – Gilles 'SO- stop being evil' Aug 12 '19 at 14:01
  • Thanks @Gilles! For someone else who stumbles across this, I used this command: formail -s </var/mail/user ./test.sh . And, in the test.sh file I am reading the message using message=$(</dev/stdin) – OjasP Aug 12 '19 at 16:24

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.