While sending plaintext emails through telnet/netcat is well-documented, adding attachments requires MIME (Multipurpose Internet Mail Extensions) protocol knowledge. Let's break down the complete raw SMTP session with attachment handling.
1. A working SMTP server (e.g., smtp.gmail.com on port 587)
2. Base64 encoder (usually built into Linux/macOS)
3. Telnet/netcat with SSL support if required
Here's a full-fledged example using Gmail's SMTP (note: requires app password for authentication):
openssl s_client -connect smtp.gmail.com:587 -starttls smtp
EHLO example.com
AUTH LOGIN
[base64-encoded-username]
[base64-encoded-password]
MAIL FROM: <sender@example.com>
RCPT TO: <recipient@example.com>
DATA
From: "Sender Name" <sender@example.com>
To: "Recipient" <recipient@example.com>
Subject: Test Email with Attachment
MIME-Version: 1.0
Content-Type: multipart/mixed; boundary="BOUNDARY_STRING"
--BOUNDARY_STRING
Content-Type: text/plain; charset=UTF-8
This is the email body text.
--BOUNDARY_STRING
Content-Type: application/octet-stream; name="test.txt"
Content-Transfer-Encoding: base64
Content-Disposition: attachment; filename="test.txt"
[base64-encoded-file-content]
--BOUNDARY_STRING--
.
QUIT
For repeated testing, this bash script automates the process:
#!/bin/bash
SMTP_SERVER="smtp.gmail.com"
SMTP_PORT=587
USERNAME="user@gmail.com"
PASSWORD="app_password"
RECIPIENT="recipient@example.com"
ATTACHMENT="file.txt"
# Generate MIME email
{
echo "From: $USERNAME"
echo "To: $RECIPIENT"
echo "Subject: Automated Test"
echo "MIME-Version: 1.0"
echo "Content-Type: multipart/mixed; boundary=\"MIMEBOUNDARY\""
echo ""
echo "--MIMEBOUNDARY"
echo "Content-Type: text/plain"
echo ""
echo "Automated email body"
echo "--MIMEBOUNDARY"
echo "Content-Type: $(file --mime-type -b $ATTACHMENT)"
echo "Content-Transfer-Encoding: base64"
echo "Content-Disposition: attachment; filename=\"$(basename $ATTACHMENT)\""
echo ""
base64 $ATTACHMENT
echo "--MIMEBOUNDARY--"
} > email.txt
# Send via OpenSSL
openssl s_client -connect $SMTP_SERVER:$SMTP_PORT -starttls smtp -quiet < email.txt
- Ensure proper line endings (CRLF)
- Base64 encode both the authentication credentials and file content
- Include the final boundary with two hyphens (--)
- SMTP servers may have attachment size limits
For servers not requiring TLS (not recommended for production):
(
echo "EHLO example.com"
sleep 1
echo "MAIL FROM: <sender@example.com>"
sleep 1
echo "RCPT TO: <recipient@example.com>"
sleep 1
echo "DATA"
sleep 1
cat email.txt
echo "."
sleep 1
echo "QUIT"
) | nc smtp.example.com 25
While modern tools make email sending trivial, understanding raw SMTP protocol remains valuable for:
- Debugging mail servers
- Testing SMTP services
- Low-level network programming
You'll need:
1. Telnet/netcat installed
2. Base64 encoding tools
3. Valid SMTP server (mx.example.com used here)
4. File to attach (test.txt in examples)
Here's how to compose a MIME-formatted email with attachment:
EHLO yourdomain.com
MAIL FROM: <sender@example.com>
RCPT TO: <recipient@domain.com>
DATA
From: Sender <sender@example.com>
To: Recipient <recipient@domain.com>
Subject: Test with attachment
MIME-Version: 1.0
Content-Type: multipart/mixed; boundary="BOUNDARY_STRING"
--BOUNDARY_STRING
Content-Type: text/plain; charset=UTF-8
This is the email body text.
--BOUNDARY_STRING
Content-Type: application/octet-stream; name="test.txt"
Content-Transfer-Encoding: base64
Content-Disposition: attachment; filename="test.txt"
[base64-encoded-file-content]
--BOUNDARY_STRING--
.
QUIT
For repeated testing, use this bash script:
#!/bin/bash
FILE="test.txt"
BOUNDARY="BOUNDARY_$(date +%s)"
(
echo "EHLO example.com"
echo "MAIL FROM: <sender@example.com>"
echo "RCPT TO: <recipient@domain.com>"
echo "DATA"
echo "From: Sender <sender@example.com>"
echo "To: Recipient <recipient@domain.com>"
echo "Subject: Automated test"
echo "MIME-Version: 1.0"
echo "Content-Type: multipart/mixed; boundary=\"$BOUNDARY\""
echo ""
echo "--$BOUNDARY"
echo "Content-Type: text/plain"
echo ""
echo "This is an automated test email"
echo ""
echo "--$BOUNDARY"
echo "Content-Type: application/octet-stream; name=\"$FILE\""
echo "Content-Transfer-Encoding: base64"
echo "Content-Disposition: attachment; filename=\"$FILE\""
echo ""
base64 "$FILE"
echo "--$BOUNDARY--"
echo "."
echo "QUIT"
) | telnet mx.example.com 25
- Encoding issues: Always use base64 for binary attachments
- Line endings: SMTP requires CRLF (\r\n) line terminators
- Size limits: Many SMTP servers reject large attachments
- Authentication: Modern servers often require STARTTLS
For servers requiring TLS:
openssl s_client -connect smtp.gmail.com:465 -quiet <<EOF
EHLO example.com
AUTH LOGIN
[base64-encoded-username]
[base64-encoded-password]
MAIL FROM: <sender@gmail.com>
RCPT TO: <recipient@domain.com>
DATA
[... rest of MIME message ...]
EOF