Fork/Hack on Pony Mail

Apache Pony Mail™ (Incubating)

Installing Pony Mail

If your distro is on this list, please refer to that specific document for detailed package installation instructions:

Otherwise, read the next two chapters:


You will need the following software installed on your machine:

Download and Install

Using auth for ElasticSearch

If your ElasticSearch instance requires authentication for the importer/archiver, please add the following lines in the elasticsearch block of ponymail.cfg once generated:

user:           [username for ES]
password:       [password for ES]

Using Apache HTTP Server:

Using nginx:

Setting up the archiver

First off, you will need both tools/ and the generated tools/ponymail.cfg present on the machine that your mail server runs on. This machine should also have access to the ElasticSearch backend.

If your mailing list supports feeding emails to a program, feed the incoming new emails to python3 /path/to/tools/ and it will use STDIN as the transport mechanism. If you are simply using aliases or dot-forwards and no ML system, you can add (for example) "|/usr/bin/python3 /path/to/tools/" to your alias file to enable archiving. If you are not using a Mailing List manager, you will need to tell Pony Mail which email header determines the list ID using the --altheader argument, for instance: foolist: "|/usr/bin/python3 /path/to/tools/ --altheader delivered-to" foolist-private: "|/usr/bin/python3 /path/to/tools/ --altheader delivered-to --private"

If you are using MailMan 3, you can add as an archive by following the instructions inside the python script: - Copy the file to $mailman_plugin_dir/mailman_ponymail/ - Copy ponymail.cfg to the same dir (for ES configuration) - Enable the module by adding the following to your mailman.cfg file:: [archiver.ponymail] # Pony Mail class: mailman_ponymail.Archiver enable: yes

For older mailing list systems such as Mailman 2 and ezmlm, you can also tak a look at our archiving examples page for pointers.

Public versus private lists

In MailMan 3, this should be auto-detected and is not a concern. When using other ML systems via piping to STDIN, you should add the --private arg to the python script to mark an email as private: foolist-private: "|/usr/bin/python3 /path/to/tools/ --private" foolist-public: "|/usr/bin/python3 /path/to/tools/"

Importing old data into Pony Mail

See this guide for details on how to import old archives into Pony Mail.

Bulk editing lists

You can use to perform bulk operations: - Rename lists - Mark entire lists are private or public

Run python3 --help for CLI args.

Setting up OAuth for Pony Mail

If you want people to be able to log in and reply via the Web UI, you can specify an OAuth provider.

Setting up an OAuth provider

Pony Mail comes with a few default OAuth examples in site/js/config.js, such as ASF Oauth and Google OAuth. You can enable these by uncommenting the lines in question, or set up your own OAuth portal to handle things. This is a standard OAuth that expects the backend to supply the following JSON data on success:

        "fullname": "The full name of the authed user",
        "email": "The user's email address",
        "uid": "(optional) The unique user ID of the logged in user (for instance, LDAP UID)",
        "isMember": true/false (optional, specifies whether the person is a privileged user with access to all lists)

For private list browsing, Pony Mail supplies an example AAA library in site/api/lib/aaa.lua that does LDAP lookups to determine which groups a person belongs to, and thus which lists said person has access to. The AAA example is modelled on the Apache LDAP structure, so you may wish to change this to suit your need. We have several simple AAA examples in the aaa_examples directory.

If you are looking for an OAuth portal to provide users access to private lists in the archive, you will need to add the OAuth domain to config.admin_oauth in config.lua:

    admin_oauth = { '', '*', 'etc' }


If not specified in config.lua, OAuth will only provide users with a place to store settings and notifications, and - provided your mail server is set to accept this - a place to reply to emails in the archive.

Using GitHub OAuth and other client-secret providers

If your OAuth provider requires a client secret, you can specify this in site/api/lib/config.lua, as this GitHub example shows:

    oauth_fields = {
        github = {
            client_secret = "abcdef1",
            client_id = "abcdef2",
            oauth_token = ""

This essentially overrides config.js but without showing the data to anyone outside the server.

Whitelisting replies via the Web UI

To have Pony Mail accept replies done via the Web UI, you must make sure that site/api/lib/config.lua contains the appropriate string (or array of strings) matching the domain(s) you wish to allow new email for. To allow replies to everything, set this to *(NOT RECOMMENDED). You can also allow based on GLOBs or an array of accepted domains and sub-domains:

    accepted_domains = "*" -- This would allow posts to any email address, baaaad choice.
    accepted_domains = "" -- Allow only to *
    accepted_domains = "*" -- Allow only posts to *@*, but not *
    accepted_domains = { "", "*" } -- Allow posts both to * and

Setting email footers

It is possible to set email footers in each email sent via the Web UI. This is done by configuring the email_footer variable in site/api/lib/config.lua. You may use the following variables in the footer:

    $list: The mailing list being sent to (foo@bar.tld)
    $hostname: The hostname of the server
    $port: The port of the server (80, 443 etc)
    $msgid: The message ID of the email (for permalinks etc)

An example footer could be:

    Sent via Pony Mail for $list.
    To view this list online, visit: https://my.tld/list.html?$list
    To view this email (and subsequent replies), visit:

A note on email headers

By default, headers such as to/cc are not shown in the normal email view. To enable these headers, set full_headers to true in the site/api/lib/config.lua file.

Lastly, a note about Message-ID (MID) generators

The default MID generator is called 'medium' and digests the message body, timestamp and list-ID to generate the MID. There is also a 'short' that only digests the body, and a 'full' that uses the entire message as a bytestring to generate an ID. Medium is recommended for most setups (especially clustered setups), while full can be used for single-machine setups. N.B. At present, all the generators have issues, see (#176 #177 #178)


Apache Pony Mail (Incubating) is an effort undergoing incubation at The Apache Software Foundation (ASF), sponsored by the Apache Incubator. Incubation is required of all newly accepted projects until a further review indicates that the infrastructure, communications, and decision making process have stabilized in a manner consistent with other successful ASF projects. While incubation status is not necessarily a reflection of the completeness or stability of the code, it does indicate that the project has yet to be fully endorsed by the ASF.

Copyright 2016, the Apache Software Foundation.
Apache Pony Mail and the Apache Pony Mail logo are trademarks of the Apache Software Foundation. Apache and the Apache feather are registered trademarks of the Apache Software Foundation.