guides
Sending long emails in Python without breaking delivery
Use Python and smtplib to send long email content safely with MIME structure, size controls, and transport-aware formatting.
Long emails fail for predictable reasons:
- message size too large after encoding,
- malformed MIME structure,
- poor line wrapping for transport,
- or weak retries around temporary SMTP failures.
This guide focuses on the part teams usually skip: transport-aware structure.
What "long email" means technically
Length issues are not only about character count.
- HTML templates with inline CSS increase payload quickly.
- Base64 attachments expand message size significantly.
- Poorly wrapped plain text can trigger transport inconsistencies.
If your emails include media-heavy content, treat size as an explicit test condition.
Recommended Python stack
Use Python's standard library first:
smtplibfor SMTP session and delivery.email.mime.multipart.MIMEMultipartfor structured messages.email.mime.text.MIMETextfor text and HTML parts.email.mime.base.MIMEBasefor attachments.
This gives enough control for production-safe long messages.
Structure messages for reliability
- Build
multipart/alternativefor text + HTML bodies. - Add attachments only when required.
- Set explicit charset (
utf-8) for body parts. - Keep subject, from, and recipient headers normalized.
SMTP session controls to include
- TLS/STARTTLS enabled by default.
- Explicit timeout.
- Authentication error handling (535/530).
- Retry logic for temporary 4xx responses.
- Observability around message ID and send latency.
Example code
Imports
import smtplib, ssl
import os
from os.path import basename
# get an api key at https://app.mailslurp.com/sign-up
import mailslurp_client
from mailslurp_client import CreateInboxDto
api_key = os.environ.get('API_KEY')
assert api_key is not None
# create a mailslurp configuration
configuration = mailslurp_client.Configuration()
configuration.api_key['x-api-key'] = api_key
context = ssl.create_default_context()
Send long message example
from email.mime.text import MIMEText
with mailslurp_client.ApiClient(configuration) as api_client:
inbox_controller = mailslurp_client.InboxControllerApi(api_client)
inbox1 = inbox_controller.create_inbox_with_options(CreateInboxDto(inbox_type="SMTP_INBOX"))
inbox2 = inbox_controller.create_inbox_with_options(CreateInboxDto(inbox_type="SMTP_INBOX"))
smtp_access = inbox_controller.get_imap_smtp_access(inbox_id=inbox1.id)
# create long message
text = ""
for i in range(1, 42):
text += "This is line {}\n".format(i)
context = ssl.create_default_context()
try:
server = smtplib.SMTP(smtp_access.secure_smtp_server_host, smtp_access.secure_smtp_server_port)
server.ehlo()
server.starttls(context=context)
server.ehlo("test_client")
server.login(smtp_access.smtp_username, smtp_access.smtp_password)
# recipients
subject = "A message with a 41-line body"
from_address = inbox1.email_address
to_address = inbox2.email_address
# send message
message = MIMEText(text)
# Set the email subject and 'From' and 'To' headers
message["Subject"] = subject
message["From"] = from_address
message["To"] = to_address
server.sendmail(from_address, to_address, message.as_string())
# now fetch email from inbox2
wait_for_controller = mailslurp_client.WaitForControllerApi(api_client)
email = wait_for_controller.wait_for_latest_email(inbox_id=inbox2.id)
assert email.subject == subject
# assert sent all lines
assert "This is line 41" in email.body
finally:
server.quit()
Pre-send checklist for long messages
| Check | Why it matters |
|---|---|
| Rendered size budget | Prevent provider rejections and clipping |
| Text fallback present | Improve accessibility and client compatibility |
| Links/token format validated | Catch broken flow behavior before delivery |
| Attachment MIME type checked | Avoid client-side corruption |
| Delivery timeout defined | Prevent hidden queue or throttling failures |
When to move beyond raw SMTP scripts
If you need repeatable release checks, add API-based inbox validation:
That combination catches both send-time and receive-time regressions.