A web tool for analyzing suspicious emails for signs of phishing or malware.
Upload a .eml or .msg email file and MailDrop will:
- Show email header details (sender, route, SPF/DKIM/DMARC authentication)
- Plot the email's geographic route on a map, using an offline GeoLite2 database so no IP addresses ever leave your server
- Scan attachments against VirusTotal and flag infected files
- Statically inspect each attachment for malware signs without ever running it: content/extension mismatches, dangerous file types, Office macros and remote templates, risky PDF actions, dangerous archive contents, and HTML smuggling
- Extract all links from the email body, unwrap security-gateway rewrites, and check them against VirusTotal
- Detect hidden tracking pixels and list all remote content the email would load
- Flag links whose visible text does not match their destination, punycode domains, and lookalikes of the sender domain
- Show a safe text-only preview of the message body
- Warn if the email looks like a phishing attempt, with the evidence explained
Uploaded files are processed entirely in memory and are never stored.
With Docker Compose (recommended):
cp .env.example .env # add your API keys
docker compose upThen open http://localhost.
With plain Docker:
cp .env.example .env # add your API keys
docker build -t maildrop .
docker run -d --name maildrop \
--env-file .env \
-e GEOIP_DB_PATH=/data/GeoLite2-City.mmdb \
-p 80:80 \
-v "$(pwd)/data:/data:ro" \
--tmpfs /tmp \
--restart always \
maildropThe .env file is read from the directory you run the command in. To use the prebuilt image instead of building yourself, replace the docker build step and the final maildrop argument with ghcr.io/bjornhels/maildrop:latest.
Without Docker:
pip install -r requirements.txt
python app.pyCreate a .env file with:
API_KEY=your_virustotal_api_key
MAPBOX_TOKEN=your_mapbox_token
BRAND_NAME=Your Organization
API_KEY— VirusTotal API key. Required for attachment and link scanning; without it, attachments show as "Not checked".MAPBOX_TOKEN— Mapbox access token. Optional; the map is hidden when unset.BRAND_NAME— Optional organization name shown in the page title and header next to "MailDrop".GEOIP_DB_PATH— Path to the GeoLite2 City database. Optional; geolocation and the map are disabled when the file is missing. With Docker, place the file in./data/and the bundled compose file mounts it automatically.
Static attachment analysis lives in static_analysis.py. Each check is a function that takes a FileContext (with the raw bytes, the filename, the parsed extension, and the detected file type) and returns a list of findings. Adding a new check is one function:
@register
def inspect_my_rule(ctx):
if not_relevant(ctx):
return []
return [finding(
'medium', # high | medium | low | info
'my-category',
'Short title shown to the user',
'the exact thing observed',
'A plain-language explanation of why this matters.',
)]The @register decorator adds it to the pipeline automatically; findings are deduplicated, sorted by severity, and rendered under the attachment. No check ever executes the file - they only parse and inspect its bytes.
Geolocation runs fully offline against a local MaxMind GeoLite2 database, so the IP addresses found in analyzed emails never leave your server.
- Create a free MaxMind account at https://www.maxmind.com/en/geolite2/signup.
- Sign in and go to Download Files under GeoIP, then download the GeoLite2 City database in
.mmdbformat. - Place the file at
./data/GeoLite2-City.mmdbnext todocker-compose.yaml(or setGEOIP_DB_PATHto wherever you keep it when running without Docker). - Restart the app. MaxMind updates the database twice a week, so re-download it now and then (or automate it with their
geoipupdatetool).
- Create a free account at https://www.virustotal.com/gui/join-us.
- Sign in, open your profile menu in the top right corner and choose API key.
- Copy the key into
API_KEYin your.envfile.
The free tier allows 4 lookups per minute and 500 per day. MailDrop uses one lookup per attachment and up to 10 link lookups per analyzed email, so a busy instance may need a paid tier.
- Create a free account at https://account.mapbox.com/auth/signup/.
- Go to https://account.mapbox.com/access-tokens/ and use the Default public token, or create a dedicated token for MailDrop.
- Add a URL restriction on the token so it only works from your site's domain. Public tokens are visible to everyone who visits the page, and the restriction prevents anyone else from using yours.
- Copy the token into
MAPBOX_TOKENin your.envfile.