How Email Works for Pentesters
TL;DR: Email uses SMTP for sending, POP3/IMAP for receiving. SPF, DKIM, and DMARC protect against spoofing. Understanding email flow is essential for phishing assessments and email security testing.
Table of Contents
Open Table of Contents
Quick Reference
Email Ports
| Port | Protocol | Security | Use |
|---|
| 25 | SMTP | None/STARTTLS | Server-to-server |
| 465 | SMTPS | Implicit TLS | Submission (deprecated) |
| 587 | SMTP | STARTTLS | Client submission |
| 110 | POP3 | None/STARTTLS | Receive mail |
| 995 | POP3S | Implicit TLS | Receive mail (secure) |
| 143 | IMAP | None/STARTTLS | Receive mail |
| 993 | IMAPS | Implicit TLS | Receive mail (secure) |
Essential Commands
| Command | Purpose | Example |
|---|
dig TXT | Query SPF/DKIM/DMARC | dig TXT example.com |
nmap smtp | SMTP enumeration | nmap --script smtp-* -p 25 target |
swaks | SMTP testing | swaks --to test@target.com |
telnet | Manual SMTP | telnet mail.target.com 25 |
mxtoolbox | Online email testing | mxtoolbox.com |
Email Security Records
| Record | DNS Type | Purpose | Example |
|---|
| SPF | TXT | Authorize senders | v=spf1 include:_spf.google.com -all |
| DKIM | TXT | Sign messages | selector._domainkey.example.com |
| DMARC | TXT | Policy enforcement | _dmarc.example.com |
| MX | MX | Mail server | 10 mail.example.com |
Why Email Matters for Pentesters
Phishing: The #1 Attack Vector
| Year | % of Breaches Starting with Phishing |
|---|
| 2020 | 36% |
| 2021 | 41% |
| 2022 | 39% |
| 2023 | 44% |
What Pentesters Test
- Email spoofing - Can we send as target domain?
- SPF/DKIM/DMARC - Are protections configured correctly?
- SMTP enumeration - User harvesting, version info
- Phishing simulation - Social engineering assessments
- Email headers - Information disclosure
- Open relays - Unauthorized mail forwarding
Real-World Email Attacks
| Attack | Technique | Impact |
|---|
| BEC (Business Email Compromise) | Domain spoofing | $26B+ losses (FBI 2023) |
| Credential Phishing | Fake login pages | Account takeover |
| Malware Delivery | Malicious attachments | System compromise |
| Supply Chain | Vendor impersonation | Multi-org breach |
Email Architecture
TL;DR: Email travels from sender’s client → sender’s server → recipient’s server → recipient’s client.
Email Flow
┌──────────────┐ ┌──────────────┐
│ Sender │ │ Recipient │
│ (Alice) │ │ (Bob) │
│ │ │ │
│ alice@a.com │ │ bob@b.com │
└──────┬───────┘ └──────▲───────┘
│ │
│ 1. Compose & Send │ 6. Retrieve
│ (SMTP:587) │ (IMAP:993)
│ │
▼ │
┌──────────────┐ ┌──────────────┐
│ Mail Server │ 2. SMTP Relay ┌───────────► │ Mail Server │
│ (a.com) │─────────────────────│ │ (b.com) │
│ │ │ │ │
│ MTA + MSA │ 3. DNS MX Lookup │ │ MTA + MDA │
└──────────────┘ for b.com ─────┘ └──────────────┘
│
▼
┌──────────┐
│ DNS │
│ Server │
└──────────┘
Returns: MX 10 mail.b.com
Email Components
| Component | Full Name | Role |
|---|
| MUA | Mail User Agent | Email client (Outlook, Gmail web) |
| MSA | Mail Submission Agent | Accepts mail from MUA |
| MTA | Mail Transfer Agent | Routes mail between servers |
| MDA | Mail Delivery Agent | Delivers to mailbox |
| MX | Mail Exchanger | DNS record pointing to mail server |
Complete Email Journey
1. Alice writes email to bob@b.com
2. Alice's MUA connects to MSA (SMTP:587, authenticated)
3. MSA accepts and forwards to MTA
4. MTA queries DNS for b.com MX record
5. DNS returns: MX 10 mail.b.com
6. MTA connects to mail.b.com (SMTP:25)
7. Remote MTA verifies SPF, DKIM, DMARC
8. MDA stores in Bob's mailbox
9. Bob's MUA retrieves via IMAP:993
SMTP Deep Dive
TL;DR: SMTP (Simple Mail Transfer Protocol) is the protocol for sending email. Understanding SMTP commands is essential for testing.
SMTP Conversation
┌────────────────────────────────────────────────────────────────────┐
│ SMTP Session Example │
├────────────────────────────────────────────────────────────────────┤
│ │
│ Client connects to server:25 │
│ │
│ S: 220 mail.example.com ESMTP Postfix │
│ C: EHLO sender.com │
│ S: 250-mail.example.com │
│ S: 250-PIPELINING │
│ S: 250-SIZE 10240000 │
│ S: 250-STARTTLS │
│ S: 250-AUTH PLAIN LOGIN │
│ S: 250 8BITMIME │
│ C: MAIL FROM:<alice@sender.com> │
│ S: 250 Ok │
│ C: RCPT TO:<bob@example.com> │
│ S: 250 Ok │
│ C: DATA │
│ S: 354 End data with <CR><LF>.<CR><LF> │
│ C: Subject: Test Email │
│ C: From: alice@sender.com │
│ C: To: bob@example.com │
│ C: │
│ C: This is the email body. │
│ C: . │
│ S: 250 Ok: queued as 12345 │
│ C: QUIT │
│ S: 221 Bye │
│ │
└────────────────────────────────────────────────────────────────────┘
SMTP Commands
| Command | Purpose | Example |
|---|
HELO | Identify sender (basic) | HELO sender.com |
EHLO | Identify sender (extended) | EHLO sender.com |
MAIL FROM | Specify sender | MAIL FROM:<alice@sender.com> |
RCPT TO | Specify recipient | RCPT TO:<bob@target.com> |
DATA | Begin message content | DATA |
QUIT | End session | QUIT |
VRFY | Verify user exists | VRFY bob |
EXPN | Expand mailing list | EXPN admins |
RSET | Reset session | RSET |
AUTH | Authenticate | AUTH PLAIN ... |
STARTTLS | Upgrade to TLS | STARTTLS |
SMTP Response Codes
| Code | Meaning | Example |
|---|
| 2XX | Success | 250 Ok |
| 3XX | Continue | 354 Start mail input |
| 4XX | Temporary failure | 450 Mailbox unavailable |
| 5XX | Permanent failure | 550 User not found |
SMTP Vulnerabilities
| Vulnerability | Impact | Check |
|---|
| Open Relay | Send spam through server | MAIL FROM external, RCPT TO external |
| VRFY enabled | User enumeration | VRFY username |
| EXPN enabled | List enumeration | EXPN mailinglist |
| No STARTTLS | Traffic interception | Check EHLO response |
| Weak AUTH | Credential brute force | Test AUTH mechanisms |
| Attack | Detect | Defend |
|---|
| Open relay abuse | Monitor outbound volume | Require authentication |
| User enumeration | Log VRFY/RCPT attempts | Disable VRFY/EXPN |
| Credential stuffing | Monitor failed auths | Rate limiting, MFA |
| Spoofing | Check SPF/DKIM/DMARC | Implement all three |
SMTP Testing Commands
# === Manual SMTP Testing ===
# Connect with telnet
telnet mail.target.com 25
# Connect with openssl (TLS)
openssl s_client -connect mail.target.com:465
openssl s_client -starttls smtp -connect mail.target.com:587
# === Test for Open Relay ===
# Using telnet
telnet mail.target.com 25
EHLO test.com
MAIL FROM:<test@external.com>
RCPT TO:<anyone@another-external.com>
# If "250 Ok" - OPEN RELAY!
# Using nmap
nmap --script smtp-open-relay -p 25 mail.target.com
# === User Enumeration ===
# VRFY method
telnet mail.target.com 25
VRFY admin
VRFY bob
VRFY nonexistent
# RCPT TO method (more reliable)
MAIL FROM:<test@test.com>
RCPT TO:<admin@target.com> # 250 = exists
RCPT TO:<nonexistent@target.com> # 550 = doesn't exist
# Using smtp-user-enum
smtp-user-enum -M VRFY -U users.txt -t mail.target.com
smtp-user-enum -M RCPT -U users.txt -t mail.target.com
# === Using swaks ===
# Basic send test
swaks --to test@target.com --server mail.target.com
# Test authentication
swaks --to test@target.com --server mail.target.com \
--auth LOGIN --auth-user user --auth-password pass
# Test with custom from
swaks --to victim@target.com --from ceo@target.com \
--server mail.target.com
# === Nmap Scripts ===
# All SMTP scripts
nmap --script "smtp-*" -p 25,465,587 mail.target.com
# Specific scripts
nmap --script smtp-commands -p 25 mail.target.com
nmap --script smtp-enum-users --script-args smtp-enum-users.methods={VRFY} -p 25 mail.target.com
nmap --script smtp-vuln-cve2010-4344 -p 25 mail.target.com
POP3 and IMAP
TL;DR: POP3 downloads and (usually) deletes email. IMAP keeps email on server with folder sync. Both used for retrieving mail.
POP3 vs IMAP
| Feature | POP3 | IMAP |
|---|
| Email storage | Downloads to client | Stays on server |
| Multiple devices | Poor support | Full sync |
| Folders | No support | Full support |
| Search | Local only | Server-side |
| Bandwidth | Download all | Download on demand |
| Offline | Full access | Limited |
| Ports | 110 (plain), 995 (SSL) | 143 (plain), 993 (SSL) |
POP3 Commands
| Command | Purpose |
|---|
USER | Specify username |
PASS | Specify password |
STAT | Mailbox statistics |
LIST | List messages |
RETR | Retrieve message |
DELE | Delete message |
QUIT | End session |
IMAP Commands
| Command | Purpose |
|---|
LOGIN | Authenticate |
SELECT | Select mailbox |
FETCH | Retrieve message |
SEARCH | Search messages |
STORE | Modify flags |
LOGOUT | End session |
POP3/IMAP Testing Commands
# === POP3 Testing ===
# Connect
telnet mail.target.com 110
# or with SSL
openssl s_client -connect mail.target.com:995
# Authenticate
USER testuser
PASS testpass
# List messages
STAT
LIST
# Retrieve message
RETR 1
# === IMAP Testing ===
# Connect
telnet mail.target.com 143
# or with SSL
openssl s_client -connect mail.target.com:993
# Authenticate
a1 LOGIN testuser testpass
# List folders
a2 LIST "" "*"
# Select inbox
a3 SELECT INBOX
# Fetch message
a4 FETCH 1 FULL
# Search
a5 SEARCH FROM "sender@example.com"
# === Nmap Scripts ===
nmap --script "pop3-*" -p 110,995 mail.target.com
nmap --script "imap-*" -p 143,993 mail.target.com
# Brute force
nmap --script pop3-brute -p 110 mail.target.com
nmap --script imap-brute -p 143 mail.target.com
TL;DR: Email headers reveal the full path an email took, authentication results, and potential forgery indicators.
| Header | Purpose | Security Relevance |
|---|
From | Displayed sender | Can be spoofed |
Return-Path | Envelope sender | Used for SPF |
Received | Routing path | Trace email path |
Message-ID | Unique identifier | Identify duplicates |
X-Originating-IP | Sender’s IP | Geographic info |
Authentication-Results | SPF/DKIM/DMARC results | Verify authenticity |
DKIM-Signature | Digital signature | Verify integrity |
X-Mailer | Client software | Reconnaissance |
Received headers are read BOTTOM-UP (oldest first):
Received: from mail.final.com (mail.final.com [1.2.3.4]) ← Most recent
by recipient-server.com (Postfix)
for <bob@recipient.com>; Mon, 1 Jan 2024 12:00:00 +0000
Received: from mail.middle.com (mail.middle.com [5.6.7.8]) ← Middle hop
by mail.final.com (Postfix)
for <bob@recipient.com>; Mon, 1 Jan 2024 11:59:00 +0000
Received: from sender-server.com (sender-server.com [9.10.11.12]) ← First hop
by mail.middle.com (Postfix)
for <bob@recipient.com>; Mon, 1 Jan 2024 11:58:00 +0000
Reading path: sender-server.com → mail.middle.com → mail.final.com → recipient
Authentication-Results: mx.recipient.com;
spf=pass (sender IP is 1.2.3.4) smtp.mailfrom=sender.com;
dkim=pass (signature was verified) header.d=sender.com;
dmarc=pass (p=REJECT sp=REJECT) header.from=sender.com
Breakdown:
- spf=pass → Email came from authorized server
- dkim=pass → Email wasn't modified in transit
- dmarc=pass → Domain's policy was satisfied
Header Analysis Commands
# View raw email headers (in email client)
# Gmail: Show original
# Outlook: View source
# Analyze with online tools
# - mxtoolbox.com/EmailHeaders.aspx
# - mailheader.org
# Command line analysis
# Save email as .eml file, then:
cat email.eml | grep -E "^(From|To|Subject|Received|Authentication|DKIM|Return-Path|X-)"
# Parse received headers
cat email.eml | grep "^Received:" | tac
# Check for spoofing indicators
cat email.eml | grep -E "(Reply-To|Return-Path|From)"
# If From and Return-Path domains differ - suspicious!
SPF (Sender Policy Framework)
TL;DR: SPF is a DNS record that lists which servers can send email for a domain. Receiving servers check if the sender’s IP is authorized.
How SPF Works
1. Sender sends email claiming to be from example.com
2. Receiving server checks SPF:
┌──────────────┐
│ DNS Query: │
│ TXT example. │──────────► DNS Server
│ com │
└──────────────┘ │
│
┌─────▼─────┐
│ SPF Record│
│ v=spf1 │
│ ip4:1.2.3.│
│ 4 -all │
└───────────┘
3. Server checks if sender IP matches record:
- Sender IP: 1.2.3.4 → PASS
- Sender IP: 9.9.9.9 → FAIL
SPF Syntax
v=spf1 ip4:192.168.1.0/24 include:_spf.google.com -all
│ │ │ │
│ │ │ └── Qualifier
│ │ └── Include another SPF record
│ └── Allow this IP range
└── SPF version (required)
SPF Mechanisms
| Mechanism | Purpose | Example |
|---|
ip4 | IPv4 address/range | ip4:192.168.1.1 |
ip6 | IPv6 address/range | ip6:2001:db8::/32 |
a | A record of domain | a:mail.example.com |
mx | MX records | mx |
include | Include another SPF | include:_spf.google.com |
all | Match everything else | -all |
exists | Check DNS existence | exists:%{i}.bl.example.com |
SPF Qualifiers
| Qualifier | Meaning | Result |
|---|
+ (default) | Pass | Accept |
- | Fail | Reject |
~ | Soft fail | Accept but mark |
? | Neutral | Accept |
Common SPF Records
# Google Workspace
v=spf1 include:_spf.google.com ~all
# Microsoft 365
v=spf1 include:spf.protection.outlook.com -all
# Multiple providers
v=spf1 include:_spf.google.com include:sendgrid.net ip4:1.2.3.4 -all
# Strict (no email from this domain)
v=spf1 -all
SPF Vulnerabilities
| Issue | Risk | Check |
|---|
| No SPF record | Spoofing possible | dig TXT domain.com |
~all instead of -all | Soft fail allows delivery | Check qualifier |
| Too many includes | >10 DNS lookups = permerror | Count mechanisms |
| No SPF on subdomains | Subdomain spoofing | Check sub.domain.com |
| Attack | Detect | Defend |
|---|
| Spoof without SPF | Check for TXT record | Publish SPF |
| Exploit ~all | Check SPF qualifier | Use -all |
| Subdomain spoofing | Check all subdomains | SPF on all subdomains |
SPF Testing Commands
# Query SPF record
dig TXT example.com +short | grep spf
# Detailed query
dig TXT example.com
# Check subdomain SPF
dig TXT mail.example.com +short
# Count DNS lookups (max 10)
# Use online tools like mxtoolbox.com/spf.aspx
# Test SPF from command line
# Install: pip install pyspf
spfquery -i 1.2.3.4 -s sender@example.com -h mail.example.com
# Using kitterman.com/spf/validate.html for validation
DKIM (DomainKeys Identified Mail)
TL;DR: DKIM adds a digital signature to emails. The receiving server verifies the signature using a public key in DNS.
How DKIM Works
Sending Server:
┌─────────────────────────────────────────────────────┐
│ 1. Compose email │
│ 2. Generate hash of headers + body │
│ 3. Sign hash with private key │
│ 4. Add DKIM-Signature header │
└─────────────────────────────────────────────────────┘
│
│ Email with signature
▼
Receiving Server:
┌─────────────────────────────────────────────────────┐
│ 1. Extract DKIM-Signature │
│ 2. Query DNS for public key │
│ (selector._domainkey.domain.com) │
│ 3. Verify signature │
│ 4. If valid, email wasn't modified │
└─────────────────────────────────────────────────────┘
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
d=example.com; s=selector1;
h=from:to:subject:date:message-id;
bh=base64-body-hash=;
b=base64-signature-here=
Breakdown:
v=1 → DKIM version
a=rsa-sha256 → Algorithm
c=relaxed → Canonicalization (how whitespace is handled)
d=example.com→ Signing domain
s=selector1 → Selector (to find public key)
h=from:to:...→ Headers that were signed
bh=... → Body hash
b=... → Signature
DKIM DNS Record
DNS Query: selector1._domainkey.example.com TXT
Response:
v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQ...
Breakdown:
v=DKIM1 → Version
k=rsa → Key type
p=... → Public key (base64)
DKIM Vulnerabilities
| Issue | Risk | Check |
|---|
| No DKIM | No integrity check | Query _domainkey |
| Weak key (<1024 bit) | Key factoring | Check key size |
| Key not rotated | Compromised key | Check key age |
| Signature missing headers | Partial protection | Check h= tag |
| Attack | Detect | Defend |
|---|
| Modify unsigned headers | Check h= tag | Sign all headers |
| Replay signed email | Check Message-ID | Include date in signature |
| Key compromise | Monitor DKIM failures | Regular key rotation |
DKIM Testing Commands
# Find DKIM selector (look at email headers)
# DKIM-Signature: ... s=selector1 ...
# Query DKIM record
dig TXT selector1._domainkey.example.com +short
# Common selectors to try
for selector in default google selector1 selector2 s1 s2 dkim; do
echo "Trying: $selector"
dig TXT ${selector}._domainkey.example.com +short
done
# Verify DKIM key size
dig TXT selector1._domainkey.example.com | grep -o 'p=[^;]*' | \
sed 's/p=//' | base64 -d | openssl rsa -pubin -text -noout 2>/dev/null | \
grep "Public-Key"
# Online validation
# - mxtoolbox.com/dkim.aspx
# - mail-tester.com
DMARC (Domain-based Message Authentication)
TL;DR: DMARC tells receiving servers what to do when SPF and DKIM fail, and where to send reports.
How DMARC Works
┌─────────────────────────────────────────────────────────────────┐
│ DMARC Decision Flow │
└─────────────────────────────────────────────────────────────────┘
│
▼
┌──────────────────┐
│ Check SPF │
│ (envelope from) │
└────────┬─────────┘
│
┌──────────────┴──────────────┐
│ │
SPF Pass SPF Fail
│ │
▼ ▼
┌──────────────────┐ ┌──────────────────┐
│ SPF Aligned? │ │ Check DKIM │
│ (domain matches │ │ │
│ header From) │ └────────┬─────────┘
└────────┬─────────┘ │
│ ┌──────────┴──────────┐
┌─────┴─────┐ │ │
│ │ DKIM Pass DKIM Fail
Aligned Not Aligned │ │
│ │ ▼ ▼
│ │ ┌──────────────────┐ ┌──────────────┐
│ │ │ DKIM Aligned? │ │ DMARC FAIL │
│ │ └────────┬─────────┘ │ Apply policy │
│ │ │ └──────────────┘
│ │ ┌─────┴─────┐
│ │ Aligned Not Aligned
│ │ │ │
▼ ▼ ▼ ▼
┌─────────────────────────────────────────────────────┐
│ DMARC PASS │ DMARC FAIL │
│ (at least one aligned pass) │ Apply policy │
└─────────────────────────────────────────────────────┘
DMARC Record
_dmarc.example.com TXT "v=DMARC1; p=reject; rua=mailto:dmarc@example.com; ruf=mailto:forensics@example.com; pct=100"
Breakdown:
v=DMARC1 → Version
p=reject → Policy (none, quarantine, reject)
rua=mailto:... → Aggregate report address
ruf=mailto:... → Forensic report address
pct=100 → Percentage of emails to apply policy
sp=reject → Subdomain policy
adkim=s → DKIM alignment (s=strict, r=relaxed)
aspf=s → SPF alignment (s=strict, r=relaxed)
DMARC Policies
| Policy | Action | Use Case |
|---|
p=none | Monitor only | Initial deployment |
p=quarantine | Mark as spam | Testing phase |
p=reject | Block email | Full enforcement |
DMARC Vulnerabilities
| Issue | Risk | Check |
|---|
| No DMARC | No policy enforcement | dig TXT _dmarc.domain.com |
p=none | No protection, just monitoring | Check policy tag |
| No subdomain policy | Subdomain spoofing | Check sp= tag |
Low pct | Partial protection | Check pct value |
| Attack | Detect | Defend |
|---|
| Spoof with p=none | Check DMARC policy | Set p=reject |
| Subdomain spoofing | Check sp= tag | Set sp=reject |
| Lookalike domain | Monitor reports | Implement DMARC |
DMARC Testing Commands
# Query DMARC record
dig TXT _dmarc.example.com +short
# Check subdomain DMARC (inherits from parent if not set)
dig TXT _dmarc.sub.example.com +short
# Validate DMARC record
# Online: mxtoolbox.com/dmarc.aspx
# Online: dmarcanalyzer.com/dmarc/dmarc-record-check
# Full email authentication check
# Send test email to: check-auth@verifier.port25.com
# Or: ping@tools.mxtoolbox.com
Email Spoofing Techniques
TL;DR: Email spoofing sends emails with forged sender addresses. Success depends on target’s email security configuration.
Spoofing Decision Tree
Can we spoof @target.com?
1. Check SPF
└── No SPF? → Likely spoofable
└── SPF exists? → Check qualifier
└── ~all (softfail)? → May work (marked suspicious)
└── -all (fail)? → Check DMARC
2. Check DMARC
└── No DMARC? → SPF softfail works
└── p=none? → Spoofable (just monitored)
└── p=quarantine? → Goes to spam
└── p=reject? → Blocked
3. Check DKIM
└── No DKIM? → No signature verification
└── DKIM exists? → Email modification detected
4. Subdomain check
└── Check sub.target.com (often unprotected)
Spoofing Techniques
| Technique | Description | Bypasses |
|---|
| Direct spoofing | Send as @target.com | No SPF/DMARC |
| Subdomain spoofing | Send as @sub.target.com | Missing subdomain records |
| Display name spoofing | ”CEO” attacker@evil.com | User awareness |
| Lookalike domain | @target-corp.com | Technical controls |
| Reply-to manipulation | From: legit, Reply-To: evil | User awareness |
| Header injection | Multiple From headers | Some mail clients |
Testing Checklist
Spoofing Test Commands
# === Reconnaissance ===
# Full email security check
echo "Checking email security for target.com"
echo "=== MX Records ==="
dig MX target.com +short
echo "=== SPF Record ==="
dig TXT target.com +short | grep spf
echo "=== DMARC Record ==="
dig TXT _dmarc.target.com +short
echo "=== DKIM (try common selectors) ==="
for s in default selector1 selector2 google s1 s2 k1; do
result=$(dig TXT ${s}._domainkey.target.com +short 2>/dev/null)
if [ -n "$result" ]; then
echo "Found: ${s}._domainkey.target.com"
echo "$result"
fi
done
# === Spoofing Tests (authorized testing only) ===
# Using swaks to test spoofing
swaks --to victim@target.com \
--from ceo@target.com \
--server mail.target.com \
--header "Subject: Urgent Request"
# Test with external SMTP (if target accepts)
swaks --to victim@target.com \
--from ceo@target.com \
--server smtp.yourserver.com
# Display name spoofing
swaks --to victim@target.com \
--from '"John Smith CEO" <innocent@attacker.com>' \
--server smtp.yourserver.com
# === Using SET (Social Engineering Toolkit) ===
# setoolkit → Social-Engineering Attacks → Mass Mailer Attack
# === Using Gophish (for phishing assessments) ===
# Configure sending profile with SMTP server
# Create email template
# Launch campaign
Email Security Testing
Comprehensive Testing Workflow
1. DNS Reconnaissance
│
├── MX records
├── SPF record
├── DKIM selectors
└── DMARC policy
│
▼
2. SMTP Enumeration
│
├── Banner grabbing
├── Supported commands
├── User enumeration
└── Open relay test
│
▼
3. Authentication Testing
│
├── SPF validation
├── DKIM verification
└── DMARC alignment
│
▼
4. Spoofing Tests
│
├── Direct spoofing
├── Subdomain spoofing
└── Display name spoofing
│
▼
5. Report Findings
Testing Checklist
| Test | Tool | Pass Criteria |
|---|
| MX records exist | dig MX | Records returned |
| SPF configured | dig TXT | v=spf1 present |
| SPF uses -all | dig TXT | Ends with -all |
| DKIM configured | dig TXT selector._domainkey | Key present |
| DKIM key ≥1024 bit | openssl | RSA 1024+ |
| DMARC configured | dig TXT _dmarc | v=DMARC1 present |
| DMARC p=reject | dig TXT _dmarc | p=reject |
| No open relay | nmap script | Relay denied |
| VRFY disabled | SMTP test | 502/252 response |
| STARTTLS supported | SMTP EHLO | STARTTLS in response |
| Tool | Purpose | Install |
|---|
| swaks | Swiss army knife for SMTP | apt install swaks |
| smtp-user-enum | User enumeration | apt install smtp-user-enum |
| nmap smtp scripts | SMTP scanning | Built into nmap |
| dnsrecon | DNS enumeration | apt install dnsrecon |
| emkei.cz | Online spoofing test | Web-based |
| Tool | Purpose | Type |
|---|
| Gophish | Phishing campaigns | Open source |
| King Phisher | Phishing campaigns | Open source |
| SET | Social engineering | Open source |
| Evilginx2 | Phishing + MFA bypass | Open source |
| Tool | URL | Use |
|---|
| MXToolbox | mxtoolbox.com | Full email check |
| Mail Tester | mail-tester.com | Deliverability test |
| DMARC Analyzer | dmarcanalyzer.com | DMARC check |
| Learn DMARC | learndmarc.com | Interactive learning |
Practice Labs
Beginner
| Resource | Focus |
|---|
| TryHackMe - Phishing | Email basics |
| HackTheBox Academy | SMTP enumeration |
| OverTheWire | Network services |
| Resource | Focus |
|---|
| VulnHub mail machines | Full exploitation |
| Gophish lab | Campaign setup |
| Custom SMTP server | Understand protocols |
Set Up Practice Environment
# Install local mail server for testing
# Using hMailServer (Windows) or Postfix (Linux)
# Postfix quick setup
apt install postfix
# Choose "Internet Site"
# Configure /etc/postfix/main.cf
# Test locally
swaks --to test@localhost --server localhost
# Set up Gophish for phishing practice
wget https://github.com/gophish/gophish/releases/latest/download/gophish-linux-64bit.zip
unzip gophish-linux-64bit.zip
./gophish
# Access at https://localhost:3333
Glossary
| Term | Definition |
|---|
| BEC | Business Email Compromise |
| DKIM | DomainKeys Identified Mail (signature) |
| DMARC | Domain-based Message Authentication |
| Envelope From | MAIL FROM address (for SPF) |
| Header From | Displayed From address |
| IMAP | Internet Message Access Protocol |
| MDA | Mail Delivery Agent |
| MTA | Mail Transfer Agent |
| MUA | Mail User Agent (client) |
| MX | Mail Exchanger record |
| Open Relay | Server that forwards mail for anyone |
| POP3 | Post Office Protocol v3 |
| Selector | DKIM identifier in DNS |
| SMTP | Simple Mail Transfer Protocol |
| SPF | Sender Policy Framework |
| STARTTLS | Upgrade connection to TLS |
What’s Next?
Now that you understand email security:
| Topic | Description | Link |
|---|
| DNS Deep Dive | MX and TXT records | DNS Guide |
| Social Engineering | Phishing techniques | Coming Soon |
| Web App Pentesting | Web-based attacks | Web App Guide |
| Authentication Flows | Auth mechanisms | Auth Flows Guide |
Summary
Email security is critical for penetration testing:
- SMTP - Know the protocol, test for open relay, user enumeration
- SPF - Check for existence and strict qualifier (-all)
- DKIM - Verify signature and key strength
- DMARC - Check policy enforcement (p=reject)
- Headers - Analyze for authentication results and routing
- Spoofing - Test based on security configuration
Key Findings to Report:
- Missing SPF/DKIM/DMARC
- Weak SPF qualifier (~all)
- DMARC p=none
- Missing subdomain policies
- Open relay
- VRFY/EXPN enabled
- Successful spoofing tests
Found this guide helpful? Check out the other posts in the SecureKhan penetration testing series.