Mail Integration
The Nexios Mail contrib module provides a comprehensive email sending solution with SMTP support, template integration, and background task processing.
Overview
Nexios Mail is a powerful and easy-to-use email sending solution for Nexios applications that includes:
- SMTP Support: Full SMTP configuration with TLS/SSL support
- Template Integration: Jinja2-based HTML email templates
- Background Tasks: Async email sending with nexios-contrib tasks
- Dependency Injection: Easy integration with Nexios applications
- Multiple Providers: Pre-configured settings for Gmail, Outlook, SendGrid
- Attachments: Support for file attachments and inline images
- Error Handling: Comprehensive error reporting and logging
Installation
# Basic installation
pip install nexios-contrib[mail]
# With template support
pip install nexios-contrib[mail,templating]
# With all features
pip install nexios-contrib[all]Quick Start
Basic Setup
from nexios import NexiosApp
from nexios_contrib.mail import setup_mail, MailConfig
app = NexiosApp()
# Setup with environment variables
mail_client = setup_mail(app)
# Or with custom configuration
config = MailConfig(
smtp_host="smtp.gmail.com",
smtp_port=587,
smtp_username="your-email@gmail.com",
smtp_password="your-app-password",
use_tls=True,
default_from="Your Name <your-email@gmail.com>"
)
mail_client = setup_mail(app, config=config)Environment Variables
# SMTP Configuration
SMTP_HOST=smtp.gmail.com
SMTP_PORT=587
SMTP_USERNAME=your-email@gmail.com
SMTP_PASSWORD=your-app-password
SMTP_USE_TLS=true
SMTP_USE_SSL=false
# Email Defaults
MAIL_DEFAULT_FROM=Your Name <your-email@gmail.com>
MAIL_DEFAULT_REPLY_TO=support@yourcompany.com
# Template Directory
MAIL_TEMPLATE_DIR=templates/emails
# Debug Settings
MAIL_DEBUG=false
MAIL_SUPPRESS_SEND=falseUsage Examples
Sending Basic Emails
from nexios.http import Request, Response
from nexios_contrib.mail import MailDepend
@app.post("/send-email")
async def send_email(
request: Request,
response: Response,
mail_client: MailClient = MailDepend()
):
result = await mail_client.send_email(
to="user@example.com",
subject="Welcome to Our Service",
body="Thank you for joining our platform!",
html_body="<h1>Welcome!</h1><p>Thank you for joining our platform!</p>"
)
return response.json({
"success": result.success,
"message_id": result.message_id,
"sent_at": result.sent_at.isoformat()
})Using Email Templates
Create templates in your templates/emails/ directory:
templates/emails/welcome.html
<!DOCTYPE html>
<html>
<head>
<title>Welcome {{ name }}!</title>
</head>
<body>
<h1>Welcome {{ name }}!</h1>
<p>Thank you for joining {{ company_name }}.</p>
<p>Your account has been created with email: {{ email }}</p>
<a href="{{ activation_url }}">Activate Your Account</a>
</body>
</html>templates/emails/welcome.txt
Welcome {{ name }}!
Thank you for joining {{ company_name }}.
Your account has been created with email: {{ email }}.
Activate Your Account: {{ activation_url }}Send template emails:
@app.post("/send-welcome")
async def send_welcome_email(
request: Request,
response: Response,
mail_client: MailClient = MailDepend()
):
result = await mail_client.send_template_email(
to="newuser@example.com",
subject="Welcome to Our Platform!",
template_name="welcome",
context={
"name": "John Doe",
"email": "newuser@example.com",
"company_name": "Acme Corp",
"activation_url": "https://example.com/activate/12345"
}
)
return response.json({"success": result.success, "message_id": result.message_id})Background Email Sending
Send emails asynchronously without blocking your API responses:
from nexios_contrib.mail import send_email_async
@app.post("/send-async")
async def send_async_email(
request: Request,
response: Response
):
task = await send_email_async(
request=request,
to="user@example.com",
subject="Processing Your Request",
body="We're processing your request and will notify you when complete."
)
return response.json({
"message": "Email queued for sending",
"task_id": task.id if task else None
})Configuration
Provider-Specific Configurations
Gmail
config = MailConfig.for_gmail(
username="your-email@gmail.com",
password="your-app-password", # Use app password, not regular password
default_from="Your Name <your-email@gmail.com>"
)Outlook/Office 365
config = MailConfig.for_outlook(
username="your-email@outlook.com",
password="your-password",
default_from="Your Name <your-email@outlook.com>"
)SendGrid
config = MailConfig.for_sendgrid(
api_key="your-sendgrid-api-key",
default_from="your-email@yourdomain.com"
)Advanced Features
Custom Email Messages
from nexios_contrib.mail import EmailMessage
# Create detailed email message
message = EmailMessage(
to="recipient@example.com",
subject="Custom Email",
body="Plain text content",
html_body="<h1>HTML Content</h1>",
cc="manager@example.com",
bcc="archive@example.com",
priority=1 # High priority
)
# Add custom headers
message.add_header("X-Campaign-ID", "summer-2024")
message.add_header("X-Mailer", "Nexios Mail")
# Add attachments
message.add_attachment("report.pdf", b"PDF content", "application/pdf")
# Send the message
result = await mail_client.send_message(message)Template Custom Filters
# Add custom Jinja2 filters
def format_currency(value, currency="USD"):
return f"{value:.2f} {currency}"
# In your mail client setup
mail_client._template_env.filters["currency"] = format_currency
# Use in templates
{{ price | currency }}API Reference
MailClient
The main mail client class for sending emails.
Methods
send_email(to, subject, body=None, html_body=None, **kwargs)- Send an emailsend_message(message)- Send an EmailMessage objectsend_template_email(to, subject, template_name, context=None, **kwargs)- Send template emailcreate_message(to, subject, **kwargs)- Create EmailMessage object
EmailMessage
Represents an email message with all its components.
Properties
to- Recipient email addressessubject- Email subjectbody- Plain text bodyhtml_body- HTML bodyattachments- List of attachmentsheaders- Custom headers
Methods
add_attachment(filename, content, content_type=None, content_id=None)- Add attachmentset_template(template_name, context=None)- Set templateadd_header(name, value)- Add custom header
MailConfig
Configuration for the mail client.
Class Methods
for_gmail(username, password, **kwargs)- Gmail configurationfor_outlook(username, password, **kwargs)- Outlook configurationfor_sendgrid(api_key, **kwargs)- SendGrid configuration
Best Practices
Security
- Never hardcode credentials - Always use environment variables
- Use app passwords - For Gmail, generate app passwords instead of using your main password
- Enable TLS - Always use TLS/SSL for secure connections
- Validate inputs - Sanitize and validate all email inputs
Performance
- Use background tasks - Send emails asynchronously to avoid blocking responses
- Connection pooling - Reuse SMTP connections when possible
- Template caching - Templates are automatically cached for performance
Reliability
- Error handling - Always handle email sending errors gracefully
- Logging - Enable debug mode during development
- Testing - Use
suppress_send=Truefor testing without actually sending emails
Troubleshooting
Common Issues
Authentication Failed
- Check SMTP credentials
- For Gmail, use an App Password instead of your regular password
- Verify 2FA settings
Connection Timeout
- Check SMTP host and port
- Verify firewall settings
- Increase
smtp_timeoutvalue
Template Not Found
- Verify template directory path
- Check template file names and extensions
- Ensure template files exist
Background Tasks Not Working
- Install nexios-contrib tasks:
pip install nexios-contrib[tasks] - Setup tasks in your app:
setup_tasks(app)
- Install nexios-contrib tasks:
Debug Mode
Enable debug mode to see SMTP communication:
config = MailConfig(
debug=True, # Enables SMTP debug logging
suppress_send=True # Test mode - don't actually send
)Integration with Other Modules
Background Tasks
The mail module integrates seamlessly with the nexios-contrib tasks module for async email sending:
from nexios_contrib.tasks import setup_tasks
from nexios_contrib.mail import setup_mail
app = NexiosApp()
# Setup tasks first
task_manager = setup_tasks(app)
# Then setup mail (will automatically integrate with tasks)
mail_client = setup_mail(app)Templates
The mail module uses Jinja2 for template rendering, which can be integrated with your existing template setup:
# Share template environment with your web templates
from jinja2 import FileSystemLoader, Environment
# Create shared template environment
template_env = Environment(
loader=FileSystemLoader(["templates/web", "templates/emails"])
)
# Use with mail client
mail_client._template_env = template_envExamples
Complete Email Service
from nexios import NexiosApp
from nexios_contrib.mail import setup_mail, MailConfig, MailDepend
from nexios_contrib.tasks import setup_tasks
import os
app = NexiosApp()
# Setup background tasks
task_manager = setup_tasks(app)
# Setup mail
config = MailConfig(
smtp_host=os.getenv("SMTP_HOST"),
smtp_port=int(os.getenv("SMTP_PORT")),
smtp_username=os.getenv("SMTP_USERNAME"),
smtp_password=os.getenv("SMTP_PASSWORD"),
use_tls=True,
default_from=os.getenv("MAIL_DEFAULT_FROM"),
template_directory="templates/emails"
)
mail_client = setup_mail(app, config=config)
@app.post("/send-welcome")
async def send_welcome_email(
request: Request,
response: Response,
mail_client: MailClient = MailDepend()
):
data = await request.json
result = await mail_client.send_template_email(
to=data["email"],
subject="Welcome to Our Platform!",
template_name="welcome",
context={
"name": data["name"],
"email": data["email"],
"company_name": "Acme Corp"
}
)
return response.json({
"success": result.success,
"message_id": result.message_id,
"error": result.error
})
@app.post("/send-async")
async def send_async_email(
request: Request,
response: Response
):
data = await request.json
task = await send_email_async(
request=request,
to=data["email"],
subject=data["subject"],
body=data["body"]
)
return response.json({
"message": "Email queued for sending",
"task_id": task.id if task else None
})This comprehensive mail integration provides everything you need to add professional email functionality to your Nexios applications with ease.
