5. Address Resolution and Mail Handling
This section describes how SMTP clients determine where to deliver mail messages and how they should handle the delivery process.
5.1. Locating the Target Host
When an SMTP client has mail to deliver to a particular domain, it must determine the appropriate destination host(s). This process uses the Domain Name System (DNS) and follows these steps:
Step 1: Look up MX Records
Query DNS for Mail eXchanger (MX) records for the destination domain:
$ dig example.com MX
;; ANSWER SECTION:
example.com. 3600 IN MX 10 mail1.example.com.
example.com. 3600 IN MX 20 mail2.example.com.
example.com. 3600 IN MX 30 mail3.example.com.
Step 2: Sort by Priority
Sort MX records by priority (lower number = higher priority):
mail1.example.com(priority 10)mail2.example.com(priority 20)mail3.example.com(priority 30)
Step 3: Attempt Delivery
Try to connect to each host in priority order:
- Attempt connection to highest priority (lowest number) MX
- If connection fails, try next priority level
- Continue until successful or all MX hosts exhausted
Step 4: Fallback to A/AAAA Records
If no MX records exist, treat the domain itself as the mail server:
- Look up A record (IPv4) or AAAA record (IPv6)
- Attempt direct connection to that IP address
Important: If MX records exist but all fail, do NOT fall back to A/AAAA records.
Detailed Algorithm
1. Query MX records for destination domain
2. If MX records found:
a. Remove any MX pointing to "." (null MX)
b. Sort remaining MX by priority
c. For each priority level (starting with lowest number):
i. Resolve all MX hosts at this priority to IP addresses
ii. Randomly order hosts at same priority
iii. Try connecting to each host
iv. If connection succeeds, deliver mail
v. If all hosts at this priority fail, try next priority
d. If all MX hosts fail, defer delivery (temporary failure)
3. If no MX records found:
a. Query A/AAAA records for domain
b. Try connecting directly to domain's IP
c. If connection fails, defer delivery
4. If domain does not resolve:
- Return permanent failure (5xx code)
Example Scenarios
Scenario 1: Standard MX Resolution
Domain: example.com
MX Records:
10 mail1.example.com
20 mail2.example.com
Process:
1. Try mail1.example.com → Success, deliver mail
Scenario 2: Primary MX Fails
MX Records:
10 mail1.example.com (down)
20 mail2.example.com
Process:
1. Try mail1.example.com → Connection failed
2. Try mail2.example.com → Success, deliver mail
Scenario 3: No MX Records
Domain: smallcompany.example
No MX records found
Process:
1. Look up A record for smallcompany.example
2. Connect directly to IP address
3. Deliver mail
Scenario 4: Null MX Record
Domain: nomail.example
MX Record:
0 .
Meaning: This domain does not accept mail
Process: Return permanent failure (556 or 550)
Best Practices
- Respect TTL: Cache DNS results according to TTL values
- Connection Timeouts: Use reasonable timeouts (e.g., 5 minutes for initial connection)
- Retry Logic: For transient failures (4xx), retry periodically
- Load Balancing: For same-priority MX records, randomize selection
- IPv6 Support: Try both A and AAAA records
- Error Handling: Distinguish between temporary and permanent failures
Common Errors
Error 1: Falling back to A record when MX exists but fails
❌ Wrong:
MX records exist but all fail → Try A record
✅ Correct:
MX records exist but all fail → Defer delivery (temporary failure)
Error 2: Not handling null MX properly
❌ Wrong:
MX: 0 . → Ignore and try A record
✅ Correct:
MX: 0 . → Domain explicitly rejects mail, return permanent error
5.2. IPv6 and MX Records
When resolving MX hostnames, clients should:
- Query both A (IPv4) and AAAA (IPv6) records
- Prefer IPv6 if both available (implementation-dependent)
- Fall back to IPv4 if IPv6 connection fails
Example:
mail.example.com has:
A 192.0.2.1
AAAA 2001:db8::1
Process:
1. Try IPv6: 2001:db8::1
2. If fails, try IPv4: 192.0.2.1
IPv6 Address Literals
SMTP supports IPv6 address literals in MAIL FROM and RCPT TO:
Format: user@[IPv6:2001:db8::1]
Example:
C: MAIL FROM:`<sender@[IPv6:2001:db8::1]>`
S: 250 Ok
Dual-Stack Considerations
- Happy Eyeballs: Try IPv6 and IPv4 in parallel with slight delay
- Timeout Handling: Don't let IPv6 attempts delay IPv4 too long
- Preference: Allow configuration of IPv4/IPv6 preference
- Fallback: Always have IPv4 fallback for compatibility