Email plugin for Litestar
Project description
litestar-email
Email support for Litestar applications. This plugin provides a pluggable email backend system for sending transactional emails with support for multiple providers.
Installation
pip install litestar-email
Usage
from litestar import Litestar
from litestar_email import EmailConfig, EmailPlugin
config = EmailConfig(
backend="console", # or "memory", "smtp", "sendgrid", "resend"
from_email="noreply@example.com",
from_name="My App",
)
app = Litestar(plugins=[EmailPlugin(config=config)])
Sending Email
from litestar_email import EmailMessage
message = EmailMessage(
subject="Welcome!",
body="Thanks for signing up.",
to=["user@example.com"],
)
async for mailer in config.provide_service():
await mailer.send_message(message)
If message.from_email is omitted, the service uses config.from_email and
config.from_name as defaults.
Dependency Injection
The plugin registers a mailer dependency for handlers by default:
from litestar import get
from litestar_email import EmailMessage, EmailService
@get("/welcome/{email:str}")
async def send_welcome(email: str, mailer: EmailService) -> dict[str, str]:
message = EmailMessage(
subject="Welcome!",
body="Thanks for signing up.",
to=[email],
)
await mailer.send_message(message)
return {"status": "sent"}
This works for both router handlers and controller methods the same way, since the dependency is registered on the app.
If you need a service outside of Litestar (e.g., for a worker), use
config.get_service() for a one-off instance or config.provide_service()
for batch sending.
Events and Listeners
Litestar listeners do not support DI, so pass the service explicitly when emitting:
from litestar import Litestar, Request, get
from litestar.events import listener
from litestar_email import EmailConfig, EmailMessage, EmailPlugin, EmailService
config = EmailConfig(
backend="smtp",
from_email="noreply@example.com",
from_name="My App",
)
@listener("user.registered")
async def on_user_registered(email: str, mailer: EmailService) -> None:
message = EmailMessage(
subject="Welcome!",
body="Thanks for signing up.",
to=[email],
)
await mailer.send_message(message)
@get("/register/{email:str}")
async def register(email: str, request: Request) -> dict[str, str]:
request.app.emit(
"user.registered",
email,
mailer=config.get_service(request.app.state),
)
return {"status": "queued"}
app = Litestar(
plugins=[EmailPlugin(config=config)],
listeners=[on_user_registered],
)
You can override the dependency and state keys via EmailConfig if needed:
email_service_dependency_key="email_service" and email_service_state_key="email_service".
If you have the plugin instance available, use plugin.get_service(request.app.state).
Standalone (No Litestar)
Use the config helpers directly without Litestar:
from litestar_email import EmailConfig, EmailMessage
config = EmailConfig(backend="smtp", from_email="noreply@example.com")
message = EmailMessage(
subject="Hello!",
body="This is a standalone send.",
to=["user@example.com"],
)
async for mailer in config.provide_service():
await mailer.send_message(message)
For batch sends, use the context helper to reuse the connection:
async for mailer in config.provide_service():
await mailer.send_messages([message1, message2, message3])
HTML Email
from litestar_email import EmailMultiAlternatives
message = EmailMultiAlternatives(
subject="Welcome!",
body="Thanks for signing up.", # Plain text fallback
html_body="<h1>Welcome!</h1><p>Thanks for signing up.</p>",
to=["user@example.com"],
)
Available Backends
| Backend | Description | Use Case |
|---|---|---|
console |
Prints emails to stdout | Development |
memory |
Stores emails in memory | Testing |
smtp |
Async SMTP via aiosmtplib | Production |
sendgrid |
SendGrid HTTP API | Production |
resend |
Resend HTTP API | Production |
Testing
The InMemoryBackend is designed for testing:
from litestar_email.backends import InMemoryBackend
def test_sends_welcome_email():
InMemoryBackend.clear()
# ... code that sends email ...
assert len(InMemoryBackend.outbox) == 1
assert InMemoryBackend.outbox[0].subject == "Welcome!"
If you need direct backend access in tests, use config.get_backend():
from litestar_email import EmailConfig, EmailMessage
config = EmailConfig(backend="memory")
backend = config.get_backend()
message = EmailMessage(subject="Hello", body="Body", to=["user@example.com"])
await backend.send_messages([message])
Development
make install # Install dependencies
make test # Run tests
make lint # Run linting
make check-all # Run all checks
License
MIT
Project details
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 litestar_email-0.1.0.tar.gz.
File metadata
- Download URL: litestar_email-0.1.0.tar.gz
- Upload date:
- Size: 187.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
75ac56b0a300b980c58b7041be495a77efaf5e18e685400765c9b7cc0f62edb5
|
|
| MD5 |
1e70a3681bc4525ca411db7a1ea5de9f
|
|
| BLAKE2b-256 |
cad08c7d83fa2ea1c805943345e24d560b4cafcff509217945ed5cebef06d0b9
|
Provenance
The following attestation bundles were made for litestar_email-0.1.0.tar.gz:
Publisher:
publish.yml on cofin/litestar-email
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
litestar_email-0.1.0.tar.gz -
Subject digest:
75ac56b0a300b980c58b7041be495a77efaf5e18e685400765c9b7cc0f62edb5 - Sigstore transparency entry: 790835578
- Sigstore integration time:
-
Permalink:
cofin/litestar-email@a47cb86b5efeb31d3f5651dc0b07047a894838b3 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/cofin
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@a47cb86b5efeb31d3f5651dc0b07047a894838b3 -
Trigger Event:
release
-
Statement type:
File details
Details for the file litestar_email-0.1.0-py3-none-any.whl.
File metadata
- Download URL: litestar_email-0.1.0-py3-none-any.whl
- Upload date:
- Size: 23.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
71a05dc214b36459a286bf6b74a94338b147ddcf47f7a56691c17edf0a7254bd
|
|
| MD5 |
e1a72f66cdb1071f03498f2b3caaefeb
|
|
| BLAKE2b-256 |
29147b8341ba35215babe1a9bf6ff244eccfb33cb97fe578e5dc7414f35ac5d9
|
Provenance
The following attestation bundles were made for litestar_email-0.1.0-py3-none-any.whl:
Publisher:
publish.yml on cofin/litestar-email
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
litestar_email-0.1.0-py3-none-any.whl -
Subject digest:
71a05dc214b36459a286bf6b74a94338b147ddcf47f7a56691c17edf0a7254bd - Sigstore transparency entry: 790835580
- Sigstore integration time:
-
Permalink:
cofin/litestar-email@a47cb86b5efeb31d3f5651dc0b07047a894838b3 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/cofin
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@a47cb86b5efeb31d3f5651dc0b07047a894838b3 -
Trigger Event:
release
-
Statement type: