Usage¶
After you’ve installed Django Mail Admin:
Send a simple email is really easy:
from django_mail_admin import mail, models
mail.send(
'from@example.com',
'recipient@example.com', # List of email addresses also accepted
subject='My email',
message='Hi there!',
priority=models.PRIORITY.now,
html_message='Hi <strong>there</strong>!',
)
If you want to use templates: create an
EmailTemplate
instance via admin
or manually
and do the following:
from post_office import mail, models
template = models.EmailTemplate.objects.create(name='first', description='desc', subject='{{id}}',
email_html_text='{{id}}')
email = mail.create('from@example.com',
'recipient@example.com', # List of email addresses also accepted
template=template,
priority=models.PRIORITY.now)
models.TemplateVariable.objects.create(name='id', value=1, email=email)
models.OutgoingEmail.objects.get(id=email.id).dispatch() # re-get it from DB for template variable to kick in, not needed when sending emails from queue via cron/celery/etc.
# OR
mail.send('from@example.com',
'recipient@example.com', # List of email addresses also accepted
template=template,
priority=models.PRIORITY.now,
variable_dict={'id': 1})
Template variables & tags¶
Django mail admin
supports Django’s template tags and variables.
It is important to note, however, that due to usage of TemplateVariable db-model,
only strings can be stored as value, and anything in the template will be treated as a string.
For example, 'foo': [5,6]
when called in template as {{ foo|first }}
will result in [
,
not in 5
. Please keep this in mind.
As an example of usage, if you put “Hello, {{ name }}” in the subject line and pass in
{'name': 'Alice'}
as variable_dict, you will get “Hello, Alice” as subject:
from post_office import mail, models
models.EmailTemplate.objects.create(
name='morning_greeting',
subject='Morning, {{ name|capfirst }}',
content='Hi {{ name }}, how are you feeling today?',
html_content='Hi <strong>{{ name }}</strong>, how are you feeling today?',
)
mail.send(
'from@example.com',
'recipient@example.com', # List of email addresses also accepted
template=template,
priority=models.PRIORITY.now,
variable_dict={'name': 'alice'})
)
# This will create an email with the following content:
subject = 'Morning, Alice',
content = 'Hi alice, how are you feeling today?'
content = 'Hi <strong>alice</strong>, how are you feeling today?'
mail.send()¶
mail.send
is the most important function in this library, it takes these
arguments:
Argument | Required | Description |
recipients | No | list of recipient email addresses |
sender | Yes | Defaults to settings.DEFAULT_FROM_EMAIL ,
display name is allowed (John <john@a.com> ) |
subject | No | Email subject (if template is not specified) |
message | No | Email content (if template is not specified) |
html_message | No | HTML content (if template is not specified) |
template | No | EmailTemplate instance |
cc | No | list emails, will appear in cc field |
bcc | No | list of emails, will appear in bcc field |
attachments | No | Email attachments - A dictionary where the keys are the filenames and the values are either:
|
variables_dict | No | A dictionary, used to render templated email |
headers | No | A dictionary of extra headers on the message |
scheduled_time | No | A date/datetime object indicating when the email should be sent |
priority | No | high , medium , low or now
(send_immediately) |
backend | No | Alias of the backend you want to use.
default will be used if not specified. |
Here are a few examples.
If you just want to send out emails without using database templates. You can
call the send
command without the template
argument.
from django_mail_admin import mail
mail.send(
'from@example.com',
['recipient1@example.com'],
subject='Welcome!',
message='Welcome home, {{ name }}!',
html_message='Welcome home, <b>{{ name }}</b>!',
headers={'Reply-to': 'reply@example.com'},
scheduled_time=date(2019, 1, 1),
variables_dict={'name': 'Alice'},
)
django_mail_admin
is also task queue friendly. Passing now
as priority into
send_mail
will deliver the email right away (instead of queuing it),
regardless of how many emails you have in your queue:
from django_mail_admin import mail, models
mail.send(
'from@example.com',
['recipient1@example.com'],
template=models.EmailTemplate.objects.get(name='welcome'),
variables_dict={'foo': 'bar'},
priority='now',
)
This is useful if you already use something like django-rq to send emails asynchronously and only need to store email related activities and logs.
If you want to send an email with attachments:
from django.core.files.base import ContentFile
from django_mail_admin import mail, models
mail.send(
['recipient1@example.com'],
'from@example.com',
template=models.EmailTemplate.objects.get(name='welcome'),
variables_dict={'foo': 'bar'},
priority='now',
attachments={
'attachment1.doc': '/path/to/file/file1.doc',
'attachment2.txt': ContentFile('file content'),
'attachment3.txt': { 'file': ContentFile('file content'), 'mimetype': 'text/plain'},
}
)
send_many()¶
send_many()
is much more performant (generates less database queries) when
sending a large number of emails. send_many()
is almost identical to mail.send()
,
with the exception that it accepts a list of keyword arguments that you’d
usually pass into mail.send()
:
from from django_mail_admin import mail
first_email = {
'sender': 'from@example.com',
'recipients': ['alice@example.com'],
'subject': 'Hi!',
'message': 'Hi Alice!'
}
second_email = {
'sender': 'from@example.com',
'recipients': ['bob@example.com'],
'subject': 'Hi!',
'message': 'Hi Bob!'
}
kwargs_list = [first_email, second_email]
mail.send_many(kwargs_list)
Attachments are not supported with mail.send_many()
.
Management Commands¶
send_queued_mail
- send queued emails, those aren’t successfully sent will be marked asfailed
. Accepts the following arguments:
Argument | Description |
--processes or -p |
Number of parallel processes to send email. Defaults to 1 |
--lockfile or -L |
Full path to file used as lock file. Defaults to
/tmp/post_office.lock |
cleanup_mail
- delete all emails created before an X number of days (defaults to 90).
Argument | Description |
--days or -d |
Number of days to filter by. |
get_new_mail
- receive new emails for all mailboxes or, if any args passed - filtered, e.g.:
python manage.py get_new_mail `test`
Set cron/Celery/RQ job to send/receive email, e.g.
* * * * * (cd $PROJECT; python manage.py send_queued_mail --processes=1 >> $PROJECT/cron_mail.log 2>&1)
* * * * * (cd $PROJECT; python manage.py get_new_mail >> $PROJECT/cron_mail_receive.log 2>&1)
0 1 * * * (cd $PROJECT; python manage.py cleanup_mail --days=30 >> $PROJECT/cron_mail_cleanup.log 2>&1)
If you use uWSGI as application server, add this short snipped to the
project’s wsgi.py
file:
from django.core.wsgi import get_wsgi_application
application = get_wsgi_application()
# add this block of code
try:
import uwsgidecorators
from django.core.management import call_command
@uwsgidecorators.timer(10)
def send_queued_mail(num):
"""Send queued mail every 10 seconds"""
call_command('send_queued_mail', processes=1)
except ImportError:
print("uwsgidecorators not found. Cron and timers are disabled")
Alternatively you can also use the decorator @uwsgidecorators.cron(minute, hour, day, month, weekday)
.
This will schedule a task at specific times. Use -1
to signal any time, it corresponds to the uWSGI
in cron.
Please note that uwsgidecorators
are available only, if the application has been started
with uWSGI. However, Django’s internal ./manage.py runserver
also access this file,
therefore wrap the block into an exception handler as shown above.
This configuration is very useful in environments, such as Docker containers, where you don’t have a running cron-daemon.
Logging¶
You can configure Django Mail Admin’s logging from Django’s settings.py. For example:
LOGGING = {
"version": 1,
"disable_existing_loggers": False,
"formatters": {
"django_mail_admin": {
"format": "[%(levelname)s]%(asctime)s PID %(process)d: %(message)s",
"datefmt": "%d-%m-%Y %H:%M:%S",
},
},
"handlers": {
"django_mail_admin": {
"level": "DEBUG",
"class": "logging.StreamHandler",
"formatter": "django_mail_admin"
},
# If you use sentry for logging
'sentry': {
'level': 'ERROR',
'class': 'raven.contrib.django.handlers.SentryHandler',
},
},
'loggers': {
"django_mail_admin": {
"handlers": ["django_mail_admin", "sentry"],
"level": "INFO"
},
},
}
Django Admin integration¶
Integration with Django Admin interface is provided. In there, you can send & receive emails, configure Outbox’es and Mailbox’es,
and if you’ve installed django-admin-row-actions you will have easy access to many features.
The admin interface integration will only be enabled if DJANGO_MAILADMIN_ADMIN_ENABLED setting is set to True (default is True).