posted: March 7, 2021
tl;dr: Fighting back, with 80 lines of Python...
I harbor no delusions that I will ever be able to stop the email@example.com spam scam emails from polluting my personal email account. Yet I did decide to fight back, to reduce my own personal aggravation.
I still use, for my personal email, a Hotmail account that I got when Hotmail was a cutting-edge startup company in the 1996-1997 timeframe. Hotmail, today, is Microsoft’s free Outlook email service (they like to keep renaming it). I use Google Mail at work, so I can compare and contrast them based on personal experience. Google Mail (a.k.a. GMail) does have better spam detection, which appears to be based upon more sophisticated algorithms than Microsoft Outlook employs. GMail does a reasonably good job of separating spam from legitimate mail, although occasionally a spam message makes it into my Inbox and a legitimate message ends up in my Spam folder. Legitimate messages landing in my Spam folder are rare enough occurrences that I don’t have to regularly check the Spam folder.
For my Hotmail/Outlook account, I long ago learned that I needed to run it in the strictest Inbox filtering mode, lest too many spam messages land there. To make it into my Inbox, an email needs to be sent by someone already in my contacts list, or from a domain or subdomain that I have explicitly added to a “safe” list (i.e. whitelisted). This works reasonably well: my Inbox is very clean, but I do need to occasionally check my Junk folder for messages from new senders that I do want to receive. If I have to wade through too much junk, it slows me down.
The firstname.lastname@example.org email spam scam seems specifically designed to defeat my Outlook email filtering scheme, because the spammer is so prolific. My Junk mail folder fills up with spam from the burner domains purchased from NameCheap by the spammer. There is definitely a pattern to the emails, and I am a bit surprised that the Outlook folks at Microsoft haven’t yet figured out a way to combat this spammer.
I decided to take matters into my own hands by writing a script to clean up my Junk mail folder by detecting and deleting the email@example.com scam emails. I knew I could use ICANN’s whois service, which most Unix-like operating systems make available via the ‘whois’ command, to look up the domain of each email in my Junk mail folder to see if it was registered with NameCheap. If it was, I would automatically delete it. As a small act of retribution, I also decided to, for each such email, send an email to the account that NameCheap is required to maintain for complaints about domain scams, which is ‘firstname.lastname@example.org’.
The script turned out to be a lot easier to write than I had expected, thanks to the power of Python. I have written code to interface with a variety of email service providers, such as Mailchimp, Mailgun, and Vero, and that code typically involves importing a library from the email service provider which provides an API. But it turns out that, for standard IMAP and SMTP-based email services like Hotmail/Outlook and GMail, Python comes with all the libraries you need as part of the Python standard library. There’s plenty of online documentation, typically blog posts, from Python programmers who explain how to do various email tasks. Here are the ones that I found most useful:
With these blog posts as a guide, I quickly pieced together a script which works. The other trick I employed is using Python’s subprocess module to run the operating system ‘whois’ command, and capturing and parsing the output that it produces. The subprocess module is pretty amazing because it gives a Python program the ability to do almost anything that can be done from the command line. It’s as though the entire operating system is available as a module.
The current version of the script is just 80 lines long. It logs into my email account, to be able to read, send, and delete emails. It goes through the emails in my Junk folder, and for each one that it finds, it looks up the sender’s domain in whois to see if the domain came from NameCheap, plus a couple other shady DNS registrars that the script also discovered for me: 'name.com' and 'namesilo.com'. If the sender used a shady DNS registrar, it creates a new email from some of the whois output plus the body of the spam email, and sends a complaint email to the DNS registrar’s abuse account. It then deletes the spam email. It also deletes the emails that NameCheap sends as an autoreply to each spam complaint email that the script sends.
So far the script has worked great. I run it a few times a day, and it does a great job of cleaning up my Junk mail folder, leaving none or just a handful of other emails for me to review. So far every single email that it has deleted has indeed been a spam email. I can still see enough info about the spam to be able to take action if the script deletes an email that I don’t want to be deleted. Once I’m more confident in the script, I’ll move it into the cloud, so that I don’t have to manually launch it.
As expected, NameCheap is not taking any action on the abuse complaints that I am filing. Their system did, after the first one, set up an account for me that I can use to see the disposition of each complaint that is filed. I truly doubt any human at all is looking at the complaints: they probably have their own automation to simply close out every complaint filed after a certain delay, which makes it appear as though they are considering the complaint. The next step, if I want to escalate the battle with NameCheap, would be to file a complaint about NameCheap with ICANN, for every spam email sent from a domain that NameCheap registered. ICANN has a web form to do so, but is protected with a reCAPTCHA to try to prevent bots from filling it out (maybe there is a Python library to submit reCAPTCHAs?).
Here is the current version of the script:
# Standard library imports
from email.mime.text import MIMEText
MY_EMAIL = 'MY_EMAIL'
MY_PASSWORD = 'MY_PASSWORD'
FOLDER_TO_DESPAM = 'Junk'
SHADY_REGISTRARS = ('namecheap.com', 'name.com', 'namesilo.com', )
smtp = smtplib.SMTP('smtp-mail.outlook.com', 587)
imap = imaplib.IMAP4_SSL('smtp-mail.outlook.com', 993)
_, messages = imap.search(None, 'ALL')
mail_ids = messages.split()
for mail_id in mail_ids:
_, message = imap.fetch(mail_id, '(RFC822)')
for response in message:
if isinstance(response, tuple):
msg = email.message_from_string(response.decode('utf-8'))
print('\nFrom: ' + msg['from'])
print('Subject: ' + msg['subject'])
# Delete autoreply sent by Namecheap's abuse account
if msg['from'].startswith('"Namecheap.com"') and msg['subject'].startswith('Re: Spam being sent'):
imap.store(mail_id, '+FLAGS', '\\Deleted')
print('Deleted email with subject:', msg['subject'])
email_body = msg.get_payload(decode=True) or b''
email_body_nodecode = msg.get_payload(decode=False) or b''
spammer_email = msg['from'].split('<').split('>')
spammer_domain = '.'.join(spammer_email.split('@').split('.')[-2:])
print('Checking whois for:', spammer_domain)
result = subprocess.run(['whois', spammer_domain],
for shady_registrar in SHADY_REGISTRARS:
if shady_registrar in result.stdout:
print('Unrecognized DNS registrar')
shady_registrar_email = result.stdout.split('Registrar Abuse Contact Email: ').split('\n')
if 'Registry Registrant ID:' in result.stdout:
whois_body = 'Registry Registrant ID:' + result.stdout.split('Registry Registrant ID:').split('Name Server:')
else: # whois database did not return complete info
whois_body = ' Domain Name:' + result.stdout.split('Domain Name:').split('>>> Last update')
msg_out = MIMEText(whois_body + '\n\n' + str(email_body, 'utf-8'))
except UnicodeDecodeError as e:
msg_out = MIMEText(whois_body + '\n\n' + email_body_nodecode)
print('Had to use decode=False version of original email body')
msg_out['Subject'] = 'Spam being sent from ' + spammer_email
msg_out['From'] = MY_EMAIL
msg_out['To'] = shady_registrar_email
print('Sending abuse complaint to:', shady_registrar_email)
smtp.sendmail(MY_EMAIL, [shady_registrar_email], msg_out.as_string())
print('Deleting email with subject:', msg['subject'])
imap.store(mail_id, '+FLAGS', '\\Deleted')
imap.expunge() # permanently remove emails that are marked as deleted from the selected mailbox