GSoC 2017 - About the plugin

As last time I described outstanding PRs to Mailman Core and other Mailman’s components, this time I am going to describe the plugin I am building on top of those components to enable PGP encrypted mailing lists.

In fact there are two plugins to present, with the first one being a general and quick plugin example that showcases how the new plugin API might be used and also provides some nice services for the PGP plugin.


repo @ gitlab

This plugin subscribes itself to receive events in Mailman Core and sends them to urls configured. It is a variation of what mailman!264 is intending to do, based on the plugin API implemented in my MRs. It currently offers only basic functionality, a URL is specified in config per endpoint along with an API key (very similar to mailman-hyperkitty) and a regex of event class names that will be sent. The data sent currently is only the event class name in a JSON object. Config can have many endpoints specified with the form shown below.

url: http://localhost/django/api
api_key: Something_secret_here
events: .*

Results in a call such as this one:

POST /django/api?key=Something_secret_here HTTP/1.1
Content-Type: application/json

{"event": "DomainCreatedEvent"}

The plugin is currently very bare bones and proper serialization of events is underway. I am thinking of recursively serializing the non-private event attributes until an easily serializable object is reached, such as an Address or a MailingList or anything that has a unique string associated with it and can be queried using the REST API and such a string. So for example:

  "name": "DomainCreatedEvent",
  "event": {
    "domain": ""


  "name": "AddressVerificationEvent",
  "event": {
    "address": ""

This plugin will be used by the mailman-pgp plugin to send events to django-mailman3 which will distribute them to Postorius, HyperKitty and the django app created to enable PGP encrypted mailing lists.


repo @ gitlab

First of all, I think I came up with a name that better fits with mailman-hyperkitty being an archiver “plugin” and in general with how plugins for projects are named in python (flask_ext_… and so on).

As the general functionality and layout of the plugin was already described I will mostly just summarise issues I am currently working on tackling.

low level PGP work#

I originally proposed using python-pgp (github pypi) to use to parse and create OpenPGP packets, as other libraries mostly offer only a high-level API or are not so feature rich. However this library seems quite un-maintained, so either a working fork should be established or a different library used. I am currently looking at both options. Will contact the original author as well as the current pypi package owner and see what’s possible.

public key on subscription#

Since a PGP enabled mailing list needs to know the public key of a subscribed address at the point when moderator approval is required, some mechanism to do so is necessary. This needs to happen before moderator approval, as the moderator / list owner should be able to see / download the provided key to verify it (or at least its fingerprint). Currently I see two options, an extension of the proposed key command or some changes to the current Subscription and Unsubscription workflows.

Extending the proposed key command would let the user use said command to send and confirm his public key, before a subscription to an encrypted list. This is similar to how schleuder does it. They essentially run somewhat of a mailing key-server where the users might submit keys via custom headers in message body.

However the current SubscriptionWorkflow and UnsubscriptionWorkflow are really close to being able to require a custom additional step during which the subscribers key is received and confirmed. Maybe making [Un]SubscriptionWorkflow pluggable components, that can be set on a per-list basis, similar to owner/posting chains or pipelines.

The second solution is definitely a more heavy-handed one, although might be a better one in the long run. As it allows plugins to provide [un]subscription steps which might be a nice use for plugins in Mailman Core. I can imagine for example subscription verification where the plugin verifies that the subscriber is a customer of some company by showing the user a confirmation token in the customer system etc..

require confirmation for all commands#

To address replay attacks where an attacker listens on a user performing a command by sending it to the list_id-confirm address and then sends the same message again in the future to replay the command, all commands will need to require confirmation. This stops the attacker since he cannot obtain the cleartext of the message containing the confirmation token, or even if he could, he cannot forge the signature on the confirmation message (leaving endpoint security out-of-scope). To reuse the confirm command, Workflows and confirmation would have to be refactored out from subscription management.