Django integration for ForwardEmail API with multi-site support
Project description
Django ForwardEmail
A Django package for integrating with the ForwardEmail API service, providing multi-site email configuration and Django email backend support.
Features
- Multi-site Support: Configure different ForwardEmail settings for each Django site
- Django Email Backend: Drop-in replacement for Django's default email backend
- Service Class: Direct API integration for custom email sending logic
- Admin Interface: User-friendly Django admin interface for managing configurations
- Type Safety: Full type hints and mypy compatibility
- Comprehensive Logging: Debug-friendly logging for troubleshooting
Requirements
- Python 3.10+
- Django 4.2+
Installation
pip install django-forwardemail
Quick Start
1. Add to Django Settings
Add django_forwardemail to your INSTALLED_APPS:
INSTALLED_APPS = [
# ... other apps
'django.contrib.sites', # Required for multi-site support
'django_forwardemail',
]
# Optional: Set ForwardEmail as your default email backend
EMAIL_BACKEND = 'django_forwardemail.backends.ForwardEmailBackend'
# Optional: Configure ForwardEmail API base URL (defaults to https://api.forwardemail.net)
FORWARD_EMAIL_BASE_URL = 'https://api.forwardemail.net'
2. Run Migrations
python manage.py migrate django_forwardemail
3. Configure in Django Admin
- Go to Django Admin → Sites → Sites and ensure you have your site configured
- Go to Django Admin → Django ForwardEmail → Email Configurations
- Create a new configuration with:
- Site: Select your site
- API Key: Your ForwardEmail API key
- From Email: Default sender email address
- From Name: Default sender name
- Reply To: Default reply-to address
Usage
Using Django's Email System
Once configured, you can use Django's standard email functions:
from django.core.mail import send_mail, EmailMultiAlternatives
# Simple text email
send_mail(
'Subject here',
'Here is the message.',
'from@example.com',
['to@example.com'],
fail_silently=False,
)
# HTML email with text fallback
msg = EmailMultiAlternatives(
'Subject here',
'Plain text version of the message.',
'from@example.com',
['to@example.com']
)
msg.attach_alternative('<h1>HTML version</h1><p>of the message.</p>', "text/html")
msg.send()
Using the Service Class Directly
For more control, use the ForwardEmailService directly:
from django_forwardemail.services import ForwardEmailService
from django.contrib.sites.models import Site
# Get the current site
site = Site.objects.get_current()
# Send simple text email
response = ForwardEmailService.send_email(
to='recipient@example.com',
subject='Test Email',
text='This is a test email.',
site=site,
)
# Send HTML email with text fallback
response = ForwardEmailService.send_email(
to='recipient@example.com',
subject='HTML Test Email',
text='This is the plain text version.',
html='<h1>HTML Email</h1><p>This is a <strong>test</strong> email.</p>',
site=site,
)
# Send with custom from/reply-to
response = ForwardEmailService.send_email(
to='recipient@example.com',
subject='Custom Sender Email',
text='This email has custom sender info.',
from_email='custom@example.com',
reply_to='support@example.com',
site=site,
)
Using in Django Views
Here's how to integrate email sending in your Django views:
from django.shortcuts import render
from django.contrib import messages
from django.http import HttpResponseRedirect
from django_forwardemail.services import ForwardEmailService
from django.contrib.sites.shortcuts import get_current_site
def contact_view(request):
if request.method == 'POST':
name = request.POST.get('name')
email = request.POST.get('email')
message = request.POST.get('message')
try:
# Send notification email
ForwardEmailService.send_email(
to='admin@example.com',
subject=f'Contact Form: {name}',
text=f'From: {name} <{email}>\n\nMessage:\n{message}',
html=f'''
<h2>Contact Form Submission</h2>
<p><strong>From:</strong> {name} <{email}></p>
<p><strong>Message:</strong></p>
<p>{message}</p>
''',
reply_to=email,
request=request, # Automatically detects site
)
messages.success(request, 'Your message has been sent!')
return HttpResponseRedirect('/contact/')
except Exception as e:
messages.error(request, f'Failed to send message: {str(e)}')
return render(request, 'contact.html')
Template-based Emails
For complex emails, use Django templates:
from django.template.loader import render_to_string
from django_forwardemail.services import ForwardEmailService
def send_welcome_email(user, request):
# Render email templates
text_content = render_to_string('emails/welcome.txt', {
'user': user,
'site_name': 'Your Site',
})
html_content = render_to_string('emails/welcome.html', {
'user': user,
'site_name': 'Your Site',
})
# Send email
ForwardEmailService.send_email(
to=user.email,
subject='Welcome to Your Site!',
text=text_content,
html=html_content,
request=request,
)
Async Email Sending with Celery
For high-volume applications, use Celery for async email sending:
from celery import shared_task
from django_forwardemail.services import ForwardEmailService
from django.contrib.sites.models import Site
@shared_task
def send_email_async(to, subject, text, html=None, site_id=1):
"""Send email asynchronously using Celery."""
try:
site = Site.objects.get(id=site_id)
ForwardEmailService.send_email(
to=to,
subject=subject,
text=text,
html=html,
site=site,
)
return f"Email sent successfully to {to}"
except Exception as e:
return f"Failed to send email: {str(e)}"
# Usage in views
def some_view(request):
# Queue email for background processing
send_email_async.delay(
to='user@example.com',
subject='Background Email',
text='This email was sent in the background.',
site_id=request.site.id,
)
Multi-site Configuration
For multi-site setups, create separate EmailConfiguration objects for each site:
from django.contrib.sites.models import Site
from django_forwardemail.models import EmailConfiguration
# Configure for site 1
site1 = Site.objects.get(domain='site1.example.com')
EmailConfiguration.objects.create(
site=site1,
api_key='your-api-key-1',
from_email='noreply@site1.example.com',
from_name='Site 1',
reply_to='support@site1.example.com',
)
# Configure for site 2
site2 = Site.objects.get(domain='site2.example.com')
EmailConfiguration.objects.create(
site=site2,
api_key='your-api-key-2',
from_email='noreply@site2.example.com',
from_name='Site 2',
reply_to='support@site2.example.com',
)
API Reference
ForwardEmailService
send_email(**kwargs)
Send an email through the ForwardEmail API.
Parameters:
to(str): Recipient email addresssubject(str): Email subject linetext(str): Plain text email contentfrom_email(str, optional): Sender email address (uses config default if not provided)html(str, optional): HTML email contentreply_to(str, optional): Reply-to email address (uses config default if not provided)request(HttpRequest, optional): Django request object for site detectionsite(Site, optional): Django Site object (auto-detected if not provided)base_url(str, optional): ForwardEmail API base URL
Returns:
Dict[str, Any]: API response from ForwardEmail
Raises:
ImproperlyConfigured: If site configuration is missingException: If email sending fails
EmailConfiguration Model
Django model for storing ForwardEmail configurations per site.
Fields:
site: ForeignKey to Django Siteapi_key: ForwardEmail API keyfrom_email: Default sender email addressfrom_name: Default sender namereply_to: Default reply-to addresscreated_at: Timestamp when createdupdated_at: Timestamp when last updated
Settings
FORWARD_EMAIL_BASE_URL
Default: 'https://api.forwardemail.net'
The base URL for the ForwardEmail API. You typically don't need to change this unless you're using a custom ForwardEmail instance.
EMAIL_BACKEND
Set this to 'django_forwardemail.backends.ForwardEmailBackend' to use ForwardEmail as your default email backend.
Development
Running Tests
# Install development dependencies
pip install -e ".[dev]"
# Run tests
pytest
# Run tests with coverage
pytest --cov=django_forwardemail
Code Quality
# Format code
black django_forwardemail/
# Lint code
flake8 django_forwardemail/
# Type checking
mypy django_forwardemail/
Contributing
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Make your changes
- Add tests for your changes
- Ensure all tests pass
- Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
License
This project is licensed under the MIT License - see the LICENSE file for details.
Support
- Documentation: https://django-forwardemail.readthedocs.io/
- Issues: https://github.com/thrillwiki/django-forwardemail/issues
- ForwardEmail Documentation: https://forwardemail.net/docs
Changelog
1.0.0 (2025-08-30)
- STABLE RELEASE - Production-ready ForwardEmail integration
- Multi-site email configuration support with automatic site detection
- Django email backend integration with full compatibility
- ForwardEmail API service class with comprehensive error handling
- Django admin interface for easy configuration management
- Full backward compatibility with existing Django email patterns
- Comprehensive test suite covering Django 4.2+ and Python 3.10+
- Modern type hints and logging integration
- Extensive documentation and usage examples
- Automated CI/CD pipeline with PyPI publishing
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 django_forwardemail-1.0.0.tar.gz.
File metadata
- Download URL: django_forwardemail-1.0.0.tar.gz
- Upload date:
- Size: 17.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.12.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7cb453a78446f04ba079bcfe5937f34edf1170e33a4378febf31a2561174f3a0
|
|
| MD5 |
1190619ef6d8c05ffe790398e69f80ba
|
|
| BLAKE2b-256 |
f5a107011849d802f85422ce36473e4f4255cffc0b12219cb72217f616b787cf
|
Provenance
The following attestation bundles were made for django_forwardemail-1.0.0.tar.gz:
Publisher:
publish.yml on Pacficient-Labs/django-forwardemail
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
django_forwardemail-1.0.0.tar.gz -
Subject digest:
7cb453a78446f04ba079bcfe5937f34edf1170e33a4378febf31a2561174f3a0 - Sigstore transparency entry: 452586984
- Sigstore integration time:
-
Permalink:
Pacficient-Labs/django-forwardemail@6a0c7d472fe93c78790a11f8d3b2801799c01220 -
Branch / Tag:
refs/tags/v1.0.0 - Owner: https://github.com/Pacficient-Labs
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@6a0c7d472fe93c78790a11f8d3b2801799c01220 -
Trigger Event:
release
-
Statement type:
File details
Details for the file django_forwardemail-1.0.0-py3-none-any.whl.
File metadata
- Download URL: django_forwardemail-1.0.0-py3-none-any.whl
- Upload date:
- Size: 16.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.12.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
29debe5747122c2a29f52682347f72e8caba38bf874f279c36aa49d855e6afc6
|
|
| MD5 |
f31ba4b0f0b7f9102ba8b4c7d8a9909b
|
|
| BLAKE2b-256 |
4ca1fe9d53398de7f80be8e1a85cb64eb9562056638494b4a79a524e9f3e031e
|
Provenance
The following attestation bundles were made for django_forwardemail-1.0.0-py3-none-any.whl:
Publisher:
publish.yml on Pacficient-Labs/django-forwardemail
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
django_forwardemail-1.0.0-py3-none-any.whl -
Subject digest:
29debe5747122c2a29f52682347f72e8caba38bf874f279c36aa49d855e6afc6 - Sigstore transparency entry: 452586991
- Sigstore integration time:
-
Permalink:
Pacficient-Labs/django-forwardemail@6a0c7d472fe93c78790a11f8d3b2801799c01220 -
Branch / Tag:
refs/tags/v1.0.0 - Owner: https://github.com/Pacficient-Labs
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@6a0c7d472fe93c78790a11f8d3b2801799c01220 -
Trigger Event:
release
-
Statement type: