Passive SMTP checker that detects whether a server advertises SMTPUTF8 in its EHLO response — the prerequisite for the Unicode Bidi Override email spoofing attack.
Reference: Exploiting SMTP with Unicode Bidi Override — Spoofing the Gap Between Auth and Render — SecurityJoes Research
When an SMTP server announces SMTPUTF8 in its EHLO banner (RFC 6531), it signals support for UTF-8 encoded addresses. This capability is required by the attack chain described by SecurityJoes:
- The server accepts Unicode characters (including Bidi control codepoints) in
MAIL FROM/RCPT TOfields. - A specially crafted sender address with Right-to-Left Override (U+202E) or Left-to-Right Isolate (U+2066) characters is accepted at the protocol layer.
- Mail clients and security gateways render the address differently from what the SMTP session authenticated, creating a spoofed display name that bypasses visual inspection.
No SMTPUTF8 in EHLO → server rejects UTF-8 addresses → attack not viable at the SMTP layer.
# Single host — auto-probes ports 25, 587, 465, 2525
python3 smtputf8_check.py mail.example.com
# Specific port only
python3 smtputf8_check.py mail.example.com --port 587
# Force STARTTLS upgrade after EHLO (use with --port)
python3 smtputf8_check.py mail.example.com --port 587 --starttls
# Verbose: show full EHLO capability list for each open port
python3 smtputf8_check.py mail.example.com -v
# Bulk: one host per line
python3 smtputf8_check.py targets.txt --timeout 15| Argument | Default | Description |
|---|---|---|
target |
— | Hostname/IP or path to a file (one host per line) |
--port PORT |
auto | Single port to probe. Omit to auto-probe 25/587/465/2525 |
--starttls |
off | Force STARTTLS upgrade after EHLO (requires --port) |
--timeout SECS |
8 | Per-port connection timeout |
-v / --verbose |
off | Show full EHLO capability list |
--impersonate LOCAL |
admin | Local-part used in PoC hints when SMTPUTF8 is found |
# one host per line — blank lines and # comments ignored
mail.target-a.com
mx1.target-b.org
10.0.0.25
[SMTPUTF8] mail.vulnerable.com:587 (STARTTLS available)
PoC hints (authorized testing only):
Register domain : bidi-poc-vulnerable-com.test
Impersonate : admin@vulnerable.com
MAIL FROM (RLO) : <moc.elbarenluv@nimda>
MAIL FROM (LRI) : <adminmoc.elpmaxe@bidi-poc-vulnerable-com.test>
MUA renders as : admin@vulnerable.com
Codepoints : U+202E (RLO), U+2066 (LRI), U+2069 (PDI)
Ref : SecurityJoes bidi override / USENIX A14
Banner : mail.vulnerable.com Hello [1.2.3.4]
EHLO :
SIZE 37748736
STARTTLS
AUTH LOGIN PLAIN
SMTPUTF8 ◄ VULNERABLE
[ OK ] mail.safe.com:587
[ skip ] mail.safe.com:25 (refused)
[ skip ] mail.safe.com:465 (timeout)
── Summary ───────────────────────────────────
Hosts checked : 2
Ports probed : 25, 587, 465, 2525
SMTPUTF8 found : 1
Vulnerable hosts:
• mail.vulnerable.com
Exit code 1 if any host has SMTPUTF8, 0 if none — useful for CI/scripting.
Python 3.9+ — stdlib only, no dependencies.
This tool is intended for authorized security assessments and research only. The author is not responsible for misuse.