Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add tests #40

Open
wants to merge 11 commits into
base: master
Choose a base branch
from
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
*.pyc
*.pyo
*.egg-info
.coverage
tests/mail.txt

gpg_keyring/
htmlcov/
tests/fixtures/
36 changes: 36 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
sudo: false
language: python
env:
- DJANGO_VERSION="Django>=1.8,<1.9"
- DJANGO_VERSION="Django>=1.9,<1.10"
- DJANGO_VERSION="Django>=1.10,<1.11"
- DJANGO_VERSION="Django>=1.11,<2.0"
- DJANGO_VERSION='https://github.com/django/django/archive/master.tar.gz'
python:
# None of the currently supported Django versions support Python 2.6
# - "2.6"
- "2.7"
- "3.4"
- "3.5"
- "3.6"
# matrix:
# exclude:
# # Django 2.0 won't support Python 2.x anymore
# - python: "2.7"
# env: DJANGO_VERSION='https://github.com/django/django/archive/master.tar.gz'
install:
- pip install coverage coveralls flake8 python-gnupg
- pip install -q "$DJANGO_VERSION"
before_script:
# Make sure we have gpg installed; this also logs the version of GPG
- gpg --version
script:
- flake8 email_extras --exclude=email_extras/migrations
- coverage run --include=email_extras/*.py manage.py migrate
- coverage run --include=email_extras/*.py --omit=email_extras/migrations/*.py manage.py test tests
after_script:
- coverage combine
- coveralls
matrix:
allow_failures:
- env: DJANGO_VERSION='https://github.com/django/django/archive/master.tar.gz'
133 changes: 107 additions & 26 deletions README.rst
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
.. image:: https://travis-ci.org/stephenmcd/django-email-extras.svg?branch=master
:target: https://travis-ci.org/stephenmcd/django-email-extras

.. image:: https://coveralls.io/repos/github/stephenmcd/django-email-extras/badge.svg
:target: https://coveralls.io/github/stephenmcd/django-email-extras


Created by `Stephen McDonald <http://twitter.com/stephen_mcd>`_

Introduction
Expand All @@ -17,21 +24,25 @@ local web browser during development is also provided.
Dependencies
============

* `python-gnupg <https://bitbucket.org/vinay.sajip/python-gnupg>`_ is
required for sending PGP encrypted email.
* `python-gnupg <https://bitbucket.org/vinay.sajip/python-gnupg>`_ is
required for sending PGP encrypted email.


Installation
============

The easiest way to install django-email-extras is directly from PyPi
using `pip <https://pip.pypa.io/en/stable/>`_ by running the command
below::
below:

.. code-block:: bash

$ pip install -U django-email-extras

Otherwise you can download django-email-extras and install it directly
from source::
from source:

.. code-block:: bash

$ python setup.py install

Expand All @@ -43,8 +54,8 @@ Once installed, first add ``email_extras`` to your ``INSTALLED_APPS``
setting and run the migrations. Then there are two functions for sending email
in the ``email_extras.utils`` module:

* ``send_mail``
* ``send_mail_template``
* ``send_mail``
* ``send_mail_template``

The former mimics the signature of ``django.core.mail.send_mail``
while the latter provides the ability to send multipart emails
Expand Down Expand Up @@ -75,15 +86,83 @@ When an ``Address`` is deleted via the Django Admin, the key is
removed from the key ring on the server.


Sending PGP Signed Email
========================

Adding a private/public signing keypair is different than importing a
public encryption key, since the private key will be stored on the
server.

This project ships with a Django management command to generate and
export private signing keys: ``email_signing_key``
management command.

You first need to set the ``EMAIL_EXTRAS_SIGNING_KEY_DATA`` option in your project's
``settings.py``. This is a dictionary that is passed as keyword arguments
directly to ``GPG.gen_key()``, so please read and understand all of the
available `options in their documentation <https://pythonhosted.org/python-gnupg/#generating-keys>`_. The default settings are:

.. code-block:: python

EMAIL_EXTRAS_SIGNING_KEY_DATA = {
'key_type': "RSA",
'key_length': 4096,
'name_real': settings.SITE_NAME,
'name_comment': "Outgoing email server",
'name_email': settings.DEFAULT_FROM_EMAIL,
'expire_date': '2y',
}

You may wish to change the ``key_type`` to a signing-only type of key,
such as DSA, or the expire date.

Once you are content with the signing key settings, generate a new
signing key with the ``--generate`` option:

.. code-block:: bash

python manage.py email_signing_key --generate

To work with specific keys, identify them by their fingerprint

.. code-block:: bash

python manage.py email_signing_key 7AB59FE794A7AC12EBA87507EF33F601153CFE28

You can print the private key to your terminal/console with:

.. code-block:: bash

python manage.py email_signing_key 7AB59FE794A7AC12EBA87507EF33F601153CFE28 --print-private-key

And you can upload the public signing key to one or more specified
keyservers by passing the key server hostnames with the ``-k`` or
``--keyserver`` options:

.. code-block:: bash

python manage.py email_signing_key 7AB59FE794A7AC12EBA87507EF33F601153CFE28 -k keys.ubuntu.com keys.redhat.com -k pgp.mit.edu

You can also perform all tasks with one command:

.. code-block:: bash

python manage.py email_signing_key --generate --keyserver pgp.mit.edu --print-private-key

Use the ``--help`` option to see the complete help text for the command.


Sending Multipart Email with Django Templates
=============================================

As mentioned above, the following function is provided in
the ``email_extras.utils`` module::
the ``email_extras.utils`` module:

.. code-block:: python

send_mail_template(subject, template, addr_from, addr_to,
fail_silently=False, attachments=None, context=None,
headers=None)
send_mail_template(subject, template, addr_from, addr_to,
fail_silently=False, attachments=None, context=None,
headers=None)

The arguments that differ from ``django.core.mail.send_mail`` are
``template`` and ``context``. The ``template`` argument is simply
Expand All @@ -95,8 +174,8 @@ the ``email_extras`` directory where your templates are stored,
therefore if the name ``contact_form`` was given for the ``template``
argument, the two template files for the email would be:

* ``templates/email_extras/contact_form.html``
* ``templates/email_extras/contact_form.txt``
* ``templates/email_extras/contact_form.html``
* ``templates/email_extras/contact_form.txt``

The ``attachments`` argument is a list of files to attach to the email.
Each attachment can be the full filesystem path to the file, or a
Expand All @@ -117,18 +196,18 @@ Configuration
There are two settings you can configure in your project's
``settings.py`` module:

* ``EMAIL_EXTRAS_USE_GNUPG`` - Boolean that controls whether the PGP
encryption features are used. Defaults to ``True`` if
``EMAIL_EXTRAS_GNUPG_HOME`` is specified, otherwise ``False``.
* ``EMAIL_EXTRAS_GNUPG_HOME`` - String representing a custom location
for the GNUPG keyring.
* ``EMAIL_EXTRAS_GNUPG_ENCODING`` - String representing a gnupg encoding.
Defaults to GNUPG ``latin-1`` and could be changed to e.g. ``utf-8``
if needed. Check out
`python-gnupg docs <https://pythonhosted.org/python-gnupg/#getting-started>`_
for more info.
* ``EMAIL_EXTRAS_ALWAYS_TRUST_KEYS`` - Skip key validation and assume
that used keys are always fully trusted.
* ``EMAIL_EXTRAS_USE_GNUPG`` - Boolean that controls whether the PGP
encryption features are used. Defaults to ``True`` if
``EMAIL_EXTRAS_GNUPG_HOME`` is specified, otherwise ``False``.
* ``EMAIL_EXTRAS_GNUPG_HOME`` - String representing a custom location
for the GNUPG keyring.
* ``EMAIL_EXTRAS_GNUPG_ENCODING`` - String representing a gnupg encoding.
Defaults to GNUPG ``latin-1`` and could be changed to e.g. ``utf-8``
if needed. Check out
`python-gnupg docs <https://pythonhosted.org/python-gnupg/#getting-started>`_
for more info.
* ``EMAIL_EXTRAS_ALWAYS_TRUST_KEYS`` - Skip key validation and assume
that used keys are always fully trusted.


Local Browser Testing
Expand All @@ -138,9 +217,11 @@ When sending multipart emails during development, it can be useful
to view the HTML part of the email in a web browser, without having
to actually send emails and open them in a mail client. To use
this feature during development, simply set your email backend as follows
in your development ``settings.py`` module::
in your development ``settings.py`` module:

.. code-block:: python

EMAIL_BACKEND = 'email_extras.backends.BrowsableEmailBackend'
EMAIL_BACKEND = 'email_extras.backends.BrowsableEmailBackend'

With this configured, each time a multipart email is sent, it will
be written to a temporary file, which is then automatically opened
Expand Down
1 change: 0 additions & 1 deletion email_extras/admin.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@

from email_extras.settings import USE_GNUPG


Expand Down
7 changes: 7 additions & 0 deletions email_extras/apps.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
from django.apps import AppConfig

from email_extras.utils import check_signing_key


class EmailExtrasConfig(AppConfig):
name = 'email_extras'
verbose_name = 'Email Extras'

# AFAICT, this is impossible to test
def ready(self): # pragma: noqa
# Fail early and loudly if the signing key fingerprint is misconfigured
check_signing_key()
Loading