Email is one of the oldest and still most heavily used applications on the Internet, predating the World Wide Web itself. Behind every email you send or receive is a coordinated system of specialized software components — Mail User Agents, Mail Transfer Agents, and Mail Delivery Agents — working together across protocols like SMTP, IMAP, and POP3. This article explains, from first principles, how email actually works, the different software roles involved, and how to send email from a Linux system, both interactively and programmatically.
The Building Blocks of Email
flowchart LR
A[Sender's MUA] --> B[Sender's MTA]
B --> C[Recipient's MTA]
C --> D[MDA]
D --> E[Recipient's Mailbox]
E --> F[Recipient's MUA - IMAP/POP3]
MUA — Mail User Agent
The MUA is the software a human actually interacts with to read and compose email. Examples:
- Graphical MUAs: Thunderbird, Outlook, Apple Mail, Gmail’s web interface
- Command-line MUAs (Linux):
mutt,mail/mailx,alpine
MTA — Mail Transfer Agent
The MTA is server software responsible for routing and relaying email between servers using SMTP (Simple Mail Transfer Protocol). Examples:
- Postfix (most common on modern Linux servers)
- Exim (default on many Debian-based systems)
- Sendmail (historic, still found on legacy systems)
MDA — Mail Delivery Agent
The MDA takes an incoming message from the MTA and actually delivers it into a specific user’s mailbox, sometimes applying filtering rules along the way. Examples:
- Dovecot (also commonly serves as an IMAP/POP3 server)
- Procmail (classic filtering MDA)
Retrieval Protocols: IMAP and POP3
Once mail is delivered to a mailbox, the recipient’s MUA retrieves it using either:
- IMAP (Internet Message Access Protocol) — mail stays on the server, synchronized across multiple devices (the modern standard)
- POP3 (Post Office Protocol v3) — mail is downloaded to a single device, often removed from the server afterward (largely legacy today)
Comparison Table: Email Component Roles
| Component | Role | Protocol Used | Example Software |
|---|---|---|---|
| MUA | User composes/reads mail | SMTP (to send), IMAP/POP3 (to receive) | Thunderbird, mutt, Gmail |
| MTA | Routes mail between servers | SMTP | Postfix, Exim, Sendmail |
| MDA | Delivers mail into a mailbox | Local delivery / LMTP | Dovecot, Procmail |
| Retrieval server | Lets MUA fetch stored mail | IMAP / POP3 | Dovecot, Courier |
The Full Journey of an Email
Imagine Alice (alice@companyA.com) sends an email to Bob (bob@companyB.com):
sequenceDiagram
participant Alice as Alice's MUA
participant MTA_A as companyA MTA
participant DNS
participant MTA_B as companyB MTA
participant Bob as Bob's MUA
Alice->>MTA_A: SMTP: Send message
MTA_A->>DNS: MX record lookup for companyB.com
DNS-->>MTA_A: mail.companyB.com
MTA_A->>MTA_B: SMTP: Relay message
MTA_B->>MTA_B: MDA delivers to Bob's mailbox
Bob->>MTA_B: IMAP: Fetch new messages- Alice’s MUA sends the message to her organization’s outgoing MTA via SMTP.
- That MTA looks up companyB.com’s MX (Mail Exchange) DNS record to find the responsible mail server.
- The sending MTA relays the message to the receiving MTA over SMTP (typically port 25 between servers).
- The receiving MTA hands the message to an MDA, which delivers it into Bob’s mailbox.
- Bob’s MUA later retrieves the message using IMAP (or POP3).
Checking MX Records (DNS for Mail Routing)
dig MX companyB.comExample output:
companyB.com. 3600 IN MX 10 mail.companyB.com.The number (10) is a priority value — lower numbers are preferred when multiple MX records exist.
Sending Email From the Linux Command Line
Using mail (mailx)
echo "This is the message body." | mail -s "Test Subject" recipient@example.comInstall if not present:
sudo apt install mailutils # Debian/Ubuntu
sudo dnf install mailx # RHEL/FedoraSending With Attachments
echo "See attached report." | mail -s "Weekly Report" -A report.pdf recipient@example.comUsing sendmail Directly
sendmail recipient@example.com <<EOF
Subject: Direct Sendmail Test
From: admin@myserver.com
This message was sent using the sendmail command directly.
EOFUsing mutt for Interactive Use
mutt -s "Subject line" recipient@example.commutt opens your configured editor to compose the body, and supports attachments, address books, and IMAP/SMTP account configuration for a full terminal-based email experience.
Sending Email Programmatically With Python
import smtplib
from email.mime.text import MIMEText
msg = MIMEText("This is the body of the email.")
msg['Subject'] = 'Automated Report'
msg['From'] = 'reports@example.com'
msg['To'] = 'admin@example.com'
with smtplib.SMTP('smtp.example.com', 587) as server:
server.starttls()
server.login('reports@example.com', 'app-specific-password')
server.send_message(msg)
print("Email sent successfully.")This is a common pattern for server monitoring scripts that email alerts automatically.
Configuring Postfix as a Basic Outgoing MTA
For a server that just needs to send outgoing notification emails (not receive), a minimal Postfix “satellite” configuration works well.
Step 1: Install Postfix
sudo apt install postfixDuring installation, choose “Internet Site” or “Satellite system” depending on your setup.
Step 2: Key settings in /etc/postfix/main.cf
myhostname = mail.example.com
relayhost = [smtp.relay-provider.com]:587
smtp_sasl_auth_enable = yes
smtp_sasl_password_maps = hash:/etc/postfix/sasl_passwd
smtp_sasl_security_options = noanonymous
smtp_tls_security_level = encryptStep 3: Configure SASL credentials for the relay
echo "[smtp.relay-provider.com]:587 username:password" | sudo tee /etc/postfix/sasl_passwd
sudo postmap /etc/postfix/sasl_passwd
sudo chmod 600 /etc/postfix/sasl_passwd*Step 4: Restart Postfix
sudo systemctl restart postfixStep 5: Test
echo "Test message" | mail -s "Postfix relay test" you@example.comReal-World Use Case: Automated Backup Notification
#!/bin/bash
BACKUP_LOG="/var/log/backup.log"
if tar -czf /backups/data-$(date +%F).tar.gz /data > "$BACKUP_LOG" 2>&1; then
echo "Backup completed successfully on $(date)" | mail -s "Backup Success" admin@example.com
else
cat "$BACKUP_LOG" | mail -s "Backup FAILED" admin@example.com
fi
Comparison: SMTP vs. IMAP vs. POP3
| Protocol | Purpose | Default Port | Mail Storage |
|---|---|---|---|
| SMTP | Sending/relaying mail | 25 (server-to-server), 587 (submission) | N/A |
| IMAP | Retrieving mail, synced across devices | 143 (or 993 for IMAPS) | Stays on server |
| POP3 | Retrieving mail, single device | 110 (or 995 for POP3S) | Typically downloaded and removed |
Best Practices
- Always use authenticated, encrypted submission (port 587 with STARTTLS) rather than legacy unauthenticated relaying on port 25, which is heavily blocked and abused.
- Set up SPF, DKIM, and DMARC DNS records for any domain sending mail, to improve deliverability and reduce the chance of being marked as spam.
- Use a reputable relay/SMTP provider for application-generated email (transactional email services) rather than running your own outbound mail server from scratch, unless you have the expertise to manage IP reputation.
- Never hard-code SMTP credentials in scripts — use environment variables, secret managers, or app-specific passwords with limited scope.
- Monitor mail queues (
postqueue -pfor Postfix) to catch delivery failures early. - Rate-limit automated email alerts to avoid flooding inboxes during incident storms.
Troubleshooting
Problem: Email sent but never arrives
Check the mail queue and logs:
postqueue -p
sudo tail -f /var/log/mail.logProblem: Relay access denied
The MTA isn’t configured to relay for your domain/IP. Check mynetworks and relay authentication settings in Postfix’s main.cf.
Problem: Mail marked as spam by recipients
Verify SPF, DKIM, and DMARC records are correctly configured:
dig TXT example.com
dig TXT _dmarc.example.comProblem: mail command not found
Install the mail utilities package:
sudo apt install mailutilsProblem: Python smtplib connection times out
Check that the SMTP port isn’t blocked by a firewall or your ISP (many residential/cloud ISPs block outbound port 25 by default; use 587 instead):
telnet smtp.example.com 587Conclusion
Email is a distributed system built from clearly separated roles — the MUA you interact with, the MTA that routes messages between servers, and the MDA/retrieval protocols (IMAP/POP3) that get mail into your inbox. Understanding this architecture, along with practical Linux tools like mail, sendmail, mutt, Postfix, and Python’s smtplib, allows you to both use email effectively as a system administrator and build reliable automated notification systems for scripts, monitoring, and backups.