Email submission services consist of a server that accepts email using
authenticated SMTP for LDAP users of the torproject.org domain. This
page also documents how DKIM signatures, SPF records, and DMARC
records are setup.
[[TOC]]
Tutorial
In general, you can configure your email client with the following SMTP settings:
- Description:
torproject.org - Server name:
submission.torproject.org - Port:
465 - Connection security:
TLS - Authentication method:
Normal password - User Name: your LDAP username without the
@torproject.orgpart, e.g. in my case it isanarcat - Password: LDAP email password set on the LDAP dashboard
If your client fails to connect in the above configuration, try
STARTTLS security on port 587 which is often open when port 465 is
blocked.
Setting an email password
To use the email submission service, you first need to set a "mail password". For this, you need to update your account in LDAP:
- head towards https://db.torproject.org/update.cgi
- login with your LDAP credentials (here's how to do a password reset if you lost that)
- be careful to hit the "Update my info" button (not the "Full search")
- enter a new, strong password in the
Change mail password:field (and save it in your password manager)
- hit the
Update...button
What this will do is set a "mail password" in your LDAP account. Within a few minutes, this should propagate to the submission server, which will then be available to relay your mail to the world. Then the next step is to configure your email client, below.
Thunderbird configuration
In Thunderbird, you will need to add a new SMTP account in "Account", "Account settings", "Outgoing Server (SMTP)". Then click "Add" and fill the form with:
- Server name:
submission.torproject.org - Port:
465 - Connection security:
SSL/TLS - Authentication method:
Normal password - User Name: (your LDAP username, e.g. in my case it is
anarcat, without the@torproject.orgpart)
If your client fails to connect in the above configuration, try
STARTTLS security on port 587 which is often open when port 465 is
blocked.
Then you can set that account as the default by hitting the "Set
default" button, if only your torproject.org identity is configured
on the server.
If not, you need to pick your torproject.org account from the
"Account settings" page, then at the bottom pick the tor SMTP server
you have just configured.
Then on first email send you will be prompted for your email
password. This password usually differs from the one used for logging in to
db.torproject.org. See how to set the email password. You should NOT get
a certificate warning, a real cert (signed by Let's Encrypt) should be presented
by the server.
Use torproject.org identity when replying
In most cases Thunderbird will select the correct identity when replying to messages that are addressed to your "@torproject.org" address. But in some other cases such as the Tor Project mailing lists, where the recipient address is not yours but the mailing list, replying to a list message may cause a warning to appear in the bottom of the compose window: "A unique identity matching the From address was not found. The message will be sent using the current From field and settings from identity username@torproject.org."
This problem can be fixed by going into "Account settings", "Manage
identities", clicking "Edit..." after selecting the torproject.org identity.
In the dialog shown, check the box next to "Reply from this identity when
delivery headers match" and in the input field, enter "torproject.org".
Apple Mail configuration
These instructions are known to be good for OSX 14 (Sonoma). Earlier versions of Apple Mail may not expose the same settings.
Before configuring the outgoing SMTP server, you need to have an existing email account configured and working, which the steps below assume is the case.
-
Open the
Mail > Settings > Accountsdialog -
On the left-hand side, select the account to associate with your
@torproject.orgaddress -
Add your
@torproject.orgaddress in the "Email Addresses" input field -
Open the "Server Settings" tab
-
Click the "Outgoing Mail Account" drop-down menu and select "Edit SMTP Server List"
-
Click the "+" sign to create a new entry:
- Description: Tor Project Submission
- User Name: (your LDAP username, e.g. in my case it is
anarcat, without the@torproject.orgpart) - Password: the correct one.
- This password usually differs from the one used for logging in to
db.torproject.org. See how to set the email password. - Host Name:
submission.torproject.org - Automatically manage connection settings: unchecked
- Port: 587
- Use TLS/SSL: checked
- Authentication:
Password
-
Click OK, close the "Accounts" dialog
-
Send a test email, ensuring to select your
@torproject.orgaddress is selected in theFrom:field
Gmail configuration
Follow those steps to configure an existing Gmail account to send
email through the Tor Project servers, to be able to send email with a
@torproject.org identity.
-
Log in to your Gmail account in a web browser
-
Click on "Settings", that should be the big gear icon towards the top right of your window
-
A "quick settings" menu should open. Click on the "See all settings" button at the top of that menu.
-
This will take you to a "Settings" page. Click on the "Accounts and Import" tab at the top of the page.
-
Under "Send mail as", click "Add another email address" and add the yourname@torproject.org address there. Keep the "treat as an alias" box checked.
-
Click the "edit info" link to the right of that account
-
A new "Edit email address" popup should open. Click "Next step" on it.
-
Finally, you'll be at a window that says "Edit email address". Fill it out like this:
- Select "Send through torproject.org SMTP servers".
- Set "SMTP Server:" to
submission.torproject.org, notmx-dal-01.torproject.org - Set "Port:" to 465.
- Set "Username:" to your username (without
@torproject.org). - Set "Password:" to the email submission password that you configured.
- This password is not the same as the one used for logging in
to
db.torproject.org. See how to set the email password. - Keep "Secured connection using SSL (recommended)" selected, the other one "Secured connection using TLS"
Double-check everything, then click "Save Changes". Gmail will try authenticating to the SMTP server; if it's successful, then the popup window will close and your account will be updated.
-
A confirmation email will be sent to the yourname@torproject.org which should forward back to your Gmail mailbox.
-
Try sending a mail with your
@torproject.orgidentity.When you compose a new message, on the "From" line, there will now be a drop-down menu, where you can pick your normal Gmail account or the new
@torproject.orgaccount as your identity.It might take a while to propagate.
How-to
Glossary
- SMTP: Simple Mail Transfer Protocol. The email protocol spoken between servers to deliver email. Consists of two standards, RFC821 and RFC5321 which defined SMTP extensions, also known as ESMTP.
- MTA: Mail Transport Agent. A generic SMTP server. mta-dal-01 is such a server.
- MUA: Mail User Agent. An "email client", a program used to receive, manage and send email for users.
- MSA : Mail Submission Agent. An SMTP server specifically designed to only receive email.
- MDA: Mail Delivery Agent. The email service actually writing the email to the user's mailbox. Out of scope.
This document describes the implementation of a MSA, although the service will most likely also include a MTA functionality in that it will actually deliver emails to targets.
More obscure clients configuration
This section regroups email client configurations that might be a little more exotic than commonly used software. The rule of thumb here is that if there's a GUI to configure things, then it's not obscure.
Also, if you know what an MTA is and are passionate about standards, you're in the obscure category, and are welcomed to this dark corner of the internet.
msmtp configuration
"msmtp is an SMTP client" which "transmits a mail to an SMTP server which takes care of further delivery". It is particularly interesting because it supports SOCKS proxies, so you can use it to send email over Tor.
This is how dgoulet configured his client:
# Defaults for all accounts.
defaults
auth on
protocol smtp
tls on
port 465
# Account: dgoulet@torproject.org
account torproject
host submission.torproject.org
from dgoulet@torproject.org
user dgoulet
passwordeval pass mail/dgoulet@torproject.org
Postfix client configuration
If you run Postfix as your local Mail Transport Agent (MTA), you'll need to do something special to route your emails through the submission server.
First, set the following configuration in main.cf, by running the
following commands:
postconf -e smtp_sasl_auth_enable=yes
postconf -e smtp_sasl_password_maps=hash:/etc/postfix/sasl/passwd
postconf -e smtp_sasl_security_options=
postconf -e relayhost=[submission.torproject.org]:submission
postconf -e smtp_tls_security_level=secure
postconf -e smtp_tls_CAfile=/etc/ssl/certs/ca-certificates.crt
postfix reload
The /etc/postfix/sasl/passwd file holds hostname user:pass
configurations, one per line:
touch /etc/postfix/sasl/passwd
chown root:root /etc/postfix/sasl/passwd && chmod 600 /etc/postfix/sasl/passwd
echo "submission.torproject.org user:pass" >> /etc/postfix/sasl/passwd
Then rehash that map:
postmap /etc/postfix/sasl/passwd
Note that this method stores your plain text password on disk. Make sure permissions on the file are limited and that you use full disk encryption.
You might already have another security_level configured for other
reasons, especially if that host already delivers mail to the internet
at large (for example: dane or may). In that case, do make
sure that mails are encrypted when talking to the relayhost, for
example through a smtp_tls_policy_maps (see below). You want at least the
verify (if you trust DNS to return the right MX records) or secure
(if you don't). dane can work (for now) because we do support
DNSSEC, but that might change in the future.
If you want to use Tor's submission server only for mail sent from a
@torproject.org address, you'll need an extra step. This should
be in main.cf:
postconf -e smtp_sender_dependent_authentication=yes
postconf -e sender_dependent_relayhost_maps=hash:/etc/postfix/sender_relay
Then in the /etc/postfix/sender_relay file:
# Per-sender provider; see also /etc/postfix/sasl_passwd.
anarcat@torproject.org [submission.torproject.org]:submission
Then rehash that map as well:
postmap /etc/postfix/sender_relay
If you are setting smtp_sender_dependent_authentication,
do not set the relayhost (above).
If you have changed your default_transport,
you'll also need a sender_dependent_default_transport_maps as
well:
postconf -e sender_dependent_default_transport_maps=hash:/etc/postfix/sender_transport
With /etc/postfix/sender_transport looking like:
anarcat@torproject.org smtp:
Hash that file:
postmap /etc/postfix/sender_transport
For debugging, you can make SMTP client sessions verbose in Postfix:
smtp unix - - - - - smtp -v
To use a tls_policy_map for just the mails you're delivering via Tor's
mail server (assuming you want to use security level dane-only,
otherwise change it to verify or secure as described above), put the
below into /etc/postfix/tls_policy:
submission.torproject.org:submission dane-only
Hash that file as well and use it in your config:
postmap /etc/postfix/tls_policy
postconf -e smtp_tls_policy_maps=hash:/etc/postfix/tls_policy
smtp_sasl_mechanism_filter is also very handy for debugging. For
example, you can try to force the authentication mechanism to
cram-md5 this way.
If you can't send mail after this configuration and get an error like this in your logs:
Sep 26 11:54:19 angela postfix/smtp[220243]: warning: SASL authentication failure: No worthy mechs found
Try installing the libsasl2-modules Debian package.
Exim4 client configuration
You can configure your Exim to send mails which you send From: your torproject.org email via the TPI submission service, while leaving your other emails going whichever way they normally do.
These instructions assume you are using Debian (or a derivative), and have the Debian semi-automatic exim4 configuration system enabled, and have selected "split configuration into small files". (If you have done something else, then hopefully you are enough of an Exim expert to know where the pieces need to go.)
- Create
/etc/exim4/conf.d/router/190_local_torprojectcontaining
smarthost_torproject:
debug_print = "R: Tor Project smarthost"
domains = ! +local_domains
driver = manualroute
transport = smtp_torproject
route_list = * submission.torproject.org
same_domain_copy_routing = yes
condition = ${if match{$h_From:}{torproject\.org}{true}{false}}
no_more
- Create
/etc/exim4/conf.d/transport/60_local_torprojectcontaining (substituting your TPI username):
smtp_torproject:
driver = smtp
port = 465
return_path = USERNAME@torproject.org
hosts_require_auth = *
hosts_require_tls = *
- In
/etc/exim4/passwd.clientadd a line like this (substituting your TPI username and password):
*.torproject.org:USERNAME:PASSWORD
-
Run
update-exim4.conf(as root). -
Send a test email. Either examine the
Receivedlines to see where it went, or look at your local/var/log/exim4/mainlog, which will hopefully say something like this:
2022-07-21 19:17:37 1oEajx-0006gm-1r => ...@torproject.org R=smarthost_torproject T=smtp_torproject H=submit-01.torproject.org [2a01:4f8:fff0:4f:266:37ff:fe18:2abe] X=TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256 CV=yes DN="CN=submit-01.torproject.org" A=plain K C="250 2.0.0 Ok: 394 bytes queued as C3BC3801F9"
By default authentication failures are treated as temporary failures. You can use exim -M ... to retry messages. While debugging, don't forget to update-exim4.conf after making changes.
Testing outgoing mail
Multiple services exist to see if mail is going out correctly, or if a given mail is "spammy". Three are recommended by TPA as being easy to use and giving good technical feedback.
In general, mail can be sent directly from the server using a command like:
echo "this is a test email" | mail -r postmaster@crm.torproject.org -s 'test email from anarcat' -- target@example.com
DKIM validator
Visit https://dkimvalidator.com/ to get a one-time email address, send a test email there, and check the results on the web site.
Will check SPF, DKIM, and run Spamassassin.
Mail tester
Visit https://www.mail-tester.com/ to get a one-time email address, send a test email there, and check the results on the website.
Will check SPF, DKIM, DMARC, Spamassassin, email formatting, list unsubscribe, block lists, pretty complete. Has coconut trees.
Limit of 3 per day for free usage, 10EUR/week after.
verifier.port25.com
Send an email check-auth@verifier.port25.com, will check SPF, DKIM, and reverse IP configuration and reply with a report by email.
Interestingly, ran by sparkpost.
Other SPF validators
Those services also provide ways to validate SPF records:
- https://www.kitterman.com/spf/validate.html - by a Debian developer
- pyspf: a Python library and binary to test SPF records
- learndmarc.com: has a Matrix (the movie) vibe and more explanations
- vamsoft's SPF checker
Testing the submission server
The above applies if you're sending mail from an existing TPA-managed server. If you're trying to send mail through the submission server, you should follow the above tutorial to configure your email client and send email normally.
If that fails, you can try using the command-line swaks tool to
test delivery. This will try to relay an email through server
example.net to the example.com domain using TLS over the submission
port (587) with user name anarcat and a prompted password (-ap -pp).
swaks -f anarcat@torproject.org -t anarcat@torproject.org -s submission.torproject.org -tls -p 587 -au anarcat -ap -pp
If you do not have a password set in LDAP, follow the setting an email password instructions (for your own user) or (if you are an admin debugging for another user) the Resetting another user mail password instructions.
Resetting another user mail password
To set a new password by hand in LDAP, you can use doveadm to
generate a salted password. This will create a bcrypt password, for
example:
doveadm pw -s BLF-CRYPT
Then copy-paste the output (minus the {} prefix) into the
mailPassword field in LDAP (if you want to bypass the web interface)
or the /etc/dovecot/private/mail-passwords file on the submission
server (if you want to bypass ud-replicate altogether). Note that manual
changes on the submission server will be overwritten fairly quickly.
Note that other schemes can be used as well.
Pager playbook
A limited number of pager playbooks have written, much more needs to be done. See the tests section below for ideas on how to debug the submission server.
Files are present in /var/mail
The FilesInVarMail alert looks like this:
Files are present in /var/mail on mx-dal-01.torproject.org
This happens when Postfix doesn't find a proper alias to deliver mail
for a user and ends up writing to a mailbox in /var/mail. Normally,
this shouldn't happen: emails should be forwarded to a service admin
or TPA, or be routed to Dovecot, which then writes mailboxes in
~/Maildir, not /var/mail.
This is not urgent, it's just a misconfiguration.
The solution is to add a postfix::alias entry for that user,
pointing either at TPA or the responsible service admin. Ideally,
check the file size and the number of messages in it with:
du -sch /var/mail/*
grep -c ^From /var/mail/*
It's possible those are errors from a daemon or cron job that could
easily be fixed as well, without even having to redirect mail to an
alias. Another possibility is to convert a cron job to a
systemd::timer in Puppet.
Those metrics are themselves generated by a systemd timer. You can reproduce the metric by running the command:
/usr/local/bin/directory-size-inodes /var/mail
Once you've fixed the error, the alert should recover after the metrics refresh, which happens only daily. To expedite the process, run the timer by hand:
systemctl start directory-size-inodes
Note that the normal value is 1, not 0, as the script counts
/var/mail itself as a file.
Deal with blocklists
Sometimes we end up on blocklists. That always sucks. What to do depends on who's blocking. Sometimes there'll be a contact address in the bounce message. Let's try to collect our experiences per provider here:
Microsoft
You can request delisting here: https://olcsupport.office.com/ , you need a microsoft account to do so. They should get back to you soon to resolve the situation, if needed you can contact them on outlooksupport@microsoftsupport.com
T-online.de
You can mail tobr@rx.t-online.de to request delisting, they usually respond pretty fast.
Disaster recovery
N/A. The server should be rebuildable from scratch using the Puppet directive and does not have long-term user data. All user data is stored in DNS or LDAP.
If email delivery starts failing, users are encouraged to go back to the email providers they were using before this service was deployed and use their personal address instead of user@torproject.org.
Reference
Installation
The new mail server setup is fully Puppetized. See the design and architecture section for more information about the various components and associated Puppet classes in use.
Submission server
To setup a new submission mail server, create a machine with the
email::submission role in Puppet. Ideally, it should be on a network
with a good IP reputation.
In letsencrypt.git, add an entry for that host's specific TLS
certificate. For example, the submit-01.torproject.org server has a
line like this:
submit-01.torproject.org submit.torproject.org
Those domains are glued together in DNS with:
submission IN CNAME submit-01
_submission._tcp IN SRV 0 1 465 submission
This implies there is only one submission.torproject.org, because
one cannot have multiple CNAME records, of course. But it should
make replacing the server transparent for end-users.
The latter SRV record is actually specified in RFC6186, but may not be sufficient for all automatic configuration. We do not go deeper into auto-discovery, because that typically implies IMAP servers and so on. But if we would, we could consider using this software which tries to support all of them (e.g. Microsoft, Mozilla, Apple). For now, we'll only stick with the SRV record.
Mailman server
See the mailman documentation.
Upgrades
Upgrades should generally be covered by the normal Debian package workflow.
SLA
There is no SLA specific to this service, but mail delivery is generally considered to be high priority. Complaints about delivery failure should be filed as issues in our ticket tracker and addressed.
Design and architecture
Mail servers
Our main mail servers (mx-dal-01, srs-dal-01, mta-dal-01, and submit-01) try to fit into the picture presented in TPA-RFC-44:

srs-dal-01 handles e-mail forwards to external providers and would classify as 'other TPA mail server' in this picture. It notably does send mail to internet non-TPO mail hosts.
Our main domain name is torproject.org. There are numerous subdomains and domain variants (e.g., nevii.torproject.org, torproject.net, etc.). These are all alias domains, meaning all addresses will be aliased to their torproject.org counterpart.
Lacking an implementation of mailboxes, a torproject.org e-mail address can either be defined as an alias or as a forward.
Aliases are defined in Hiera.
Domain aliases are defined in Hiera and through puppet exported resources.
Forwards are defined in Hiera and in LDAP.
The MX resolves all aliases. It does not resolve forwards, but transports them to the SRS server(s). It does not deliver mail to internet non-TPO mail servers.
The SRS server resolves all forwards, applies sender rewriting when necessary, and sends the mail out into the world.
Mail exchangers
Our MX servers, currently only mx-dal-01, are managed by the profile::mx manifest.
They provide the following functionality:
- receive incoming mail
- spamfiltering
- resolving of aliases and forwards
MX servers generally do not send mail to external non-TPO hosts, the only exception being bounces.
MX servers need a letsencrypt certificate, so be sure to add them to the letsencrypt-domains repo.
MX servers need to be manually added to the torproject.org MX record and have a matching PTR record.
MX servers run rspamd and clamav for spam filtering, see the spam filtering section below.
Aliases and forwards
Aliases are defined in data/common/mail.yaml and end up in /etc/postfix/maps/alias.
Forwards are defined in two places:
- in
data/common/mail.yaml, eventually ending up in/etc/postfix/maps/transport, - in LDAP. MX runs a local LDAP replica which it queries, according to
/etc/postfix/maps/ldap_local
To test if an LDAP forward is configured properly, you can run:
postmap -q user@torproject.org ldap:/etc/postfix/maps/transport_local
This should return smtp:srs.torproject.org.
Individual hosts may also define aliases with a
postfix::profile::alias define for local, backwards-compatibility
purposes. This should be considered legacy and typically will not work
if there is a virtual map override (a common configuration). In that
case, a local alias may be defined with (say):
postfix::map { 'virtual':
map_dir => $postfix::map_dir,
postmap_command => $postfix::postmap_command,
owner => $postfix::owner,
group => $postfix::group,
mode => $postfix::mode,
type => 'hash',
contents => [
'postmaster@example.torproject.org postmaster@torproject.org',
'do-not-reply@example.torproject.org nobody',
],
}
SRS
Our SRS servers, currently only srs-dal-01, are managed by the profile::srs manifest.
They provide the following functionality:
- sender address rewriting
- DKIM signing
- resolving and sending of forwards
SRS servers only receive mail from our MX servers.
SRS servers need a letsencrypt certificate, so be sure to add them to the letsencrypt-domains repo.
SRS servers need to be manually added to:
- the srs.torproject.org MX record
- the torproject.org SPF record
and must have a matching PTR record.
Sender address rewriting
The sender address rewriting ensures forwarded mail originating from other domains doesn't break SPF by rewriting the from address to @torproject.org. This only affects the envelope-from address, not the header from.
DKIM signing
Anything with a header from @torproject.org will be DKIM signed by the SRS server. This is done by rspamd. The required DNS record is automatically created by puppet.
Submission
Our submission server, submit-01, is managed by the profile::submission manifest.
It provides the following functionality:
- relaying authenticated mail
- DKIM signing
The submission server only receives mail on smtps and submission ports and it only accepts authenticated mail.
Submission servers need a letsencrypt certificate for both their fqdn and submission.torproject.org, so be sure to add them to the letsencrypt-domains repo as follows:
submit-01.torproject.org submit.torproject.org
The submission server needs to manually have:
- an MX record for submission.torproject.org
- an A record for submission.torproject.org
- an SRV record for _submission._tcp.torproject.org
- an entry in the torproject.org SPF record
and must have a matching PTR record.
There is currently no easy way to turn this into a highly available / redundant service, we'd have to research how different clients support failover mechanisms.
Authentication
SASL authentication is delegated to a dummy
Dovecot server which is only used for authentication (i.e. it
doesn't provide IMAP or POP storage). Username/password pairs are
deployed by ud-ldap into /etc/dovecot/private/mail-passwords.
The LDAP server stores those passwords in a mailPassword field and
the web interface is used to modify those passwords. Passwords are
(currently) encrypted with a salted MD5 hash because of compatibility
problems between the Perl/ud-ldap implementation and Dovecot which
haven't been resolved yet.
This horrid diagram describes the way email passwords are set from LDAP to the submission server:

DKIM signing
Anything with a header from @torproject.org will be DKIM signed by the submission server. This is done by rspamd. The required DNS record is automatically created by puppet.
MTA
Our MTA servers, currently only mta-dal-01, are managed by the profile::mta manifest.
It provides the following functionality:
- relaying authenticated mail
- DKIM signing
The submission server only receives mail on the submission port from other TPO nodes and it only accepts authenticated mail.
MTA servers need a letsencrypt certificate, so be sure to add them to the letsencrypt-domains repo.
MTA servers need to be manually added to:
- the mta.torproject.org MX record
- the torproject.org SPF record
and must have a matching PTR record.
Authentication
Other TPO nodes are authenticated using client certificates. Distribution is done through puppet, the fingerprints are exported in the profile::postfix manifest and collected in the profile::mta manifest.
DKIM signing
Anything with a header from @torproject.org will be DKIM signed by the submission server. This is done by rspamd. The required DNS record is automatically created by puppet.
Regular nodes
Regular nodes have no special mail needs and just need to be able to deliver mail. They can be recognised in puppet by having profile::postfix::independent set to false (the default value). They use our MTA servers as relayhost. This is taken care of by the profile::postfix manifest, which is included on all TPO nodes.
Currently regular nodes have no local mail delivery whatsoever, though this is subject to change, see #42024.
By default, system users will mail as @hostname.torproject.org . This has two disadvantages:
- Replying will result in mail sent to user@hostname.torproject.org , which is an alias for user@torproject.org. This may cause collisions between mail needs from different servers
- Mails from @hostname.torproject.org do not get any DKIM signature, which may cause them to be rejected by gmail and the likes.
We should ideally ensure an @torproject.org address is used for outgoing mail.
Independent mailers
Independent mailers are nodes that receive mail on their own subdomain (which should be different from the node's fqdn) and/or deliver mail themselves without using our MTA. They can be recognised in puppet by having profile::postfix::independent set to true.
There are several things to take into consideration when setting up an independent mailer. In nearly all cases you need to make sure to include profile::rspamd.
If your node is going to accept mail, you need to:
- ensure there's an entry in the letsencypt-domains repo
- ensure there's an ssl::service with the appropriate tlsaport notifying Service['postfix']
- add appropriate postfix configuration for handling the incoming mail in profile::postfix::extra_params
- open up firewalling
- potentially adjust the profile::postfix::monitor_ports and monitor_tls_ports
- set an MX record
- ensure there's a PTR record
- add it to dnswl.org
If your node is going to deliver its own mail, you need to:
- if you're mailing as something other than @fqdn or @torproject.org, set an MX record (yes, an MX record is needed, it doesn't need to actually receive mail, but other mailers hate receiving mail from domains that don't have any MX)
- set / add to the appropriate SPF records
- set profile::rspamd::dkimdomain
- consider setting profile::rspamd::antispam to false if you're not receiving mail or don't care about spam
Examples of independent mailers are: lists-01.torproject.org, crm-int-01.torproject.org, rt.torproject.org
DMARC
DMARC records glue together SPF and DKIM to tell which policy to apply once the rules defined above check out (or not). It is defined in RFC7489 and has a friendly homepage with a good introduction. Note that DMARC usage has been growing steadily since 2018 and more steeply since 2021, see the usage stats. See also the Alex top site usage.
Our current DMARC policy is:
_dmarc IN TXT "v=DMARC1;p=none;pct=100;rua=mailto:postmaster@torproject.org"
That is a "soft" policy (p= is none instead of quarantine or
reject) that applies to all email (pct=100) and sends reports to
the postmaster@ address.
Note that this applies to all subdomains by default, to change the
subdomain policy, the sp= mechanism would be used (same syntax as
p=, e.g. sp=quarantine would apply the quarantine policy to
subdomains, independently of the top domain policy). See RFC 7489
section 6.6.3 for more details on discovery.
We currently have DMARC policy set to none, but this should be changed.
DKIM signing and verification is done by rspamd. The profile::rspamd::dkimdomain can be set to ensure all mail from those domains are signed. The profile automatically ensures the appropriate DNS record is created.
SPF verification is done by rspamd. SPF records for all TPO node fqdn's are automatically created in profile::postfix. The records for torproject.org itself and subdomains like rt.torproject.org and lists.torproject.org are managed manually.
In tpo/tpa/team#40990, anarcat deployed "soft" SPF records
for all outgoing mail servers under torproject.org. The full
specification of SPF is in RFC7208, here's a condensed
interpretation of some of our (current, 2025) policies:
torproject.org
@ IN TXT "v=spf1 a:crm-int-01.torproject.org a:submit-01.torproject.org a:rdsys-frontend-01.torproject.org a:polyanthum.torproject.org a:srs-dal-01.torproject.org a:mta-dal-01.torproject.org ~all"
This is a "soft" (~all) record that will tell servers to downgrade
the reputation of mail send with a From: *@torproject.org header
when it doesn't match any of the preceding mechanisms.
We use the a: mechanism to point at 6 servers that normally should
be sending mail as torproject.org:
crm-int-01, the CRM serversubmit-01, the submission mail serverrdsys-frontend-01, the rdsys serverpolyanthum, the bridges serversrs-dal-01, the sender-rewriting servermta-dal-01, our MTA
The a mechanism tells SPF-compatible servers to check the A and
AAAA records of the given server to see if it matches with the
connecting server.
We use the a: mechanism instead of the (somewhat more common) ip4:
mechanism because we do not want to add both the IPv4 and IPv6
records.
db.torproject.org: a
Some servers have a record like that:
db IN A 49.12.57.132 ; alberti
IN AAAA 2a01:4f8:fff0:4f:266:37ff:fea1:4d3 ; alberti
IN MX 0 alberti
IN TXT "v=spf1 a a:alberti.torproject.org ~all"
This is also a "soft" record that tells servers to check the A or
AAAA records (a) to see if it matches the connecting server. It
will match only if the connecting server has an IP matching the A or
AAAA record for db.torproject.org or alberti.torproject.org.
lists.torproject.org: mx
lists IN TXT "v=spf1 mx a:mta.tails.net a:lists-01.torproject.org a ~all"
This is also a "soft" record that tells servers to check the Mail
Exchanger record (MX) to see if it matches the connecting server.
It also allows the Tails schleuder server to send as lists.torproject.org using the a: record.
The a and a:lists-01.torproject.org are redundant here, but it might actually be possible that the MX for lists is in a
different location than the web interface, for example.
CRM: hard record
Finally, one last example is the CiviCRM records:
crm IN A 116.202.120.186 ; crm-int-01
IN AAAA 2a01:4f8:fff0:4f:266:37ff:fe4d:f883
IN TXT "v=spf1 a -all"
IN MX 0 crm
Those are similar to the db.torproject.org records except they are
"hard" (-all) which should, in theory, make other servers completely
reject attempts from servers not in the A or AAAA record of
crm.torproject.org. Note that -all is rarely enforced this strictly.
DANE
TLSA records are created through puppet using the tlsaport parameter of the ssl::service resource.
We enforce DANE on all outgoing connections, except for stanford (what the hell, stanford?). This is defined in the tls_policy map in profile::postfix.
Spamfiltering
We use rspamd and clamav for spamfiltering.
Viruses and very obvious spam get rejected straight away.
Suspicion of possible spam results in grey listing, with spam results added as headers when the mail does go through.
In case of false positives or negatives, you can check the logs in /var/log/rspamd/rspamd.log
You can tweak the configuration in the profile::rspamd manifest. You can manually train the bayes classifier by running:
/usr/bin/rspamc -h localhost learn_spam
or
/usr/bin/rspamc -h localhost learn_ham
Services
The "submission" port (587) was previously used in the documentation by default because it is typically less blocked by ISP firewalls than the "smtps" port (465), but both are supported. Lately, the documentation has been changed for suggest port 465 first instead.
The TLS server is authenticated using the regular Let's Encrypt CA (see TLS documentation).
Storage
Mail services currently do not involve any sort of storage other than mail queues (below).
Queues
Mail servers typically transfer emails into a queue on reception, and
flush them out of the queue when the email is successfully
delivered. Temporary delivery failures are retried for 5 days
(bounce_queue_lifetime and maximal_queue_lifetime).
We use the Postfix defaults for those settings, which may vary from the above.
Interfaces
Most of Postfix and Dovecot operations are done through the commandline interface.
Authentication
On the submission server, SASL authentication is delegated to a dummy
Dovecot server which is only used for authentication (i.e. it
doesn't provide IMAP or POP storage). Username/password pairs are
deployed by ud-ldap into /etc/dovecot/private/mail-passwords.
The LDAP server stores those passwords in a mailPassword field and
the web interface is used to modify those passwords. Passwords are
(currently) encrypted with a salted MD5 hash because of compatibility
problems between the Perl/ud-ldap implementation and Dovecot which
haven't been resolved yet.
Implementation
Most software in this space is written in C (Postfix, Dovecot, OpenDKIM).
Related services
The submission and mail forwarding services both rely on the LDAP service, for secrets and aliases, respectively.
The mailing list service and schleuder both depend on basic email services for their normal operations. The CiviCRM service is also a particularly large mail sender.
Issues
There is no issue tracker specifically for this project, File or search for issues in the team issue tracker with the ~Email label.
When reporting email issues, do mind the reporting email problems documentation.
The submission project was coordinated and launched in [ticket
30608][].
The emergency changes to the infrastructure (including DKIM, DMARC, and SPF records) were done as part of TPA-RFC-44 (tpo/tpa/team#40981).
Known issues
Maintainer
This service is mostly written as a set of Puppet manifests. It was built by anarcat, and is maintained by TPA.
Some parts of the mail services (the submission service, in
particular) depends on patches on userdir-ldap that were partially
merged in the upstream, see LDAP docs for details.
Users
Users of this service are mostly core tor members. But effectively, any email user on the internet can interact with our mail servers in one way or another.
Upstream
Upstreams vary.
Most of the work done in our mail services is performed by Postfix, which is an active project and de-facto standard for new mail servers out there. Postfix was written by Wietse Venema while working at IBM research.
The Dovecot mail server was written by Timo Sirainen and is one of the most widely used IMAP servers out there. It is an active upstream as well.
OpenDKIM is not in such good shape: it hasn't had a commit orrelease in over 4 years (as of late 2022). We have stopped using OpenDKIM and instead use rspamd for DKIM signing and verification.
TODO: document rspamd upstream.
Monitoring and metrics
By default, all servers with profile::postfix::independent set to true are monitored by Prometheus.
This only checks that the SMTP port (or optionally whatever you set in profile::postfix::monitor_ports or monitor_tls_ports) is open. We do
not have end to end delivery monitoring just yet, that is part of the
improve mail services milestone, specifically issue 40494.
All servers that have profile::postfix::mtail_monitor enabled (which is the default) have the mtail exporter
(profile::prometheus::postfix_mtail_exporter). The Grafana
dashboard should provide shiny graphs.
Tests
Submission server
See Testing the submission server.
Logs
Mail logs are in /var/log/mail.log and probably systemd
journals. They contain PII like IP addresses and usernames and are
regularly purged.
Mails incoming on the submission server are scanned by fail2ban to ban IP addresses trying to bruteforce account passwords.
Backups
No special backup of this service is required.
If we eventually need to host mailboxes, those may require special handling as large Maildir folders are known to create problems with backup software.
Other documentation
This service was setup following some or all of those documents:
- Anarcat's home email setup
- Postfix SASL howto
- Dovecot configuration
- VirtualUsers
- passwd file
- password databases
- user databases
- RFC821 (SMTP, 1982) and RFC5321 (SMTP, 2008)
- RFC6409 (Email submission, 2011)
- RFC8314 ("Cleartext Considered Obsolete: Use of Transport Layer Security (TLS) for Email Submission and Access, makes port 465 legitimate for submission)
- RFC5598 (Internet Mail Architecture, 2009)
- RFC6186 (SRV auto-discovery)
- ticket 30608, the original request for the submission service
- first discussion of the submission service, the project was actually agreed upon at the Stockholm meeting in 2019
Discussion
The mail services at Tor have been rather neglected, traditionally. No effort was done to adopt modern standards (SPF, DKIM, DMARC) which led to significant deliverability problems in late 2022. This has improved significantly since then, with those standards being mostly adopted in 2025, although with a "soft" SPF fail policy.
Overview
Security and risk assessment
No audit was ever performed on the mail services.
The lack of SPF records and DKIM signatures mean that users must rely
on out-of-band mechanisms (like OpenPGP) to authenticate incoming
emails. Given that such solutions (especially OpenPGP) are not widely
adopted, in effect it means that anyone can easily impersonate
torproject.org users.
We have heard regular reports of phishing attempts against our users as well (tpo/tpa/team#40596), sometimes coming from our own domain. Inbound mail filters improved that situation significantly in 2025 (tpo/tpa/team#40539).
Technical debt and next steps
The next step in this project is to rebuild a proposal to followup on the long term plan from TPA-RFC-44 (TPA-RFC-45, issue tpo/tpa/team#41009). This will mean either outsourcing mail services or building a proper mail hosting service.
High availability
We currently have no high availability/redundancy.
Since SMTP conveniently has failover mechanisms built in, it would be easy to add redundancy for our MX, SRS, and MTA servers by simply deploying copies of them.
If we do host our own IMAP servers eventually, we would like them to be highly available, without human intervention. That means having an "active-active" mirror setup where the failure of one host doesn't affect users at all and doesn't require human intervention to restore services.
We already know quite well how to do an active/passive setup: DRBD allows us to replicate entire disks between machines. It might be possible to do the same with active/active setups in DRBD, in theory, but in practice this quickly runs into filesystem limitations, as (e.g.) ext4 is not designed to be accessed by multiple machines simultaneously.
Dovecot has a replication system called dsync that replicates mailboxes over a pipe. There are examples for TCP, TLS and SSH. This blog post explains the design as well. A pair of director processes could be used to direct users to the right server. This tutorial seems to have been useful for people.
Dovecot also shows a HAProxy configuration. A script called poolmon seems to be used by some folks to remove/re-add backends to the director when the go unhealthy. Dovecot now ships a dovemon program that works similarly, but it's only available in the non-free "Pro" version.
There's also a ceph plugin to store emails in a Ceph backend.
It also seems possible to store mailbox and index objects in an object storage backend, a configuration documented in the Dovecot Cluster Architecture. It seems that, unfortunately, this is part of the "Pro" version of Dovecot, not usable in the free version (see mailbox formats). There's also someone who implemented a syncthing backend.
Proposed Solutions
We went through a number of proposals to improve mail services over time:
- TPA-RFC-15: Email services: DKIM/SPF/DMARC records, mailboxes, refactoring, legacy upgrades (rejected in 2022, replaced with TPA-RFC-31)
- TPA-RFC-31: outsource email services (rejected in 2022 as well, in favor of TPA-RFC-44 and following)
- TPA-RFC-44: Email emergency recovery: DKIM, SPF, DMARC records (implemented in 2022, long term plan postponed)
- TPA-RFC-45: Mail architecture: long term plans spun off from TPA-RFC-44, mostly mailboxes left to implement (draft since 2023, needs rewrite after TPA-RFC-71)
- TPA-RFC-71: Emergency email deployments, phase B: sender-rewriting, refactoring, legacy upgrades (mostly completed as of 2025Q1)
- Enabling local delivery for regular nodes
- Email deliverability monitoring
Submission server proposal
Note: this proposal was discussed inline in the old howto/submission page, before the TPA-RFC process existed. It is kept here for historical reference.
The idea is to create a new server to deal with delivery problems
torproject.org email users are currently seeing. While they can
receive email through their user@torproject.org forwards without too
much problem, their emails often get dropped to the floor when
sending from that email address.
It is suspected that users are having those problems because the
originating servers are not in the torproject.org domain. The hope
is that setting up a new server inside that domain would help with
delivery. There's anecdotal evidence (see this comment for
example) that delivery emails from existing servers (over SSH to
iranicum, in that example) improves reliability of email delivery
significantly.
This project came out of ticket #30608, which has the launch checklist.
Note: this article has a good overview of deliverability issues faced by autonomous providers, which we already face on eugeni, but might be accentuated by this project.
Goals
Must have
- basic compatibility with major clients (Thunderbird, Mail.app, Outlook, Gmail?)
- delivery over secure (TLS + password) SMTP
- credentials stored in LDAP
Nice to have
- automatic client configuration
- improved delivery over current federated configuration
- delivery reliability monitoring with major providers (e.g. hotmail, gmail, yahoo)
- pretty graphs
- formalized SSH-key delivery to avoid storing cleartext passwords on clients
Non-Goals
- 100%, infaillable, universal delivery to all providers (ie. emails will still be lost)
- mailbox management (ie. no incoming email, IMAP, POP, etc)
- spam filtering (ie. we won't check outgoing emails)
- no DKIM, SPF, DMARC, or ARC for now, although maybe a "null" SPF record if it helps with delivery
Approvals required
Approved by vegas, requested by network team, agreed with TPA at the Stockholm meeting.
Proposed Solution
The proposed design is to setup a new email server in the howto/ganeti
cluster (currently gnt-fsn) with the user list synchronized from
LDAP, using a new password field (named mailPassword). The access
would therefore be granted only to LDAP users, and LDAP accounts would
be created as needed. In the short term, LDAP can be used to modify
that password but in the mid-term, it would be modifiable through the
web interface like the webPassword or rtcPassword fields.
Current inventory
- active LDAP accounts: 91
- non-LDAP forwards (to real people): 24
- role forwards (to other @torproject.org emails): 76
Forward targets:
- riseup.net: 30
- gmail.com: 21
- other: 93 (only 4 domains have more than one forward)
Delivery rate: SMTP, on eugeni, is around 0.5qps, with a max of 8qps in the last 7 days (2019-06-06). But that includes mailing lists as well. During that period, around 27000 emails were delivered to @torproject.org aliases.
Cost
Labor and gnt-fsn VM costs. To be detailed.
Below is an evaluation of the various Alternatives that were considered.
External hosting cost evaluation
- Google: 8$/mth/account? (to be verified?)
- riseup.net: anarcat requested price quotation
- koumbit.org: default pricing: 100$/year on shared hosting and 50GB total, possibly no spam filter. 1TB disk: 500$/year. disk encryption would need to be implemented, quoted 2000-4000$ setup fee to implement it in the AlternC opensource control panel.
- self-hosting: ~4000-500EUR setup, 5000EUR-7500EUR/year, liberal estimate (will probably be less)
- mailfence 1750 setup cost and 2.5 euros per user/year
Note that the self-hosting cost evaluation is for the fully-fledged service. Option 2, above, of relaying email, has overall negligible costs although that theory has been questioned by members of the sysadmin team.
Internal hosting cost evaluation
This is a back-of-the-napkin calculation of what it would cost to host actual email services at TPA infrastructure itself. We consider this to be a “liberal” estimate, ie. costs would probably be less and time estimates have been padded (doubled) to cover for errors.
Assumptions:
- each mailbox is on average, a maximum of 10GB
- 100 mailboxes maximum at first (so 1TB of storage required)
- LUKS full disk encryption
- IMAP and basic webmail (Roundcube or Rainloop)
- “Trees” mailbox encryption out of scope for now
Hardware:
- Hetzner px62nvme 2x1TB RAID-1 64GB RAM 75EUR/mth, 900EUR/yr
- Hetzner px92 2x1TB SSD RAID-1 128GB RAM 115EUR/mth, 1380EUR/yr
- Total hardware: 2280EUR/yr, ~200EUR setup fee
This assumes hosting the server on a dedicated server at Hetzner. It might be possible (and more reliable) to ensure further cost savings by hosting it on our shared virtualized infrastructure. Calculations for this haven’t been performed by the team, but I would guess we might save around 25 to 50% of the above costs, depending on the actual demand and occupancy on the mail servers.
Staff:
- LDAP password segregation: 4 hours*
- Dovecot deployment and LDAP integration: 8 hours
- Dovecot storage optimization: 8 hours
- Postfix mail delivery integration: 8 hours
- Spam filter deployment: 8 hours
- 100% cost overrun estimate: 36 hours
- Total setup costs: 72 hours @ 50EUR/hr: 3600EUR one time
This is the most imprecise evaluation. Most email systems have been built incrementally. The biggest unknown is the extra labor associated with running the IMAP server and spam filter. A few hypothesis:
- 1 hour a week: 52 hours @ 50EUR/hr: 2600EUR/yr
- 2 hours a week: 5200EUR/yr
I would be surprised if the extra work goes beyond one hour a week, and will probably be less. This also does not include 24/7 response time, but no service provider evaluated provides that level of service anyways.
Total:
- One-time setup: 3800EUR (200EUR hardware, 3600EUR staff)
- Recurrent: roughly between 5000EUR and 7500EUR/year, majority in staff
Alternatives considered
There are three dimensions to our “decision tree”:
- Hosting mailboxes or only forwards: this means that instead of just forwarding emails to some other providers, we actually allow users to store emails on the server. Current situation is we only do forwards
- SMTP authentication: this means allowing users to submit email using a username and password over the standard SMTP (technically “submission”) port. This is currently not allowed also some have figured out they can do this over SSH already.
- Self-hosted or hosted elsewhere: if we host the email service ourselves right now or not. The current situation is we allow inbound messages but we do not store them. Mailbox storage is delegated to each individual choice of email provider, which also handles SMTP authentication.
Here are is the breakdown of pros and cons of each approach. Note that there are multiple combinations of those possible, for example we could continue not having mailboxes but allow SMTP authentication, and delegate this to a third party. Obviously, some combinations (like no SMTP authentication and mailboxes) are a little absurd and should be taken with a grain of salt.
TP full hosting: mailboxes, SMTP authentication
Pros:
- Easier for TPA to diagnose email problems than if email is hosted by an undetermined third party
- People’s personal email is not mixed up with Tor email.
- Easier delegation between staff on rotations
- Control over where data is stored and how
- Full control of our infrastructure
- Less trust issues
Cons:
- probably the most expensive option
- requires more skilled staff
- high availability harder to achieve
- high costs
TP not hosting mailboxes; TP hosting outgoing SMTP authentication server
Pros:
- No data retention issues: TP not responsible for legal issues surrounding mailboxes contents
- Solves delivery problem and nothing else (minimal solution)
- We’re already running an SMTP server
- SSH tunnels already let our lunatic-fringe do a version of this
- Staff keeps using own mail readers (eg gmail UI) for receiving mail
- Federated solution
- probably the cheapest option
- Work email cannot be accessed by TP staff
Cons:
- SMTP-AUTH password management (admin effort and risk)
- Possible legal requests to record outgoing mail? (SSH lunatic-fringe already at risk, though)
- DKIM/SPF politics vs “slippery slope”
- Forces people to figure out some good ISP to host their email
- Shifts the support burden to individuals
- Harder to diagnose email problems
- Staff or “role” email accounts cannot be shared
TP pays third party (riseup, protonmail, mailfence, gmail??) for full service (mailboxes, delivery)
Pros:
- Less admin effort
- Less/no risk to TP infrastructure (legal or technical)
- Third party does not hold email data hostage; only handles outgoing
- We know where data is hosted instead of being spread around
Cons:
- Not a federated solution
- Implicitly accepts email cartel model of “trusted” ISPs
- Varying levels of third party data management trust required
- Some third parties require custom software (protonmail)
- Single point of failure.
- Might force our users to pick a provider they dislike
- All eggs in the same basket
Status quo (no mailboxes, no authentication)
Pros:
- Easy. Fast. Cheap. Pick three.
Cons:
- Shifts burden of email debugging to users, lack of support
Details of the chosen alternative (SMTP authentication):
- Postfix + offline LDAP authentication (current proposal)
- Postfix + direct LDAP authentication: discarded because it might fail when the LDAP server goes down. LDAP server is currently not considered to be critical and can be restarted for maintenance without affecting the rest of the infrastructure.
- reusing existing field like
webPasswordorrtcPasswordin LDAP: considered a semantic violation.
See also internal Nextcloud document.
No benchmark considered necessary.