В подавляющем большинстве проектов используется отправка сообщений на почтовые адреса клиентов/админов/отделов. На сколько утомительно каждый раз создавать шаблоны на файловой системе, задавать сигналы, использовать часто дублирующийся код для рендеринга и отправки.
В конечном итоге встают задачи о фоновой отправке, об изменениях отправителя, приоритизации, повторной отправке сообщения в случае неудачи, частом редактировании по просьбе клиента/маркетологов, прикреплению к письму стандартных файлов в виде каких-то инструкций по применению продукта, или же стандартных документов, отчетов по клиентам, переводам и тд и тп.
В больших проектах часто необходимо визуально разделять шаблоны на категории, для фильтрации, дабы не тратить время на редактирование менее важных шаблонов при рефакторинге, и во избежание путаницы с новым контентом, или при работе со старым.
Для подобных решений существует простая батарейка, призванная решить большинство подобных проблем, и избавить Вас от лишнего кода, сопровождения и нервотрепки.
django-db-mailer — открытая и простая в использовании батарейка, для отправки почтовых сообщений, рассылок и отложенных уведомлений. Не требует особых знаний или нестандартных настроек. Вам всего лишь необходимо установить пакет, настроить систему очередей Celery в связке с Redis, и можно начинать заниматься творческой работой.
Что же умеет батарейка из коробки?
1. Простой и удобный функциональный интерфейс, для отправки писем.
2. Работа в указанной очереди (необходимо когда в проекте все разбито на разные сервера и воркеры).
3. Возможность переотправки сообщения в случае неудачи (есть возможность задать кол-во попыток в БД и в коде).
4. Таймауты
5. Логирование (вы всегда можете посмотреть какие сообщение были отправлены удачно/неудачно. полезно при расследовании жалоб от пользователей).
6. Категории (быстрая фильтрация разнородных шаблонов. каталогизация по аппам и тд и тп).
7. Группы получателей (удобно для разделения на отделы внутри компании и задание адресов получателей в админке).
8. Сигналы (отправка сообщений по событию post_save/pre_save & etc. настраивается прямо в админке).
9. Отложенная отправка сообщений (хорошо для всяких промо, а так же при использовании транзакций во вьюхах).
10. Встроенный браузер полей в моделях (не нужно лезть в код, что бы просмотреть доступные для использования поля. не дрегают вас, и вы сами не лезите в код).
11. Система приоритизации (возможность задать приоритет сообщению в БД/Коде).
12. Редактирование шаблонов прямо в админке (для саппорта, менеджеров — самое оно. не отнимает время программиста).
13. Шаблоны кешируются — при каждой отправке сообщения нет обращений к БД (шаблоны и настройки читаются из кеша, что снижает нагрузку на БД. Бекенд на Ваш вкус).
14. Визуальный редактор TinyMCE (по желанию).
15. Версионирование изменений в шаблонах. Всегда можно откатиться (бывают случаи, когда без этого никак не обойтись).
16. Локализация батарейки Русский/English.
17. Тестирование сообщений прямо из админки (возможно создать шаблон и сразу же получить пример на почтовый ящик текущего пользователя).
18. Из коробки поддерживается популярная тема django-grappelli.
19. Типы письма html и text (возможность указания типа шаблона).
20. Возможность использовать все встроенные возможности мейлера джанги.
21. Bcc — можно дублировать все письма на указанные адреса (бывает полезно для логирования с текстом. по умолчанию тело письма не логируется в БД из соображений безопасности).
22. API — для совместной работы с приложениями на других языках/платформах.
23. Возможность задавать каждому шаблону поле «От» (полезно когда у Вас несколько отделов. особенно удобно при передаче обязанностей в другой отдел).
24. SMTP настройки для адресатов (можно настраивать различные smtp сервера для отправки писем).
25. Прикрепление стандартных файлов (различные вкладыши, документы, инструкции прямо в админке).
26. Мультиязычность шаблонов для локализированных сайтов (один шаблон для мультиязычных сайтов. в зависимости от локали, выбирается язык сообщения).
27. Отключение/Включение оповещений (удобно для дебага, или для временного отключения каких-то промо акций компании).
28. Простая интеграция с такими популярными сервисами как postmark (всего лишь нужно установить python-postmark).
29. Отлов и сортировка по исключениям Python (в случае использовании постмарка, или чего-нибудь еще — удобно отфильтровать и оперативно решить проблему).
30. Просмотр различий между версиями (всегда необходимо видеть кто и что менял в шаблонах, и какова причина ошибки).
31. Отчетность по прочитанным пользователями письмам (включая информацию о geo. но здесь нет никаких гарантий).
Возможности батарейки тесно связаны с Celery и Redis. Точнее — это фоновая отправка, очередь, приоритеты и отложенная отправка.
Хотя большая часть функционала работает и без них. То есть можно пользоваться батарейкой и без каких-либо внешних зависимостей.
Это уже на усмотрение программиста. Сложностей в настройке тех, или иных частей — не составляет проблем. Есть подробная документация.
Вместо Redis можно использовать RabbitMQ, MongoDB и все поддерживаемые Celery бекенды.
К сожалению, в Сelery приоритеты реализованы лишь для Redis. В основе quasi-priorities (не на стороне сервера).
Давайте рассмотрим простой пример для отправки сообщения:
from dbmail import send_db_mail
# данные контекста
settings = Settings.objects.get(user_id=1)
user = User.objects.get(pk=1)
data = {'path': request.path}
# отправка простого сообщения
send_db_mail('welcome-notification', user.email, settings, user, data)
# отправка сообщения с вложенным файлом
send_db_mail('daily-report', user.email, user, data, files=[report_file])
В данном случае мы задаем идентификатор сообщения, указываем получателя, и передаем в контекст 2 модели, которые автоматически распаковываются в шаблоне + словарь.
Мы можем обратиться к полям модели User в шаблоне как к username или email. Но так же остается возможность обратиться к ним в общепринятом виде: user.username.
Более развернутый пример:
send_db_mail(
# идентификатор шаблона в БД
slug='welcome',
# получатели могут быть списком или строкой. Например:
# 'user1@example.com' или 'user1@example.com, user2@example.com', или
# ['user1@example.com', 'user2@example.com'], или же идентификатор
# модели группы MailGroup. Например: developers, support, admins
recipient='user1@example.com',
# Все параметры *args доступны в качестве контекста в шаблоне
{
'username': request.user.username,
'full_name': request.user.get_full_name(),
'signup_date': request.user.date_joined
},
# Если передается модель в контекст, вы получаете доступ ко всем
# распакованным полям.
# Для m2m и fk, необходимо обращаться по module_name (mymodel.user.email).
MyModel.objects.get(pk=1),
# Необязательные дополнительные параметры **kwargs:
# from_email='from@example.com' # от кого
# cc=['cc@example.com'], # копия (надстройки те же, что и для recipient)
# bcc=['bcc@example.com'], # скрытая копия (надстройки те же, что и для recipient)
# user=User.objects.get(pk=1), # пользователь, для логирования в БД
#
# Описание данных опций доступны в официальной доке к Django
# attachments=[(filename, content, mimetype)],
# files=['hello.jpg', 'world.png'],
# headers={'Custom-Header':'Some value'},
#
# queue='default', # очередь
# retry_delay=300, # время до повторной отправки в случае неудачи
# max_retries=3, # максимальное кол-во попыток для переотправки
# retry=True, # разрешить попытку для переотправки
# time_limit=30, # максимальное кол-во времени для отправки
# send_after=60, # отправить письмо через N секунд
#
# use_celery=True, # использовать Celery
#
# Здесь могут быть любые дополнительные опции доступные в django.core.mail.message
)
Установка Демо проекта:
$ sudo apt-get install -y virtualenvwrapper redis-server || brew install pyenv-virtualenvwrapper redis
$ source /usr/share/virtualenvwrapper/virtualenvwrapper.sh || source /usr/local/bin/virtualenvwrapper.sh
$ mkvirtualenv db-mailer
$ workon db-mailer
$ git clone --depth 1 https://github.com/LPgenerator/django-db-mailer.git db-mailer
$ cd db-mailer
$ python setup.py develop
$ cd demo
$ pip install -r requirements.txt
$ python manage.py syncdb --noinput
$ python manage.py migrate --noinput
$ python manage.py createsuperuser --username admin --email admin@local.host
$ python manage.py runserver >& /dev/null &
$ python manage.py celeryd -Q default >& /dev/null &
Запустим shell:
$ python manage.py shell_plus --print-sql
Создадим наш первый шаблон:
>>> from dbmail.models import MailTemplate
>>> from dbmail import send_db_mail
>>>
>>> MailTemplate.objects.create(
... name="Site welcome template",
... subject="Welcome",
... message="Welcome to our site. We are glad to see you.",
... slug="welcome",
... is_html=False,
... )
Отправим письмо:
>>> send_db_mail('welcome', 'user@example.com', use_celery=False)
В первый раз в консоль будут выведены все запросы к БД, а так же само письмо. Во второй раз запросы к БД будут отсутствовать. Только запросы на запись в лог.
Проверим что у нас в логах:
>>> from pprint import pprint
>>> from django.forms.models import model_to_dict
>>> from dbmail.models import MailLog
>>>
>>> pprint([model_to_dict(obj) for obj in MailLog.objects.all()])
Теперь можно заглянуть в админку:
$ xdg-open http://127.0.0.1:8000/admin/dbmail/ >& /dev/null || open http://127.0.0.1:8000/admin/dbmail/ >& /dev/null
Дополнительные возможности:
История
Для сохранения истории изменений/отката, можно установить батарейку django-reversion.
Редактор
Для того что бы редактировать шаблоны в визуальном редакторе, можно поставить батарейку django-tinymce.
Темы
django-db-mailer — поддерживает как нативную тему, так и django-grappelli.
Очереди
Для отправки сообщений в фоне с поддержкой приоритетов, необходима батарейка django-celery.
Мультиязычность
Мультиязычность возможна в связке с django-modeltranslation.
Преобразование CSS
Для преобразования и использования строчного CSS, можно доустановить пакет premailer. Маленький, но полезный помощник для создания кросс-клиентских сообщений.
Отчеты
Отчеты о прочтении и информацию о данных пользователя можно получить установив 2 простые батарейки httpagentparser и django-ipware.
Примечания
Для того что бы работала приоритезация, необходима связка django-celery с брокером Redis.
Старые версии
Если Вам не нужен весь функционал, Вы можете использовать более простую версию батарейки.
Так же можно воспользоваться переменной DB_MAILER_ALLOWED_MODELS_ON_ADMIN, для отключения ненужного функционала в панели администратора.
API
Вы так же можете использовать батарейку в связке с мобильным приложением, либо во внутренних проектах на других языках.
Простой пример:
>>> from dbmail.models import ApiKey
>>> ApiKey.objects.create(name='Test', api_key='ZzriUzE')
$ curl -X POST http://127.0.0.1:8000/dbmail/api/ --data 'api_key=ZzriUzE&slug=welcome&recipient=root@local.host'
Поддержка Django начиная с ветки 1.4 по 1.7. Python 3 на текущий момент еще не поддерживается.
Данная батарейка используется в нескольких больших проектах, и сберегла много времени и нервов.
Надеюсь она будет полезна сообществу Django.
Репозиторий проекта на GitHub.
Pull Request-ы приветствуются.
Автор: gotlium