Catchall Mail

As a proud owner of a domain coupled with a mail server I have the freedom to use any mail address below that domain. So a long time ago I decided to use a catchall address. This is great, I can use it to track who is leaking my mail address (either by accident or on purpose - does not matter).

So when I register somewhere using shabby-webshop@example.org and, after a certain period of time, spam arrives on that address I know what to do: Cancel my account there and reject all further mails to that address. Maybe also poke around how this happened - but that’s optional…

But catchall addresses have some huge drawback:

After some time you completely lose track which addresses are in use, how often mails arrive there, and so on. All I have is my list of blacklisted addresses - I don’t know anything of the active ones.

This has to stop - so today I started to fiddle around in my mail setup to track active addresses.

I am using procmail to sort the mails directly on the server anyway - so why not start here? The first rule inside the definitions looks now like this:

:0 c
| /some/path/to/monitor.py

It passes a copy of the mail (note the c flag) to the monitor.py script and continues normally afterwards.

Inside the monitor.py script I am using something similar to this:

#!/usr/bin/env python3

from email import message_from_file
from email.utils import getaddresses
from json import dump, load
from os import path
from sys import stdin

FILENAME = 'monitor.json'

# read the mail from stdin
mail = message_from_file(stdin.read())

# parse the recipients
recipients = []
for field in ('To', 'Cc', 'Bcc'):
    recipients.extend(mail.get_all(field, []))

# load existing content from json file
result = {}
if path.exists(FILENAME):
    with open(FILENAME, 'r') as jfile:
        result = load(jfile)

# count the addresses
for _, addr in getaddresses(recipients):
    result[addr] = 1 + result.get(addr, 0)

# store result in json file
with open(FILENAME, 'w') as jfile:
    dump(result, jfile, indent=4)

Please note this is just some example code - I’ve added error handling and much more. Please do not just copy & paste that if you intend to use it!

The result is a json file with that content:

{
    "info@example.org": 23,
    "mail@example.org": 42,
    "something@example.org": 5
}

I am totally looking forward to look into the json file after some time. Hopefully this will help me to find some addresses I am using and already have forgotten about. And much more important: Hopefully this script won’t eat up all my mail.

If I won’t reply for some time, you know what happened… 🙈🙉🙊

So long.