Development of an internal social media platform with personalised dashboards for students
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

METADATA 23KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685
  1. Metadata-Version: 2.0
  2. Name: django-post-office
  3. Version: 3.1.0
  4. Summary: A Django app to monitor and send mail asynchronously, complete with template support.
  5. Home-page: https://github.com/ui/django-post_office
  6. Author: Selwin Ong
  7. Author-email: selwin.ong@gmail.com
  8. License: MIT
  9. Description-Content-Type: UNKNOWN
  10. Platform: UNKNOWN
  11. Classifier: Development Status :: 5 - Production/Stable
  12. Classifier: Environment :: Web Environment
  13. Classifier: Framework :: Django
  14. Classifier: Intended Audience :: Developers
  15. Classifier: License :: OSI Approved :: MIT License
  16. Classifier: Operating System :: OS Independent
  17. Classifier: Programming Language :: Python
  18. Classifier: Programming Language :: Python :: 2
  19. Classifier: Programming Language :: Python :: 2.7
  20. Classifier: Programming Language :: Python :: 3
  21. Classifier: Programming Language :: Python :: 3.3
  22. Classifier: Programming Language :: Python :: 3.4
  23. Classifier: Programming Language :: Python :: 3.5
  24. Classifier: Programming Language :: Python :: 3.6
  25. Classifier: Topic :: Internet :: WWW/HTTP
  26. Classifier: Topic :: Software Development :: Libraries :: Python Modules
  27. Requires-Dist: django (>=1.8)
  28. Requires-Dist: jsonfield
  29. Provides-Extra: test
  30. Requires-Dist: tox (>=2.3); extra == 'test'
  31. ==================
  32. Django Post Office
  33. ==================
  34. Django Post Office is a simple app to send and manage your emails in Django.
  35. Some awesome features are:
  36. * Allows you to send email asynchronously
  37. * Multi backend support
  38. * Supports HTML email
  39. * Supports database based email templates
  40. * Built in scheduling support
  41. * Works well with task queues like `RQ <http://python-rq.org>`_ or `Celery <http://www.celeryproject.org>`_
  42. * Uses multiprocessing (and threading) to send a large number of emails in parallel
  43. * Supports multilingual email templates (i18n)
  44. Dependencies
  45. ============
  46. * `django >= 1.8 <http://djangoproject.com/>`_
  47. * `django-jsonfield <https://github.com/bradjasper/django-jsonfield>`_
  48. Installation
  49. ============
  50. |Build Status|
  51. * Install from PyPI (or you `manually download from PyPI <http://pypi.python.org/pypi/django-post_office>`_)::
  52. pip install django-post_office
  53. * Add ``post_office`` to your INSTALLED_APPS in django's ``settings.py``:
  54. .. code-block:: python
  55. INSTALLED_APPS = (
  56. # other apps
  57. "post_office",
  58. )
  59. * Run ``migrate``::
  60. python manage.py migrate
  61. * Set ``post_office.EmailBackend`` as your ``EMAIL_BACKEND`` in django's ``settings.py``:
  62. .. code-block:: python
  63. EMAIL_BACKEND = 'post_office.EmailBackend'
  64. Quickstart
  65. ==========
  66. Send a simple email is really easy:
  67. .. code-block:: python
  68. from post_office import mail
  69. mail.send(
  70. 'recipient@example.com', # List of email addresses also accepted
  71. 'from@example.com',
  72. subject='My email',
  73. message='Hi there!',
  74. html_message='Hi <strong>there</strong>!',
  75. )
  76. If you want to use templates, ensure that Django's admin interface is enabled. Create an
  77. ``EmailTemplate`` instance via ``admin`` and do the following:
  78. .. code-block:: python
  79. from post_office import mail
  80. mail.send(
  81. 'recipient@example.com', # List of email addresses also accepted
  82. 'from@example.com',
  83. template='welcome_email', # Could be an EmailTemplate instance or name
  84. context={'foo': 'bar'},
  85. )
  86. The above command will put your email on the queue so you can use the
  87. command in your webapp without slowing down the request/response cycle too much.
  88. To actually send them out, run ``python manage.py send_queued_mail``.
  89. You can schedule this management command to run regularly via cron::
  90. * * * * * (/usr/bin/python manage.py send_queued_mail >> send_mail.log 2>&1)
  91. or, if you use uWSGI_ as application server, add this short snipped to the
  92. project's ``wsgi.py`` file:
  93. .. code-block:: python
  94. from django.core.wsgi import get_wsgi_application
  95. application = get_wsgi_application()
  96. # add this block of code
  97. try:
  98. import uwsgidecorators
  99. from django.core.management import call_command
  100. @uwsgidecorators.timer(10)
  101. def send_queued_mail(num):
  102. """Send queued mail every 10 seconds"""
  103. call_command('send_queued_mail', processes=1)
  104. except ImportError:
  105. print("uwsgidecorators not found. Cron and timers are disabled")
  106. Alternatively you can also use the decorator ``@uwsgidecorators.cron(minute, hour, day, month, weekday)``.
  107. This will schedule a task at specific times. Use ``-1`` to signal any time, it corresponds to the ``*``
  108. in cron.
  109. Please note that ``uwsgidecorators`` are available only, if the application has been started
  110. with **uWSGI**. However, Django's internal ``./manange.py runserver`` also access this file,
  111. therefore wrap the block into an exception handler as shown above.
  112. This configuration is very useful in environments, such as Docker containers, where you
  113. don't have a running cron-daemon.
  114. Usage
  115. =====
  116. mail.send()
  117. -----------
  118. ``mail.send`` is the most important function in this library, it takes these
  119. arguments:
  120. +--------------------+----------+--------------------------------------------------+
  121. | Argument | Required | Description |
  122. +--------------------+----------+--------------------------------------------------+
  123. | recipients | Yes | list of recipient email addresses |
  124. +--------------------+----------+--------------------------------------------------+
  125. | sender | No | Defaults to ``settings.DEFAULT_FROM_EMAIL``, |
  126. | | | display name is allowed (``John <john@a.com>``) |
  127. +--------------------+----------+--------------------------------------------------+
  128. | subject | No | Email subject (if ``template`` is not specified) |
  129. +--------------------+----------+--------------------------------------------------+
  130. | message | No | Email content (if ``template`` is not specified) |
  131. +--------------------+----------+--------------------------------------------------+
  132. | html_message | No | HTML content (if ``template`` is not specified) |
  133. +--------------------+----------+--------------------------------------------------+
  134. | template | No | ``EmailTemplate`` instance or name |
  135. +--------------------+----------+--------------------------------------------------+
  136. | language | No | Language in which you want to send the email in |
  137. | | | (if you have multilingual email templates.) |
  138. +--------------------+----------+--------------------------------------------------+
  139. | cc | No | list emails, will appear in ``cc`` field |
  140. +--------------------+----------+--------------------------------------------------+
  141. | bcc | No | list of emails, will appear in `bcc` field |
  142. +--------------------+----------+--------------------------------------------------+
  143. | attachments | No | Email attachments - A dictionary where the keys |
  144. | | | are the filenames and the values are either: |
  145. | | | |
  146. | | | * files |
  147. | | | * file-like objects |
  148. | | | * full path of the file |
  149. +--------------------+----------+--------------------------------------------------+
  150. | context | No | A dictionary, used to render templated email |
  151. +--------------------+----------+--------------------------------------------------+
  152. | headers | No | A dictionary of extra headers on the message |
  153. +--------------------+----------+--------------------------------------------------+
  154. | scheduled_time | No | A date/datetime object indicating when the email |
  155. | | | should be sent |
  156. +--------------------+----------+--------------------------------------------------+
  157. | priority | No | ``high``, ``medium``, ``low`` or ``now`` |
  158. | | | (send_immediately) |
  159. +--------------------+----------+--------------------------------------------------+
  160. | backend | No | Alias of the backend you want to use. |
  161. | | | ``default`` will be used if not specified. |
  162. +--------------------+----------+--------------------------------------------------+
  163. | render_on_delivery | No | Setting this to ``True`` causes email to be |
  164. | | | lazily rendered during delivery. ``template`` |
  165. | | | is required when ``render_on_delivery`` is True. |
  166. | | | This way content is never stored in the DB. |
  167. | | | May result in significant space savings. |
  168. +--------------------+----------+--------------------------------------------------+
  169. Here are a few examples.
  170. If you just want to send out emails without using database templates. You can
  171. call the ``send`` command without the ``template`` argument.
  172. .. code-block:: python
  173. from post_office import mail
  174. mail.send(
  175. ['recipient1@example.com'],
  176. 'from@example.com',
  177. subject='Welcome!',
  178. message='Welcome home, {{ name }}!',
  179. html_message='Welcome home, <b>{{ name }}</b>!',
  180. headers={'Reply-to': 'reply@example.com'},
  181. scheduled_time=date(2014, 1, 1),
  182. context={'name': 'Alice'},
  183. )
  184. ``post_office`` is also task queue friendly. Passing ``now`` as priority into
  185. ``send_mail`` will deliver the email right away (instead of queuing it),
  186. regardless of how many emails you have in your queue:
  187. .. code-block:: python
  188. from post_office import mail
  189. mail.send(
  190. ['recipient1@example.com'],
  191. 'from@example.com',
  192. template='welcome_email',
  193. context={'foo': 'bar'},
  194. priority='now',
  195. )
  196. This is useful if you already use something like `django-rq <https://github.com/ui/django-rq>`_
  197. to send emails asynchronously and only need to store email related activities and logs.
  198. If you want to send an email with attachments:
  199. .. code-block:: python
  200. from django.core.files.base import ContentFile
  201. from post_office import mail
  202. mail.send(
  203. ['recipient1@example.com'],
  204. 'from@example.com',
  205. template='welcome_email',
  206. context={'foo': 'bar'},
  207. priority='now',
  208. attachments={
  209. 'attachment1.doc': '/path/to/file/file1.doc',
  210. 'attachment2.txt': ContentFile('file content'),
  211. 'attachment3.txt': { 'file': ContentFile('file content'), 'mimetype': 'text/plain'},
  212. }
  213. )
  214. Template Tags and Variables
  215. ---------------------------
  216. ``post-office`` supports Django's template tags and variables.
  217. For example, if you put "Hello, {{ name }}" in the subject line and pass in
  218. ``{'name': 'Alice'}`` as context, you will get "Hello, Alice" as subject:
  219. .. code-block:: python
  220. from post_office.models import EmailTemplate
  221. from post_office import mail
  222. EmailTemplate.objects.create(
  223. name='morning_greeting',
  224. subject='Morning, {{ name|capfirst }}',
  225. content='Hi {{ name }}, how are you feeling today?',
  226. html_content='Hi <strong>{{ name }}</strong>, how are you feeling today?',
  227. )
  228. mail.send(
  229. ['recipient@example.com'],
  230. 'from@example.com',
  231. template='morning_greeting',
  232. context={'name': 'alice'},
  233. )
  234. # This will create an email with the following content:
  235. subject = 'Morning, Alice',
  236. content = 'Hi alice, how are you feeling today?'
  237. content = 'Hi <strong>alice</strong>, how are you feeling today?'
  238. Multilingual Email Templates
  239. ----------------------------
  240. You can easily create email templates in various different languanges.
  241. For example:
  242. .. code-block:: python
  243. template = EmailTemplate.objects.create(
  244. name='hello',
  245. subject='Hello world!',
  246. )
  247. # Add an Indonesian version of this template:
  248. indonesian_template = template.translated_templates.create(
  249. language='id',
  250. subject='Halo Dunia!'
  251. )
  252. Sending an email using template in a non default languange is
  253. also similarly easy:
  254. .. code-block:: python
  255. mail.send(
  256. ['recipient@example.com'],
  257. 'from@example.com',
  258. template=template, # Sends using the default template
  259. )
  260. mail.send(
  261. ['recipient@example.com'],
  262. 'from@example.com',
  263. template=template,
  264. language='id', # Sends using Indonesian template
  265. )
  266. Custom Email Backends
  267. ---------------------
  268. By default, ``post_office`` uses django's ``smtp.EmailBackend``. If you want to
  269. use a different backend, you can do so by configuring ``BACKENDS``.
  270. For example if you want to use `django-ses <https://github.com/hmarr/django-ses>`_::
  271. POST_OFFICE = {
  272. 'BACKENDS': {
  273. 'default': 'smtp.EmailBackend',
  274. 'ses': 'django_ses.SESBackend',
  275. }
  276. }
  277. You can then choose what backend you want to use when sending mail:
  278. .. code-block:: python
  279. # If you omit `backend_alias` argument, `default` will be used
  280. mail.send(
  281. ['recipient@example.com'],
  282. 'from@example.com',
  283. subject='Hello',
  284. )
  285. # If you want to send using `ses` backend
  286. mail.send(
  287. ['recipient@example.com'],
  288. 'from@example.com',
  289. subject='Hello',
  290. backend='ses',
  291. )
  292. Management Commands
  293. -------------------
  294. * ``send_queued_mail`` - send queued emails, those aren't successfully sent
  295. will be marked as ``failed``. Accepts the following arguments:
  296. +---------------------------+--------------------------------------------------+
  297. | Argument | Description |
  298. +---------------------------+--------------------------------------------------+
  299. | ``--processes`` or ``-p`` | Number of parallel processes to send email. |
  300. | | Defaults to 1 |
  301. +---------------------------+--------------------------------------------------+
  302. | ``--lockfile`` or ``-L`` | Full path to file used as lock file. Defaults to |
  303. | | ``/tmp/post_office.lock`` |
  304. +---------------------------+--------------------------------------------------+
  305. * ``cleanup_mail`` - delete all emails created before an X number of days
  306. (defaults to 90).
  307. +---------------------------+--------------------------------------------------+
  308. | Argument | Description |
  309. +---------------------------+--------------------------------------------------+
  310. | ``--days`` or ``-d`` | Email older than this argument will be deleted. |
  311. | | Defaults to 90 |
  312. +---------------------------+--------------------------------------------------+
  313. | ``--delete-attachments`` | Flag to delete orphaned attachment records and |
  314. | or ``-da`` | files on disk. If flag is not set, |
  315. | | on disk attachments files won't be deleted. |
  316. +---------------------------+--------------------------------------------------+
  317. You may want to set these up via cron to run regularly::
  318. * * * * * (cd $PROJECT; python manage.py send_queued_mail --processes=1 >> $PROJECT/cron_mail.log 2>&1)
  319. 0 1 * * * (cd $PROJECT; python manage.py cleanup_mail --days=30 --delete-attachments >> $PROJECT/cron_mail_cleanup.log 2>&1)
  320. Settings
  321. ========
  322. This section outlines all the settings and configurations that you can put
  323. in Django's ``settings.py`` to fine tune ``post-office``'s behavior.
  324. Batch Size
  325. ----------
  326. If you may want to limit the number of emails sent in a batch (sometimes useful
  327. in a low memory environment), use the ``BATCH_SIZE`` argument to limit the
  328. number of queued emails fetched in one batch.
  329. .. code-block:: python
  330. # Put this in settings.py
  331. POST_OFFICE = {
  332. 'BATCH_SIZE': 50
  333. }
  334. Default Priority
  335. ----------------
  336. The default priority for emails is ``medium``, but this can be altered by
  337. setting ``DEFAULT_PRIORITY``. Integration with asynchronous email backends
  338. (e.g. based on Celery) becomes trivial when set to ``now``.
  339. .. code-block:: python
  340. # Put this in settings.py
  341. POST_OFFICE = {
  342. 'DEFAULT_PRIORITY': 'now'
  343. }
  344. Log Level
  345. ---------
  346. The default log level is 2 (logs both successful and failed deliveries)
  347. This behavior can be changed by setting ``LOG_LEVEL``.
  348. .. code-block:: python
  349. # Put this in settings.py
  350. POST_OFFICE = {
  351. 'LOG_LEVEL': 1 # Log only failed deliveries
  352. }
  353. The different options are:
  354. * ``0`` logs nothing
  355. * ``1`` logs only failed deliveries
  356. * ``2`` logs everything (both successful and failed delivery attempts)
  357. Sending Order
  358. -------------
  359. The default sending order for emails is ``-priority``, but this can be altered by
  360. setting ``SENDING_ORDER``. For example, if you want to send queued emails in FIFO order :
  361. .. code-block:: python
  362. # Put this in settings.py
  363. POST_OFFICE = {
  364. 'SENDING_ORDER': ['created']
  365. }
  366. Context Field Serializer
  367. ------------------------
  368. If you need to store complex Python objects for deferred rendering
  369. (i.e. setting ``render_on_delivery=True``), you can specify your own context
  370. field class to store context variables. For example if you want to use
  371. `django-picklefield <https://github.com/gintas/django-picklefield/tree/master/src/picklefield>`_:
  372. .. code-block:: python
  373. # Put this in settings.py
  374. POST_OFFICE = {
  375. 'CONTEXT_FIELD_CLASS': 'picklefield.fields.PickledObjectField'
  376. }
  377. ``CONTEXT_FIELD_CLASS`` defaults to ``jsonfield.JSONField``.
  378. Logging
  379. -------
  380. You can configure ``post-office``'s logging from Django's ``settings.py``. For
  381. example:
  382. .. code-block:: python
  383. LOGGING = {
  384. "version": 1,
  385. "disable_existing_loggers": False,
  386. "formatters": {
  387. "post_office": {
  388. "format": "[%(levelname)s]%(asctime)s PID %(process)d: %(message)s",
  389. "datefmt": "%d-%m-%Y %H:%M:%S",
  390. },
  391. },
  392. "handlers": {
  393. "post_office": {
  394. "level": "DEBUG",
  395. "class": "logging.StreamHandler",
  396. "formatter": "post_office"
  397. },
  398. # If you use sentry for logging
  399. 'sentry': {
  400. 'level': 'ERROR',
  401. 'class': 'raven.contrib.django.handlers.SentryHandler',
  402. },
  403. },
  404. 'loggers': {
  405. "post_office": {
  406. "handlers": ["post_office", "sentry"],
  407. "level": "INFO"
  408. },
  409. },
  410. }
  411. Threads
  412. -------
  413. ``post-office`` >= 3.0 allows you to use multiple threads to dramatically speed up
  414. the speed at which emails are sent. By default, ``post-office`` uses 5 threads per process.
  415. You can tweak this setting by changing ``THREADS_PER_PROCESS`` setting.
  416. This may dramatically increase the speed of bulk email delivery, depending on which email
  417. backends you use. In my tests, multi threading speeds up email backends that use HTTP based
  418. (REST) delivery mechanisms but doesn't seem to help SMTP based backends.
  419. .. code-block:: python
  420. # Put this in settings.py
  421. POST_OFFICE = {
  422. 'THREADS_PER_PROCESS': 10
  423. }
  424. Performance
  425. ===========
  426. Caching
  427. -------
  428. if Django's caching mechanism is configured, ``post_office`` will cache
  429. ``EmailTemplate`` instances . If for some reason you want to disable caching,
  430. set ``POST_OFFICE_CACHE`` to ``False`` in ``settings.py``:
  431. .. code-block:: python
  432. ## All cache key will be prefixed by post_office:template:
  433. ## To turn OFF caching, you need to explicitly set POST_OFFICE_CACHE to False in settings
  434. POST_OFFICE_CACHE = False
  435. ## Optional: to use a non default cache backend, add a "post_office" entry in CACHES
  436. CACHES = {
  437. 'post_office': {
  438. 'BACKEND': 'django.core.cache.backends.memcached.PyLibMCCache',
  439. 'LOCATION': '127.0.0.1:11211',
  440. }
  441. }
  442. send_many()
  443. -----------
  444. ``send_many()`` is much more performant (generates less database queries) when
  445. sending a large number of emails. ``send_many()`` is almost identical to ``mail.send()``,
  446. with the exception that it accepts a list of keyword arguments that you'd
  447. usually pass into ``mail.send()``:
  448. .. code-block:: python
  449. from post_office import mail
  450. first_email = {
  451. 'sender': 'from@example.com',
  452. 'recipients': ['alice@example.com'],
  453. 'subject': 'Hi!',
  454. 'message': 'Hi Alice!'
  455. }
  456. second_email = {
  457. 'sender': 'from@example.com',
  458. 'recipients': ['bob@example.com'],
  459. 'subject': 'Hi!',
  460. 'message': 'Hi Bob!'
  461. }
  462. kwargs_list = [first_email, second_email]
  463. mail.send_many(kwargs_list)
  464. Attachments are not supported with ``mail.send_many()``.
  465. Running Tests
  466. =============
  467. To run the test suite::
  468. `which django-admin.py` test post_office --settings=post_office.test_settings --pythonpath=.
  469. You can run the full test suite with::
  470. tox
  471. or::
  472. python setup.py test
  473. Changelog
  474. =========
  475. Version 3.1.0 (2018-07-24)
  476. --------------------------
  477. * Improvements to attachments are handled. Thanks @SeiryuZ!
  478. * Added ``--delete-attachments`` flag to ``cleanup_mail`` management command. Thanks @Seiryuz!
  479. * I18n improvements. Thanks @vsevolod-skripnik and @delneg!
  480. * Django admin improvements. Thanks @kakulukia!
  481. Version 3.0.4
  482. -------------
  483. * Added compatibility with Django 2.0. Thanks @PreActionTech and @PetrDlouhy!
  484. * Added natural key support to `EmailTemplate` model. Thanks @maximlomakin!
  485. Version 3.0.2
  486. -------------
  487. - Fixed memory leak when multiprocessing is used.
  488. - Fixed a possible error when adding a new email from Django admin. Thanks @ivlevdenis!
  489. Version 3.0.2
  490. -------------
  491. - `_send_bulk` now properly catches exceptions when preparing email messages.
  492. Version 3.0.1
  493. -------------
  494. - Fixed an infinite loop bug in `send_queued_mail` management command.
  495. Version 3.0.0
  496. -------------
  497. * `_send_bulk` now allows each process to use multiple threads to send emails.
  498. * Added support for mimetypes in email attachments. Thanks @clickonchris!
  499. * An `EmailTemplate` can now be used as defaults multiple times in one language. Thanks @sac7e!
  500. * `send_queued_mail` management command will now check whether there are more queued emails to be sent before exiting.
  501. * Drop support for Django < 1.8. Thanks @fendyh!
  502. Full changelog can be found `here <https://github.com/ui/django-post_office/blob/master/CHANGELOG.md>`_.
  503. Created and maintained by the cool guys at `Stamps <https://stamps.co.id>`_,
  504. Indonesia's most elegant CRM/loyalty platform.
  505. .. |Build Status| image:: https://travis-ci.org/ui/django-post_office.png?branch=master
  506. :target: https://travis-ci.org/ui/django-post_office
  507. .. _uWSGI: https://uwsgi-docs.readthedocs.org/en/latest/