Modern group email discussion lists.
Gray Duck Mail is an alternative to email discussion group software such as Mailman and Sympa designed to be easy to set up and easy to manage. Gray Duck Mail monitors a remote mail server for messages and processes them by relaying the message to all list members. Gray Duck Mail also automatically handles user subscriptions, unsubscription requests, and email bounces. Gray Duck Mail works with any external email host that allows for POP3/SMTP connections and message forwarding or aliasing. Gray Duck Mail relies totally on an external mail provider, allowing you to use an existing web host or email account.
Gray Duck Mail is written in C# and is powered by ASP.NET Core 3.1 MVC.
Gray Duck Mail is provided as a docker image.
docker pull wagesj45/gray-duck-mail
You will find two tags utilized at Docker Hub: testing
and latest
. The testing
tag is just that; an unstable image used for testing and debugging purposes. Unless you're actively working on development of Gray Duck Mail, only use the latest
tag when pulling images and creating containers.
The docker image requires an HTTP port exposed and mapped to port 80 on the container. An optional port can be exposed and mapped to port 5000 that will accept external unsubscribe requests.
A single volume mounted to /database
is required. This volume will store the local SQLite3 database file is stored. This volume provides non-volitile storage so that data is not lost between docker image upgrades.
The docker image exposes the following environment variables that control the system.
The number of emails that can be sent before a defined time-out period. This is useful for email providers that place restrictions on the number of emails that can be sent. The default value is a System.Int32 set to 00:05:00
.
The time between sending groups of emails from the queue. After a given round of emails sent, the system will wait this amount of time before continuing from the email the queue. The default value is a System.TimeSpan set to 00:05:00
.
The time between fetching email from the remote server. The default value is a System.TimeSpan set to 00:05:00
.
System localization is supported. Language files are stored as *.resx
files. Although the initial translations were automated, pull requests are accepted for human translations.
The following values are supported:
en-US
- Englishja-JP
- Japanesees-ES
- Spanishde-DE
- German
The verbosity level with which to log application events. The default value is a System.String set to info
.
The folowing values are supoorted:
trace
|all
debug
|verbose
info
|information
warn
|warning
err
|error
fatal
The minimum viable search score when performing fuzzy searches. The default value is a System.Single (float) set to 0.2
. When using fuzzy searches fractional scores between 1
and 0
are generated. Results approach zero as search results stray from an exact match.
If set, only the web interface will be initialized. Background worker threads will not be initialized. This is useful for running the web administration interface without the rick of background service workers modifying the remote mail server. The default value is a System.Boolean set to 0
.
The following values are supported:
True
|1
False
|0
If set, an unsubscribe link will be generated and used in system and relayed messages. If unset, a link to the unsubscribe alias will be generated. The default value is a System.Boolean set to 1
.
The following values are supported:
True
|1
False
|0
If set, the URL generated for a externally accessible unsubscribe link will be generated using HTTPS
. Otherwise, it will generated using HTTP
. The default value is a System.Boolean set to 1
.
The following values are supported:
True
|1
False
|0
The host name used when generating an externally accessible unsubscribe link. The default value is a System.String set to example.com
.
A unique string used when creating hash codes for the unsubscribe link appended to email messages. This string can be anything you choose. The hash is created by performing a SHA256 hash on the ContactID
, DiscussionListID
, and WEB_SECRET
. This prevents outside actors from brute forcing the unsubscribe link maliciously. There is no default value for the System.String, however if it is not set, the system will set it to the string representation of a random GUID.
The URLs monitored by the ASP.Net server runtime. The default value is a System.String set to http:// :5000;http:// :80
. You can learn more here, but unless you're an advanced user modifying the Gray Duck Mail Docker image, you should leave this value at its default and ensure poth ports 80 and 5000 are configured. When configuring your Docker container, only port 80 is required for normal functioning.
Gray Duck Mail segments its web interface between two ports, one internal and one external. The Docker image utilizes port 80 as its designated internal point of ingress, and port 5000 as its designated external point of ingress. This means that care should be taken to expose only port 5000 of the docker container to the public internet.
Utilizing the external port allows utilization of a "one click" unsubscribe link. The unsubscribe link takes the form of http[s]://hostname/Unsubscribe/{contactID}/{discussionListID}
. This might look like https://example.com/Unsubscribe/529/187
, assuming a user with the internal identifier 529
is unsubscribing from discussion list with internal identifier 187
, utilizing HTTPS
through the hostname example.com
.
The unsubscribe link is the only externally accessible route in Gray Duck Mail. Attempting to load any other route from port 5000 will result in a 403 Forbidden
access error.
Gray Duck Mail should ideally be placed behind a reverse proxy forwarding web traffic only to port 5000 (or the port being forwarded to the external ingress port in the Docker container). It is highly recommended to utilize a reverse proxy such as nginx serving SSL content. While not recommended, it might be possible to pair the secure ingress port with HTTP basic authentication.
Gray Duck Mail stores email login credentials in a local database. These credentials are not encrypted. Additionally, the web administration interface has no concept of users or content segmentation beyond its internal and external designations. This means that anyone with access to the internal web interface through port 80 will have access to the login credentials of each email discussion list, as well as the list users' contact information (name and email address) and message archive list (sender and message contents).
The database files used by Gray Duck Mail are not encrypted and store all data in plain text. When making backups of the /database
docker volume or exporting copies of the database, care should be taken to ensure that file access is restricted.
Gray Duck Mail provides a web administration interface for basic system interaction. The web interface allows an administrator to create and remove distribution lists, create and remove list contacts, browse message archives, and access basic adminstration actions like importing and exporting copies of the local database, care should be taken to make sure those files are not accessable to the public.
The web adminstration settings control the presentation of data in the web interface, so are stored as cookies in the user's browser. These settings have no influence on the system's discussion list email processing functionality.
This setting controls the number of top level items displayed on a page, such as contacts or archived messages.
Searching through contacts and message archives will by default perform exact searches. Results will contain the search term exactly as presented. If enabled, this option will allow the search engine to engage fuzzy searching, using the Levenshtein distance to find results that closely match a given search term. This can result in better search results, but is computationally heavy as all items being searched must be loaded into memory from the database. When searching large message archives or large contact lists, this could result in time-out errors from the web server.
This action allows you to import an existing SQLite3 database file. When importing a database, the web server must restart. You can simply reload the web interface to see the new changes.
This action allows you to export a copy of the SQLite3 database file. This file can be imported into another instance of Gray Duck Mail or viewed in an external application such as DB Browser for SQLite
Contacts represent individual users that can send and recieve messages to a discussion list. New contacts can be added through the web interface or are added automatically when a previously unknown email address sends a message to request
email alias for a discussion list.
Discussion lists represent a group of contacts that can relay messages to other users via a single designated email address. Limited automated moderation can be performed by sending messages to specific email aliases.
Gray Duck Mail requires an external email account and a few defined aliases in order to function. A discussion list functions by monitoring a given POP3 email account and processing each email by either relaying it to the discussion list members, or by analyzing a message's MIME headers and performing a moderation task.
The base email account is the actual email account provided to you by an external email provider, such as your web host.
In order to process operational emails, Gray Duck Mail expects certain email aliases to be configured. This configuration may be refered to by your email provider as "forwards". These aliases should be structured so that the command name precedes the base email address with a hyphen separating them.
For example: [email protected]
.
The following email aliases are expected to exist for automatic moderation:
The request alias is used to process requests to join a discussion list by new users.
The subscription alias is used by known users who have been invited to participate in a discussion list to confirm their willingness to participate.
The unsubscription alias is used by known users who have been invited to participate in a discussion list to revoke their consent to recieve emails associated with a given discussion list.
The bounce alias is inserted into the return-path
MIME header for all system delievered messages. Some email servers rely on this return-path
value to notify senders of non-deliverable messages or invalid mail boxes.
The owner alias should forward to a non-discussion-list address, such as the administrators personal email account. The system sends alert messages to this address when external moderation is necessary, such as when a previously unknown user requests access to a discussion list.