Skip to main content

Django app for managing multiple mailing lists with both plaintext as well as HTML templates (facilitated by Markdown).

Project description

Django Mailinglist

PyPI GitHub Workflow Status PyPI - Python Version PyPI - Django Version Codecov Read the Docs

django-mailinglist is a package for administering outgoing mailing lists to subscribers. This package aims to replace django-newsletter and takes inspiration (and a non-trivial amount of code) from it.

Documentation

Please refer to the full documentation.

Installation

Use pip to install the package

pip install django-mailinglist

Configuration

Add mailinglist to the INSTALLED_APPS list and create settings for MAILINGLIST_BASE_URL and MAILINGLIST_DEFAULT_SENDER_EMAIL:

INSTALLED_APPS = [
    ...
    "mailinglist",
    ...
]
MAILINGLIST_BASE_URL = "https://www.mygreatmailingeservice.lol"  # NO TRAILING SLASH PLEASE
MAILINGLIST_DEFAULT_SENDER_EMAIL = "prime_mover@mygreatmailingservice.lol"

Add urls to project so that archive, subscribe, and unsubscribe functionality will be available.

urlpatterns = [
    ...
    path("mailinglist/", include("mailinglist.urls", namespace="mailinglist")),
    ...
]

Settings

Settings (and their defaults) are outlined below:

  • (required) MAILINGLIST_BASE_URL : Specify the base url (including protocol! No trailing slash!) for linkbacks to the archive and unsubscribe links.
  • (required) MAILINGLIST_DEFAULT_SENDER_EMAIL : The default email address for communication with subscribers.
  • MAILINGLIST_DEFAULT_SENDER_NAME = "Administrator : The name or title of the person who will manage subscribers.
  • MAILINGLIST_USER_MODEL = settings.AUTH_USER_MODEL : Specify the pool of potential subscribers; this doesn't have to be the same model that you use for authenticating users to your project.
  • MAILINGLIST_HOOKSET = "mailinglist.hooks.MailinglistDefaultHookset" : You may provide a class which provides the hooks found in the package module to override certain behaviors (sending email mostly).
  • MAILINGLIST_CONFIRM_EMAIL_SUBSCRIBE = True : Should new subscribers be sent an email to verify their email address?
  • MAILINGLIST_EMAIL_DELAY = 0.1 : Amount of seconds to wait between sending an individual email.
  • MAILINGLIST_BATCH_SIZE = 200 : The number of individual email which constitute a "batch".
  • MAILINGLIST_BATCH_DELAY = 10 : Amount of seconds to wait after completing a "batch".

Functionality

This package takes many design cues from django-newsletter, chief among those are the data models. A major difference is in the Subscription model which sources user data from the model defined in MAILINGLIST_USER_MODEL, no email addresses are stored in django-newsletter models!

Mailing List

Admin views are provided for managing mailing lists. A mailing list must exist prior to any subscriptions or messages.

Subscription

User data

You must provide your own form(s) for collecting and persisting user data. Any subclass of the AbstractUser model will suffice for holding user data, but the only requirements (by default) for this package are a get_full_name method and email attribute. The data used in messages is highly configurable by providing your own message templates.

Subscriptions proper

django-mailinglist provides a service class for managing subscriptions, as such the Subscription model should not be used for creating subscriptions. Views are provided to illustrate the use of the service class, please reference mailinglist/views.py for patterns. The provided admin forms also illustrate an appropriate pattern. Adding a subscription for a user is done like so:

from mailinglist.services import SubscriptionService

SubscriptionService().subscribe(user=user, mailing_list=mailing_list)

The service code will send a subscription confirmation email to the user (by default), the user will find a link to click which will complete their subscription. If the MAILINGLIST_CONFIRM_EMAIL_SUBSCRIBE setting is set False then no email will be sent, the user will immediately be subscribed; this is only recommended if you are already verifying email addresses as part of user registration.

Subscription change events are logged whenever a subscription is changed, a timestamp of each subscription or unsubscription is available in the admin.

Unsubscription

Unsubscribe links will go out with each email. These are personalized links which contain a token to unsubscribe that particular user only; when the user clicks the link they will be marked as unsubscribed and will no longer receive messages on that mailing list.

Message

Messages belong to a certain mailing list and are comprised of message parts. Message parts may have a heading and text. The text supports markdown.

Submission

Finally, submissions are the means by which a message is published and sent. An admin action exists to "publish" a submission, which will mark it as ready for sending

Sending

The management command process_submissions will go through the sending action for all published submissions. Receiver lists are rendered at the time of sending to include all subscribed users and to exclude any users who have joined the global deny list. Each subscriber gets a message rendered solely for them which contains an unsubscribe link. Each sending is logged with a timestamp so that if a sending action is interrupted the process can be resumed without double-sending messages to any subscriber.

While sending, a delay can be configured between the sending of each email (MAILINGLIST_EMAIL_DELAY), also a delay can be configured between "batches" as well (MAILINGLIST_BATCH_DELAY, MAILINGLIST_BATCH_SIZE).

Global Deny List

The author of this project feels strongly that people should be able to opt-in to being on mailing lists. They should also, if they wish, to opt-out of being on any mailing list. The GlobalDeny model exists to respect that right of users. When a GlobalDeny instance is associated with a user then that user will not receive messages on any mailing list to which they are subscribed, nor will they be able to be subscribed to any additional mailing lists. The user, when managing their subscriptions, will be able to join the global deny list. If a user is unsuccessful in unsubscribing from a mailing list they will be redirected to join the global deny list.

Comparisons with django-newsletter

This project is a direct descendant of django-newsletter although not a fork. It borrows some amount of code from it (as well as the license), but in general is a full rewrite which uses a services architecture to keep the models thinner. The (subjectively appraised) differences between the architecture of this package and its predecessor are outlined below.

Improvements

  • Easier configuration: doesn't require installing and configuring additional apps, customized templates are not required, doesn't require the sites framework.
  • More secure: doesn't leak user data in subscribe/unsubscribe flows; allows use of https.
  • More private: doesn't store user data within its own models, project must provide a User-like model for storing subscriber user data.
  • More compliant: outgoing messages adhere (accurately) to RFC3269 on email header fields for mailing lists.
  • Implicit send lists: when a message is published, it is sent to all subscribers (at time of processing) except those explicitly excluded from the submission.
  • Send tracking: tracks each sending of a message to a subscriber so that interrupted sending jobs can be resumed.
  • Lower friction user self-management: the unsubscribe link in outgoing message will immediately unsubscribe the recipient.
  • Global unsubscribe: allows users to globally opt-out of receiving mailing list messages.
  • Pluggable behavior: define your own email send and "user" creation functionality (if you like).

Drawbacks

  • No internationalization: Only English (for now).
  • Worse subscriber import: Only CSV import is supported (for now).
  • Worse documentation: There is a lot of room to grow here!
  • No inline images (yet).

Equivalent, but different

  • Markdown instead of traditional rich text. It is the author's opinion that Markdown is superior to rich text because Markdown retains meaning as plain text, therefore your intent in formatting will be better conveyed in the plaintext version of the message.

Changelog

Changes to this project will be documented in this file.

[Unreleased]

Added

Changed

Removed

Fixed

[0.1.6]

Fixed

  • Unsupported operator for MySQL database backend. (#11)

[0.1.6]

Added

  • Link to manage subscriptions page from the unsubscribe page

Removed

  • Some unnecssary code for dynamically importing modules

Fixed

  • Documentation reference to management command

[0.1.5]

Added

  • Demo of pluggable user model to test_project.

Fixed

  • BREAKING! Pluggable user model. This requires that you roll back your migrations for this app and reapply them.
  • Project URL in setup.py.

[0.1.4]

Added

  • Models graph to documentation
  • Docs badge to readme

[0.1.3]

Added

  • MessageAttachment model and machinery to manage and send attachments.
  • List-Unsubscribe header to outgoing messages.
  • Lots of documentation!
  • Contents to message_subject.txt template.
  • Management command, celery tasks for processing published submissions.
  • View and URL for index of mailing list archives.
  • Documentation generation within CI pipeline

Changed

  • More fiddling with the badges
  • Message preparation pipeline to reduce template lookups

Removed

  • Message.subject

[0.1.2]

Changed

  • Readme to point to correct github workflow status

[0.1.1]

Added

  • Nothing, just getting CI pipeline working

[0.1.0]

Added

  • Everything

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

django-mailinglist-0.1.7.tar.gz (48.1 kB view details)

Uploaded Source

Built Distribution

django_mailinglist-0.1.7-py3-none-any.whl (50.2 kB view details)

Uploaded Python 3

File details

Details for the file django-mailinglist-0.1.7.tar.gz.

File metadata

  • Download URL: django-mailinglist-0.1.7.tar.gz
  • Upload date:
  • Size: 48.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/5.0.0 CPython/3.12.2

File hashes

Hashes for django-mailinglist-0.1.7.tar.gz
Algorithm Hash digest
SHA256 0917a57626a4d608224b7ff18238fdf4029fc52c6ebcff9ac4849a7730a2f2c5
MD5 1ea5b90c23fa0c0f11938eed7699ce75
BLAKE2b-256 04887232f38409285174f0f198df064f950347b5fe25b70029c9216b7484673e

See more details on using hashes here.

File details

Details for the file django_mailinglist-0.1.7-py3-none-any.whl.

File metadata

File hashes

Hashes for django_mailinglist-0.1.7-py3-none-any.whl
Algorithm Hash digest
SHA256 b0c110f8a9e6df08f8732d99f1e5a335034c3fdc76fc6e30165a3e69ac641fea
MD5 6e4a9f73d482bd87a1aeffe9d736125d
BLAKE2b-256 c5671ba15637c889fbd34aa06cb50292aa6329fb4e18619ab620eda526d09734

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page