18.2. SMTP
Table of Contents
What SMTP Is
SMTP stands for Simple Mail Transfer Protocol. It is the main protocol used to send emails across the internet.
When your backend application sends an email, it almost always talks to an SMTP server. Your code does not push a message directly into someone’s inbox. Instead, it gives the message to an SMTP server, and that server is responsible for delivering the message to the recipient’s mail server.
You can think of SMTP as the “postal service protocol” for email. It defines:
- How a client connects to a mail server
- How the client identifies the sender and recipients
- How the message content is transferred
- How errors are reported
Modern email delivery also involves security, spam checks, and other protocols, but SMTP is the foundation for sending.
Key idea: SMTP is used for sending and relaying email messages between mail servers. It is not used by clients to read email. Reading usually uses POP3 or IMAP.
SMTP Roles: Client and Server
In SMTP, there are two main roles:
| Role | Also called | Typical example |
|---|---|---|
| SMTP client | Mail User Agent / Mail Transfer | Your backend app, a library like smtplib, or a mail relay |
| SMTP server | Mail Transfer Agent (MTA) | Gmail’s SMTP server, Postfix, Sendmail, Mailgun, etc. |
Your backend behaves as an SMTP client:
- Connects to an SMTP server (for example
smtp.gmail.comon port 587). - Authenticates with username and password or some other method.
- Sends details about the email and the message content.
- Disconnects.
The SMTP server then takes over:
- It looks at the recipient’s domain (
@example.com). - It finds the correct mail server for that domain (using DNS MX records).
- It tries to deliver the message to that server using SMTP again.
SMTP Ports
SMTP uses specific TCP ports.
Common SMTP ports:
| Port | Use case | Encryption style |
|---|---|---|
| 25 | Server to server SMTP | Often blocked for clients |
| 465 | “SMTPS” legacy encrypted SMTP | Implicit TLS from the start |
| 587 | Submission port for clients | Start unencrypted, then STARTTLS |
For backend applications, you usually use:
- Port 587 for sending with STARTTLS
- Sometimes port 465 if the provider offers it as “secure SMTP”
Rule: For application email sending, use the submission ports (587 or 465), not port 25, and always use encryption (TLS) if available.
Example configuration you might see:
SMTP_HOST=smtp.mailprovider.com
SMTP_PORT=587
SMTP_USERNAME=my_app@example.com
SMTP_PASSWORD=super-secret
SMTP_USE_TLS=trueThe Basic SMTP Conversation
SMTP is a text-based protocol. The client and server exchange lines of text.
A simplified example:
- Client connects to server on port 587.
- Server:
220 smtp.example.com ESMTP Ready - Client:
EHLO myapp.local - Server: responds with capabilities (for example
STARTTLS,AUTH LOGIN). - Client:
STARTTLS(if using TLS upgrade). - TLS handshake happens, connection becomes encrypted.
- Client:
EHLO myapp.localagain (now inside TLS). - Client:
AUTH LOGINor another auth method, sends credentials. - Client:
MAIL FROM:<no-reply@myapp.com> - Client:
RCPT TO:<user@example.org> - Client:
DATA - Client sends headers and body, ends with a line containing only a single dot:
Subject: Welcome
Hello user!
.- Server:
250 Message accepted for delivery - Client:
QUIT - Server:
221 Bye
Each step uses simple commands and responses.
Common SMTP Commands
| Command | Meaning |
|---|---|
HELO / EHLO | Say hello, identify the client |
STARTTLS | Upgrade the connection to TLS |
AUTH | Authenticate (LOGIN, PLAIN, etc.) |
MAIL FROM | Set the envelope sender |
RCPT TO | Add a recipient |
DATA | Start sending the message content |
QUIT | End the session |
You rarely need to type these manually. Libraries handle them, but understanding them helps debugging.
SMTP vs Email Message Format
There are two related but different parts:
- SMTP envelope
MAIL FROM:<...>andRCPT TO:<...>- Used for delivery and bounce handling
- Not always visible to the user
- Message itself (the content inside
DATA) - Has its own headers (like
From:,To:,Subject:) - Contains the body (text, HTML, attachments)
It is possible for the SMTP envelope sender to be different from the From: header that users see. For example, mailing lists often do this.
Important: The envelope addresses (MAIL FROM, RCPT TO) control delivery. The From: and To: headers control what the recipient sees. They are not guaranteed to match.
SMTP Response Codes
SMTP servers respond with numeric codes similar to HTTP, but with 3 digits.
General meaning:
| First digit | Meaning |
|---|---|
| 2xx | Success |
| 3xx | More information needed |
| 4xx | Temporary failure (try again later) |
| 5xx | Permanent failure (do not retry as-is) |
Examples:
| Code | Meaning |
|---|---|
| 220 | Service ready |
| 221 | Service closing transmission channel |
| 235 | Authentication successful |
| 250 | Requested action completed |
| 354 | Start mail input (after DATA) |
| 421 | Service not available, closing |
| 450 | Mailbox unavailable, temporary |
| 550 | Mailbox unavailable, permanent |
In a backend app, your library will expose these as exceptions or error messages, but understanding 4xx vs 5xx helps decide whether you should retry.
SMTP Authentication
Most SMTP servers require authentication before you can send emails, especially when you connect from the internet as a client.
Typical methods:
- Username + password over a TLS protected connection
- Specialized methods like OAuth 2.0 tokens with some providers
If you try to send without authentication, you might see errors like:
530 5.7.0 Authentication required550 5.7.1 Relaying denied
SMTP AUTH is negotiated after EHLO. The client sends:
AUTH LOGINThen exchanges credentials (usually Base64 encoded) inside the TLS tunnel.
Rule: Never send SMTP credentials without TLS. If you see STARTTLS in the server features, use it. For ports like 465, TLS usually starts immediately.
SMTP Security: TLS and STARTTLS
SMTP by itself is plaintext. To secure it, we use TLS.
Two common patterns:
| Method | Port | How encryption starts |
|---|---|---|
| Implicit TLS | 465 | TLS handshake happens immediately on connect |
| STARTTLS (explicit) | 587 | Start plaintext, then issue STARTTLS |
Sequence with STARTTLS:
- Connect on port 587.
EHLO.- Server advertises
STARTTLS. - Client sends
STARTTLS. - TLS handshake happens.
- Client sends
EHLOagain in the encrypted channel. - Client authenticates and sends email.
Backends usually only need to set a parameter like use_tls or use_ssl and the library handles the details.
SMTP in Backend Applications
In backend development, you usually do not interact with SMTP directly. Instead, you:
- Choose a mail provider:
- Gmail (with app passwords or OAuth)
- Services like SendGrid, Mailgun, Amazon SES
- Your own SMTP server (Postfix, Exim, etc.)
- Configure your backend with:
- SMTP host and port
- Credentials
- Whether to use TLS or SSL (implicit TLS)
- From address and name
- Use a library (for example in Python) to:
- Build the message (plain text or HTML)
- Attach files if needed
- Send via SMTP
Example high-level flow in pseudocode:
smtp = SMTP(
host="smtp.mailprovider.com",
port=587,
tls=True,
username="no-reply@myapp.com",
password="secret",
)
msg = EmailMessage(
from_="MyApp <no-reply@myapp.com>",
to="user@example.org",
subject="Welcome to MyApp",
body="Thanks for signing up!"
)
smtp.send(msg)Under the hood this does the full SMTP conversation you saw before.
Common SMTP Errors for Backends
When integrating SMTP, these are common issues:
| Problem | Typical cause |
|---|---|
| Connection refused / timeout | Wrong host or port, firewall, provider blocking |
| Authentication failed | Wrong username/password, account not allowed |
535 5.7.8 Authentication ... | Using wrong auth mechanism or invalid credentials |
550 5.7.1 Relaying denied | Not authenticated, or trying to send from/to disallowed addresses |
552 5.3.4 Message size exceeds | Email too large (attachments) |
421 or 450 temporary errors | Provider rate limiting, remote server issues |
Your backend should:
- Log SMTP errors with enough detail
- Decide when to retry (for 4xx) and when to fail permanently (for 5xx)
- Potentially send messages through a background job system, not in the main request
SMTP vs Email APIs
Many modern email providers give you two options:
- Raw SMTP
- You configure SMTP host, port, username, password.
- Use standard SMTP libraries.
- HTTP API
- You call a JSON REST API endpoint like
POST /sendwith an API key. - Provider sends the email for you.
Comparison:
| Aspect | SMTP | HTTP Email API |
|---|---|---|
| Protocol | SMTP over TCP (text commands) | HTTP / HTTPS (JSON payloads) |
| Libraries | SMTP libraries, built into many languages | HTTP clients, often easier to debug |
| Features | Basic sending, standard | Often richer (templates, tracking) |
| Debugging | SMTP logs, codes | HTTP status & JSON responses |
For backend beginners, SMTP is useful to understand conceptually, even if in production you often use a provider’s HTTP API for convenience.
Summary
- SMTP is the core protocol for sending emails between servers.
- Your backend acts as an SMTP client that connects to an SMTP server.
- Common ports are 25 (server to server), 465 (implicit TLS), and 587 (submission with STARTTLS).
- An SMTP conversation uses commands like
EHLO,AUTH,MAIL FROM,RCPT TO,DATA, andQUIT. - There is a difference between the SMTP envelope and the message headers and body.
- SMTP responses use codes where 2xx is success, 4xx is temporary error, and 5xx is permanent error.
- Always use TLS when sending credentials and email content.
- Backend apps typically rely on libraries to speak SMTP, and often use third-party email providers rather than running their own mail servers.
Views: 7
KAHIBARO