Everything you need to send email in Plain.
Project description
plain.email
Send emails from your Plain application using SMTP, console output, or file-based backends.
Overview
You can send emails using the send_mail function for simple cases, or use the EmailMessage and EmailMultiAlternatives classes for more control. For template-based emails, the TemplateEmail class renders HTML templates automatically.
Sending a simple email
The send_mail function is the easiest way to send an email.
from plain.email import send_mail
send_mail(
subject="Welcome!",
message="Thanks for signing up.",
from_email="hello@example.com",
recipient_list=["user@example.com"],
)
To include an HTML version along with the plain text:
send_mail(
subject="Welcome!",
message="Thanks for signing up.",
from_email="hello@example.com",
recipient_list=["user@example.com"],
html_message="<h1>Thanks for signing up!</h1>",
)
Sending HTML emails
For more control over multipart emails, use EmailMultiAlternatives.
from plain.email import EmailMultiAlternatives
email = EmailMultiAlternatives(
subject="Your order confirmation",
body="Your order #123 has been confirmed.",
from_email="orders@example.com",
to=["customer@example.com"],
)
email.attach_alternative("<h1>Order #123 Confirmed</h1>", "text/html")
email.send()
Template-based emails
The TemplateEmail class renders emails from template files. You provide a template name, and it looks for corresponding files in your templates/email/ directory:
email/{template}.html- HTML content (required)email/{template}.txt- Plain text content (optional, falls back to stripping HTML tags)email/{template}.subject.txt- Subject line (optional)
from plain.email import TemplateEmail
email = TemplateEmail(
template="welcome",
context={"user_name": "Alice"},
to=["alice@example.com"],
)
email.send()
With these template files:
<!-- templates/email/welcome.html -->
<h1>Welcome, {{ user_name }}!</h1>
<p>We're glad you're here.</p>
{# templates/email/welcome.subject.txt #}
Welcome to our app, {{ user_name }}!
You can subclass TemplateEmail to customize the template context by overriding get_template_context().
Attachments
You can attach files to any email message.
from plain.email import EmailMessage
email = EmailMessage(
subject="Your report",
body="Please find your report attached.",
to=["user@example.com"],
)
# Attach content directly
email.attach("report.csv", csv_content, "text/csv")
# Or attach a file from disk
email.attach_file("/path/to/report.pdf")
email.send()
Settings
| Setting | Default | Env var |
|---|---|---|
EMAIL_BACKEND |
Required | PLAIN_EMAIL_BACKEND |
EMAIL_DEFAULT_FROM |
Required | PLAIN_EMAIL_DEFAULT_FROM |
EMAIL_DEFAULT_REPLY_TO |
None |
PLAIN_EMAIL_DEFAULT_REPLY_TO |
EMAIL_HOST |
"localhost" |
PLAIN_EMAIL_HOST |
EMAIL_PORT |
587 |
PLAIN_EMAIL_PORT |
EMAIL_HOST_USER |
"" |
PLAIN_EMAIL_HOST_USER |
EMAIL_HOST_PASSWORD |
"" |
PLAIN_EMAIL_HOST_PASSWORD |
EMAIL_USE_TLS |
True |
PLAIN_EMAIL_USE_TLS |
EMAIL_USE_SSL |
False |
PLAIN_EMAIL_USE_SSL |
EMAIL_TIMEOUT |
None |
PLAIN_EMAIL_TIMEOUT |
EMAIL_SSL_CERTFILE |
None |
PLAIN_EMAIL_SSL_CERTFILE |
EMAIL_SSL_KEYFILE |
None |
PLAIN_EMAIL_SSL_KEYFILE |
EMAIL_USE_LOCALTIME |
False |
PLAIN_EMAIL_USE_LOCALTIME |
See default_settings.py for more details.
Email backends
The EMAIL_BACKEND setting controls how emails are sent. Plain includes three backends.
SMTP backend
The default backend sends emails via SMTP.
EMAIL_BACKEND = "plain.email.backends.smtp.EmailBackend"
Console backend
Prints emails to the console instead of sending them. Useful during development.
EMAIL_BACKEND = "plain.email.backends.console.EmailBackend"
FAQs
How do I send to multiple recipients efficiently?
Use send_mass_mail to send multiple messages over a single connection:
from plain.email import send_mass_mail
messages = (
("Subject 1", "Body 1", "from@example.com", ["to1@example.com"]),
("Subject 2", "Body 2", "from@example.com", ["to2@example.com"]),
)
send_mass_mail(messages)
How do I reuse a connection for multiple emails?
Use the backend as a context manager:
from plain.email import get_connection, EmailMessage
with get_connection() as connection:
for user in users:
email = EmailMessage(
subject="Hello",
body="Hi there!",
to=[user.email],
connection=connection,
)
email.send()
How do I add custom headers?
Pass a headers dict to any email class:
email = EmailMessage(
subject="Hello",
body="Content",
to=["user@example.com"],
headers={"X-Custom-Header": "value", "Reply-To": "reply@example.com"},
)
How do I create a custom email backend?
Subclass BaseEmailBackend and implement the send_messages method:
from plain.email.backends.base import BaseEmailBackend
class MyBackend(BaseEmailBackend):
def send_messages(self, email_messages):
# Your sending logic here
return len(email_messages)
Installation
Install the plain.email package from PyPI:
uv add plain.email
Add plain.email to your INSTALLED_PACKAGES and configure the required settings:
# settings.py
INSTALLED_PACKAGES = [
# ...
"plain.email",
]
EMAIL_BACKEND = "plain.email.backends.smtp.EmailBackend"
EMAIL_DEFAULT_FROM = "noreply@example.com"
# For SMTP (adjust for your mail provider)
EMAIL_HOST = "smtp.example.com"
EMAIL_PORT = 587
EMAIL_HOST_USER = "your-username"
EMAIL_HOST_PASSWORD = "your-password"
EMAIL_USE_TLS = True
For local development, use the console backend to see emails in your terminal:
EMAIL_BACKEND = "plain.email.backends.console.EmailBackend"
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file plain_email-0.17.0.tar.gz.
File metadata
- Download URL: plain_email-0.17.0.tar.gz
- Upload date:
- Size: 16.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.10.9 {"installer":{"name":"uv","version":"0.10.9","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
31d222414d70ca144dbb583773908c5f56e9b01ca6fb33fb90abecfe8ab1310d
|
|
| MD5 |
d22d1a831948af30de0f7a569f3513b1
|
|
| BLAKE2b-256 |
b3ba0eaf5506cad17a909d63c3c06c405aed056481fc8344fdeb907da316c874
|
File details
Details for the file plain_email-0.17.0-py3-none-any.whl.
File metadata
- Download URL: plain_email-0.17.0-py3-none-any.whl
- Upload date:
- Size: 20.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.10.9 {"installer":{"name":"uv","version":"0.10.9","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7221002db4e8876686032d0c4f4b5b3374f3e7b842e42abd67b73c5d11aaed49
|
|
| MD5 |
65756feb1d1d144d4fc8ca456a2e8587
|
|
| BLAKE2b-256 |
3e80c89eaa52266248e25b96b3fd14a35a2a0e8ce095142a016795848410141b
|