Monday, June 18, 2012

Tracking e-mails to invalid addresses

Customer request: Can you let me know what was e-mailed to an address that doesn't exist on our system? 

Consultant answer: Maybe, but any information on these e-mails will be limited to the source IP and from address. 

Most e-mail systems don't save much when an e-mail is received for a user that doesn't exist, since the recipient e-mail address is sent early in the establishment of the SMTP connection, most e-mails are dropped as soon as the server receives the invalid e-mail address.  On Microsoft Exchange Server 2010, the SMTP connection is logged through verbose protocol logging on the connectors, if this is enabled, you can get a little bit of information on e-mails sent to invalid addresses.

I whipped up the following command for doing just that.

for /f %a in ('dir /b') do for /f "delims=, tokens=3" %b in ('type %a ^| find /i "unkownuser@exchangelab.info"') do for /f "delims=, tokens=1,8" %c in ('type %a ^| find "%b" ^| find "MAIL FROM"') do echo %c - %d >>; unknownuser.log
I'll break it down

for /f %a in ('dir /b')
This one should be easy, dir /b, a basic directory listing and store it in a variable, you'll see %a in the next line.  I ran the script from c:\Program Files\Microsoft\Exchange Server\V14\TransportRoles\Logs\ProtocolLog\SmtpReceive\

for /f "delims=, tokens=3" %b in ('type %a ^| find /i "unkownuser@exchangelab.info"')
This one is a little more complex, using the %a from above, I type each file piping to find, the e-mail address I'm looking for.  I'm only looking for the connection's session identifier in the comma delineated file, hence the tokens=3, which I store in another variable.

for /f "delims=, tokens=1,8" %c in ('type %a ^| find "%b" ^| find "MAIL FROM"')
Using the file names in %a from above, plus the session ID I've stored in %b, I type the files again, limiting it to only the session ID I'm looking for, filtering it further to the MAIL FROM entry.  This will get me the e-mail address that tired to send the e-mail.  This time I want different fields, 2 this time, the date-time and the data, which will give me some useful data in my variables %c and %d.  Notice that I don't define %d, the for command does that for me.

echo %c - %d >> unknownuser.log
finally, take the %d and %d from above and write them to a file

I actually started doing this in powershell, but it was taking longer than I thought it should.  Since I've done a lot of log parsing with the for command, I decided to go to what I know and use the old DOS commands.  My colleague is working on a powershell version, if he posts it to his blog, I'll give him a link.