Send emails the easy way
Project description
django-notifiedby
Integrate django-notifiedby to send emails and manage email flows through the NotifiedBy API.
Features
- Email Backend: Drop-in replacement for Django's email backend
- Flow Management: Subscribe users to automated email sequences (onboarding, drip campaigns, newsletters)
- Recipient Management: Create and manage recipients with metadata and flags for segmentation
- Email Querying: Check delivery status and query email history
- Simple API: Pythonic functions that are easy to use
Installation
Using pip:
pip install django-notifiedby
Configuration
Add the notifiedby email backend to your Django settings:
# my_project/settings.py
# Required: Set your NotifiedBy API key
EMAIL_BACKEND = "notifiedby.NotifiedByEmailBackend"
NOTIFIEDBY_API_KEY = "your-api-key-here"
# Optional: Add encryption key if you use encrypted emails
NOTIFIEDBY_ENCRYPTION_KEY = "your-encryption-key" # Optional
API Keys can be purchased from NotifiedBy.com
Usage
Sending Transactional Emails
The built-in Django emails will automatically send through NotifiedBy:
from django.core.mail import EmailMessage
email = EmailMessage(
subject='Subject Here',
body='Body of the email here',
from_email='your_email@example.com',
to=['recipient@example.com'],
cc=['cc_recipient@example.com'], # CC
bcc=['bcc_recipient@example.com'], # BCC
)
# Attach a file
email.attach('example.pdf', b'Some binary data', 'application/pdf')
email.send()
Flow Management
Subscribe users to automated email sequences:
from notifiedby import subscribe_to_flow, unsubscribe_from_flow
# Subscribe a user to a welcome email series
subscribe_to_flow(
flow_trigger='welcome_series',
email='user@example.com',
first_name='John',
last_name='Doe',
flags=['free_plan', 'new_user']
)
# Unsubscribe from a flow
unsubscribe_from_flow('newsletter_weekly', 'user@example.com')
# List all flow subscriptions
from notifiedby import list_flow_subscriptions
subscriptions = list_flow_subscriptions(page=1)
print(f"Total subscriptions: {subscriptions['count']}")
for sub in subscriptions['results']:
print(f"{sub['recipient_email']} - {sub['flow_name']} ({sub['status']})")
Common Flow Patterns
User Signup Flow:
from django.contrib.auth.signals import user_signed_up
from notifiedby import subscribe_to_flow
def on_user_signup(sender, user, **kwargs):
"""Automatically subscribe new users to onboarding flow"""
subscribe_to_flow(
flow_trigger='onboarding',
email=user.email,
first_name=user.first_name,
flags=['free_plan']
)
user_signed_up.connect(on_user_signup)
Subscription Upgrade Flow:
from notifiedby import subscribe_to_flow, set_recipient_flags
def upgrade_to_premium(user):
# Update user flags
set_recipient_flags(user.email, ['premium', 'paid'])
# Subscribe to premium onboarding
subscribe_to_flow(
flow_trigger='premium_onboarding',
email=user.email,
first_name=user.first_name
)
Recipient Management
Create and manage recipients with metadata:
from notifiedby import (
create_or_update_recipient,
set_recipient_flags,
clear_recipient_flags,
list_recipients
)
# Create or update a recipient
recipient = create_or_update_recipient(
email='user@example.com',
first_name='Jane',
last_name='Smith',
flags=['premium', 'beta_tester']
)
print(f"Recipient ID: {recipient['sqid']}")
# Set flags for segmentation (adds to existing flags)
set_recipient_flags('user@example.com', ['annual_plan', 'power_user'])
# Clear specific flags
clear_recipient_flags('user@example.com', ['trial', 'pending'])
# List all recipients
recipients = list_recipients(page=1)
for recipient in recipients['results']:
print(f"{recipient['email']} - Created: {recipient['created_at']}")
Flags are custom tags for segmentation (e.g., 'premium', 'churned', 'early_adopter'). Use them to:
- Trigger different email flows based on user status
- Filter and segment your audience
- Track user lifecycle stages
Email Querying
Check email delivery status and query sent emails:
from notifiedby import (
get_email_detail,
list_sent_emails,
get_email_delivery_status,
send_email_via_api
)
from django.core.mail import EmailMessage
# Send an email and get the ID
message = EmailMessage(
subject='Test Email',
body='Hello!',
to=['user@example.com']
)
email_id = send_email_via_api(message)
# Check delivery status
if email_id:
status = get_email_delivery_status(email_id)
print(f"Delivery status: {status}")
# Get email details by ID
email = get_email_detail(sqid='abc123xyz')
print(f"Subject: {email['subject']}")
print(f"Sent to: {email['recipient']}")
# Get most recent email to a recipient
email = get_email_detail(email='user@example.com')
# List all sent emails
emails = list_sent_emails(page=1)
print(f"Total emails sent: {emails['count']}")
# Filter by recipient
user_emails = list_sent_emails(recipient='user@example.com')
for email in user_emails['results']:
print(f"{email['subject']} - {email['created_on']}")
Error Handling
The library provides specific exceptions for different error scenarios:
from notifiedby import subscribe_to_flow
from notifiedby.exceptions import (
NotifiedByAPIError,
NotifiedByValidationError,
NotifiedByAuthError,
NotifiedByConfigError,
NotifiedByNotFoundError,
)
try:
subscribe_to_flow('welcome', 'user@example.com')
except NotifiedByConfigError as e:
# API key not configured
print(f"Configuration error: {e}")
except NotifiedByValidationError as e:
# Invalid data (bad email, unknown flow, etc.)
print(f"Validation error: {e}")
except NotifiedByAuthError as e:
# Authentication failed (invalid API key)
print(f"Auth error: {e}")
except NotifiedByNotFoundError as e:
# Resource not found
print(f"Not found: {e}")
except NotifiedByAPIError as e:
# Other API errors
print(f"API error: {e.status_code} - {e}")
Advanced Usage
Custom Client for Testing
You can inject a custom client for testing or using a different API endpoint:
from notifiedby import NotifiedByClient, subscribe_to_flow
# Create a test client
test_client = NotifiedByClient(
api_key='test_key',
base_url='http://localhost:8000'
)
# Use with any function
subscribe_to_flow(
'welcome',
'test@example.com',
client=test_client
)
Direct API Usage
For more control, use the NotifiedByClient directly:
from notifiedby import NotifiedByClient
client = NotifiedByClient()
# Make custom API calls
response = client.post('/flows/subscribe/', json={
'flow_trigger': 'custom_flow',
'email': 'user@example.com'
})
# GET request with parameters
subscriptions = client.get('/flows/subscriptions/', params={'page': 2})
# DELETE request
client.delete('/flows/subscriptions/')
Contributing
In order to contribute to the plugin itself so just need to clone the repo, create the venv and install the dev requirements.
git clone git@gitlab.com:rezero-consulting/django-notifiedby.git
python -m venv venv
source venv/bin/activate
pip install -r dev-requirements.txt
Updating PyPi
This plugin is hosted on PiPy and needs to be uploaded when anything is updated
When a change has been make you need to update the version number in pyproject.toml You then need to build the distribution files
cd django-notifiedby
python -m build
This will build new version files in the dist folder and update some other files in the django_notifiedby.egg-info folder. All these files can be added to the repo but only the two new files in the dist folder need uploading to PyPi.
In order to upload this plugin to PyPi you will need a valid key for the PyPi project. Contact rich@rezero.net about this. Once you have a key upload to PyPi with:
cd django-notifiedby
twine upload dist/django_nofitiedby-[version]*
Where [version] is the version you've just built.
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 django_notifiedby-0.2.0.tar.gz.
File metadata
- Download URL: django_notifiedby-0.2.0.tar.gz
- Upload date:
- Size: 14.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
57b86f9b75d2ea9d38bfabedfdbf1450caebfd636885ac8e1ee9ed495bf57e09
|
|
| MD5 |
9747e9f13b4f2abb1819c4325c94f1df
|
|
| BLAKE2b-256 |
323fd76df499e4a165b74a321a6200e0798738449c76a23cec57d7412865f281
|
File details
Details for the file django_notifiedby-0.2.0-py3-none-any.whl.
File metadata
- Download URL: django_notifiedby-0.2.0-py3-none-any.whl
- Upload date:
- Size: 14.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
297871c0f0e06229b1b1b1c8fe52f53e04ed42be8ceb0dcab958de5626455420
|
|
| MD5 |
aaf9f755cba9c9cd41bfc927ba3b58bc
|
|
| BLAKE2b-256 |
d488af91651404725c090ebc9f9e9235af938cc6c03ae6a3cabd1f81d7408207
|