What command can I use to search sendmail logs for ALL message details involving a specific recipient.

30,210

Solution 1

You could do something similar to this.

for i in `grep -i "[email protected]" /var/log/maillog | awk '{print $5}'`; do grep -i $i /var/log/maillog; done

This will grep out the line for the user you are looking for, then select the 5th item on the line (seperated by spaces iirc). Then for each message ID in that list, will then grep for the lines containing the message ID's.

If you want to remove the : from the end of the message ID, you can do something like for i in grep -i "[email protected]" /var/log/maillog | awk '{print $5}' | sed 's/\://; do grep -i $i /var/log/maillog; done

Hope that helps.

Solution 2

This is a refinement of Harry's answer.

First, awk can do pattern matches like grep, so you can skip the first grep. Also, you might get duplicates, so we can remove those with sort -u:

for i in `awk '/[email protected]/ {print $6}' /var/log/maillog | sort -u `; do grep -i $i /var/log/maillog; done

This version uses two passes through the mail log:

awk '/[email protected]/ {print $6}' /var/log/maillog | sort -u > /tmp/message-ids.list
grep -f /tmp/message-ids.list /var/log/maillog

In the first version, the for loop will grep through mail.log for as many message id's found in the log. In the second version, grep will use the list of message id's as a filter and only process the log file once, which will be more efficient for a large log file.

Solution 3

This is not a direct answer to your specific problem (Harry answered that already) but just a thought to plan ahead if you need such information often. Install MIMEDefang and then have the filter_recipient routine log all the information that you need in the format that suits you best.

Solution 4

There's no reason to pipe grep into awk since AWK can do grep's job. There's also no reason to use a for loop since grep can accept patterns on its standard input.

awk '/[email protected]/ {print $6}' /var/log/maillog | sort -u  | grep -i -f - /var/log/maillog

You can modify that further, removing the need for sort -u (really, sort is unnecessary - you could have used uniq)

awk '/[email protected]/ {addr[$6]} END {for (a in addr) {print addr[a]}}' /var/log/maillog | grep -i -f - /var/log/maillog

Both of those (and the other answers) do the search in two or more passes over the log file. It would be interesting to see if the following one-pass technique would be faster (and faster yet using Perl or Python).

awk -v addr='[email protected]' '$0 ~ addr {
         ids[$6]
     }
     {
         for (id in ids) {
             if ($0 ~ "^" ids[id] "$") {
                 print
             }
         }
     }
     $NF == "Completed" {
         delete ids[$1]
     }' /var/log/maillog

I haven't tested that code. You may need to adjust the field numbers, particularly in the section that deletes the id when the "Completed" log entry is found. It can be easily made into a one-liner.

Share:
30,210

Related videos on Youtube

Mike B
Author by

Mike B

Technology Enthusiast, Gamer, Sci-Fi Addict, and DIY-er in training. =)

Updated on September 18, 2022

Comments

  • Mike B
    Mike B almost 2 years

    CENTOS 5.x | Sendmail

    Occasionally I need to search through sendmail delivery logs to find out what happened to a missing message. This usually involves two (or more) steps:

    STEP 1: Search /var/log/maillog for the user's email address. For example grep -i "[email protected]" /var/log/maillog

    That usually returns something like this:

      Jan 11 07:43:34 server-example sendmail[12732]: p937blksdh3: to=<[email protected]>, delay=00:00:00, xdelay=00:00:00, mailer=esmtp, pri=102537, relay=mta.recipientdomain.com. [12.34.56.78], dsn=5.7.1, stat=Service unavailable
    

    STEP 2: I'll then grab the unique message name (in this case p937blksdh3) and search for that. For example: grep -i p937blksdh3 /var/log/maillog

    I want to combine steps 1 and 2 into a one-liner and have it automatically perform the same search for other ids. So in a single command, I'd like to do the following:

    1. Search sendmail maillog for specific string.
    2. Identify the message-id (in the example above, this was p937blksdh3) for the email. (I'm guessing awk '{print $}' would be used?)
    3. Search the same log but search for the message id instead (basically grep -i p937blksdh3 /var/log/maillog in the example above)
    4. Output the results of step 3. Repeat this for other message ids.
  • Mike B
    Mike B over 12 years
    AWESOME! A couple quick questions... wouldn't it technically be awk '{print $6} based on my example? Also... is there a way to paginate? Maybe something like: for i in grep -i "[email protected]" /var/log/maillog | awk '{print $6}'; do grep -i $i /var/log/maillog; done | less
  • Harry
    Harry over 12 years
    You are correct. I can do math! You would do awk '{print $6}' I just missed a space when glancing at it. If you wanted to page the output, then a less at the end would be correct. for i in grep -i "[email protected]" /var/log/maillog | awk '{print $5}'; do grep -i $i /var/log/maillog; done | less