Skip to content
New issue

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

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

Already on GitHub? # 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