Simple Mail Transfer Protocol (SMTP) has been the backbone of email delivery since 1982. Despite its age, SMTP remains the standard protocol for sending email across the internet. Understanding SMTP is essential for anyone building or maintaining email-sending applications.
This guide covers SMTP from the ground up - the protocol itself, configuration options, security considerations, and best practices for integration.
Understanding SMTP
What SMTP Does
SMTP handles the transmission of email from sender to recipient. When you hit "send" on an email:
- Your email client connects to an SMTP server
- The server accepts the message and determines the destination
- The server relays the message to the recipient's mail server
- The recipient's server delivers to their mailbox
SMTP only handles sending and relaying. Retrieving email uses different protocols (IMAP, POP3).
SMTP Protocol Basics
SMTP uses a simple text-based command-response protocol:
EHLO sender.example.com
250-mail.example.org Hello sender.example.com
250-SIZE 35882577
250-AUTH LOGIN PLAIN
250 OK
AUTH LOGIN
334 VXNlcm5hbWU6
dXNlckBleGFtcGxlLmNvbQ==
334 UGFzc3dvcmQ6
cGFzc3dvcmQ=
235 Authentication successful
MAIL FROM:
250 OK
RCPT TO:
250 OK
DATA
354 Start mail input
Subject: Test Email
From: user@example.com
To: recipient@example.org
This is a test message.
.
250 OK
QUIT
221 Bye
Key SMTP Commands
- EHLO/HELO: Initiates the session and identifies the sender
- AUTH: Authenticates the sender
- MAIL FROM: Specifies the sender address (envelope from)
- RCPT TO: Specifies recipient address(es)
- DATA: Begins message content transmission
- QUIT: Ends the session
SMTP Response Codes
Response codes indicate success or failure:
- 2xx: Success (250 = OK, 235 = Auth successful)
- 3xx: Continue (354 = Start mail input)
- 4xx: Temporary failure (421 = Service unavailable, 450 = Mailbox unavailable)
- 5xx: Permanent failure (550 = User not found, 553 = Invalid address)
SMTP Ports and Security
Standard Ports
- Port 25: Server-to-server relay (often blocked by ISPs for client use)
- Port 465: SMTPS (implicit TLS, deprecated but still used)
- Port 587: Submission (recommended for client-to-server)
- Port 2525: Alternative when 587 is blocked
Encryption Options
STARTTLS
STARTTLS upgrades a plain connection to encrypted:
- Client connects on port 587 (unencrypted)
- Client sends EHLO, server advertises STARTTLS
- Client sends STARTTLS command
- TLS negotiation occurs
- Connection continues encrypted
Implicit TLS (SMTPS)
Connection is encrypted from the start (port 465). No upgrade needed - TLS handshake happens immediately upon connection.
Which to Use?
Port 587 with STARTTLS is the modern standard for mail submission. Port 465 with implicit TLS is making a comeback due to its simplicity. Either is acceptable; avoid unencrypted connections.
Authentication Methods
- PLAIN: Username and password sent base64 encoded (only use over TLS)
- LOGIN: Similar to PLAIN, slightly different encoding
- CRAM-MD5: Challenge-response, doesn't send password directly
- OAUTH2: Token-based, used by Gmail and others
Configuring SMTP in Applications
Common Configuration Parameters
SMTP_HOST=smtp.getmailer.com
SMTP_PORT=587
SMTP_USER=apikey
SMTP_PASS=your-api-key
SMTP_SECURE=STARTTLS
Node.js (Nodemailer)
const nodemailer = require('nodemailer');
const transporter = nodemailer.createTransport({
host: 'smtp.getmailer.com',
port: 587,
secure: false, // true for 465, false for other ports
auth: {
user: 'apikey',
pass: 'your-api-key'
}
});
await transporter.sendMail({
from: 'sender@example.com',
to: 'recipient@example.com',
subject: 'Hello',
text: 'Plain text body',
html: 'HTML body
'
});
Python (smtplib)
import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
msg = MIMEMultipart('alternative')
msg['Subject'] = 'Hello'
msg['From'] = 'sender@example.com'
msg['To'] = 'recipient@example.com'
text = MIMEText('Plain text body', 'plain')
html = MIMEText('HTML body
', 'html')
msg.attach(text)
msg.attach(html)
with smtplib.SMTP('smtp.getmailer.com', 587) as server:
server.starttls()
server.login('apikey', 'your-api-key')
server.send_message(msg)
PHP (PHPMailer)
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\SMTP;
$mail = new PHPMailer(true);
$mail->isSMTP();
$mail->Host = 'smtp.getmailer.com';
$mail->SMTPAuth = true;
$mail->Username = 'apikey';
$mail->Password = 'your-api-key';
$mail->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS;
$mail->Port = 587;
$mail->setFrom('sender@example.com');
$mail->addAddress('recipient@example.com');
$mail->Subject = 'Hello';
$mail->Body = 'HTML body
';
$mail->AltBody = 'Plain text body';
$mail->send();
SMTP Error Handling
Connection Errors
- Connection timeout: Server unreachable, check host/port
- Connection refused: Port blocked or server not running
- SSL/TLS errors: Certificate issues or TLS version mismatch
Authentication Errors
- 535: Authentication failed - check credentials
- 530: Authentication required - enable auth in your client
Sending Errors
- 550: Various - user not found, policy rejection
- 552: Message size exceeded
- 553: Invalid sender address
- 554: Transaction failed
Retry Logic
Implement exponential backoff for temporary failures (4xx codes):
const delays = [1000, 5000, 30000, 120000]; // ms
async function sendWithRetry(message, attempt = 0) {
try {
return await sendEmail(message);
} catch (error) {
if (error.responseCode >= 400 && error.responseCode < 500 && attempt < delays.length) {
await sleep(delays[attempt]);
return sendWithRetry(message, attempt + 1);
}
throw error;
}
}
SMTP vs API
When to Use SMTP
- Legacy application integration
- Applications with built-in SMTP support
- Simple use cases without need for advanced features
- When you want provider portability
When to Use API
- Modern applications with API-first design
- Need for webhooks and event notifications
- Advanced features (templates, scheduling, etc.)
- Better error information and debugging
- Higher throughput requirements
Performance Considerations
SMTP requires a TCP connection per session. For high-volume sending:
- Reuse connections for multiple messages when possible
- Consider connection pooling
- APIs typically offer better throughput due to HTTP/2 multiplexing
SMTP Security Best Practices
Always Use Encryption
Never send credentials over unencrypted connections. Use TLS for all SMTP communication.
Secure Credential Storage
- Don't hardcode credentials in source code
- Use environment variables or secrets management
- Rotate credentials periodically
Validate Certificates
Don't disable certificate validation in production. If you have certificate issues, fix them properly.
Use API Keys Over Passwords
If your provider supports it, use API keys for SMTP auth. They can be revoked independently and scoped to specific permissions.
Troubleshooting SMTP
Testing Connectivity
# Test basic connectivity
telnet smtp.example.com 587
# Test with OpenSSL for TLS
openssl s_client -connect smtp.example.com:465
openssl s_client -starttls smtp -connect smtp.example.com:587
Enable Debug Logging
Most SMTP libraries support debug mode that logs the full SMTP conversation. Enable this when troubleshooting.
Check DNS
Ensure your server can resolve the SMTP host. DNS issues are a common cause of connection failures.
Conclusion
SMTP is a mature, well-understood protocol that remains relevant for email delivery. Understanding how it works helps you configure it correctly, troubleshoot issues, and make informed decisions about when to use SMTP vs. API-based sending.
GetMailer supports both SMTP and API-based sending. Use SMTP for easy integration with existing applications, or our REST API for modern applications requiring webhooks, templates, and advanced features.
