summaryrefslogtreecommitdiff
path: root/content/articles/2019-email-server-tutorial.md
blob: cca8379f0c3cd3be3319136d01289146e78c61a0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
+++
title = "How to set up an email server in 2019"
+++

# How to set up an email server in 2019

This is a guide to set up your own email server in 2019.
This is a messy topic, and the available documentation is even messier,
so I compiled this guide in an attempt to make it all more accessible.

So why run your own mail server? There are many reasons,
ranging from privacy concerns about popular providers,
to simply wanting to learn about this stuff for fun.
If you've arrived here, then I assume you've already found a reason.

But beware that this is not for the faint of heart:
email is a horribly designed system, and even if you manage
to set up your own server, you may find that GMail flags all
your messages as spam, with little you can do about it.
This guide tries to implement all the security measures
that GMail seems to like, but *your mileage may vary*.



## How email works

The program on your device that you use to read and send emails
contains both a Mail User Agent (MUA) and a Mail Retrieval Agent (MRA),
although in practice the MRA is also often referred to as an MUA.
These mail agents can be in a dedicated app like [Thunderbird](https://www.thunderbird.net/en-US/)
or Microsoft Outlook, or it can simply be a web interface.

When you check your inbox, your MRA asks for any new emails
from the server, which then sends them via the [IMAP](https://en.wikipedia.org/wiki/Internet_Message_Access_Protocol) protocol
(we ignore [POP3](https://en.wikipedia.org/wiki/Post_Office_Protocol), since it is rather [outdated](https://www.pop2imap.com/)).
The server-side program here is simply called the IMAP server,
which watches over the server's copy of your inbox.

When you send an email, your MUA passes it along to the server's
Mail Submission Agent (MSA), which then immediately hands it over
to the Mail Transfer Agent (MTA) running on that same server.
In practice, the MSA's functionality is often regarded as part of the MTA.

The MTA then works out where your email needs to go,
and sends it over a protocol called [SMTP](https://en.wikipedia.org/wiki/Simple_Mail_Transfer_Protocol)
to the MTA of the server responsible for the recipient of your message.
In complex networks there may be multiple MTAs in a chain.

The final receiving MTA then hands over your email to the
Mail Delivery Agent (MDA) running on that same server.
The MDA checks whether it's spam, and then writes it to the server's storage,
which is being watched over by an IMAP server, thus completing the cycle.
Most MTA programs also have MDA features for simplicity,
although in this guide we'll be using our IMAP server's MDA helper.

Long story short, the server we want to set up
must at least be running both an MTA for you to send emails
and an IMAP server for you to check your inbox,
one of which should also include MDA functionality.



## Email security

This messy base email system is horribly insecure on its own,
so we still need to tack on some more messy features.
In this context, "security" refers to both spam and privacy protection.
This guide covers all techniques mentioned here.

Spam protection also means two things:
defending yourself against spammers, and
preventing that your emails' recipients' filters don't flag *you* as a spammer.
The former is optional, but the latter is not.

Let's start with how to come across as a trustworthy mail server:

The first feature is [Sender Policy Framework](https://en.wikipedia.org/wiki/Sender_Policy_Framework) (SPF),
which stops a spammer from filling in your email address
in the "sender" field of their message.
You do this by publishing a policy in a DNS record for how your domain
should relate to the IP address of your email server.
A filter enforcing SPF will use that to check that your server
is authorized to send messages with your email address.

Then there's [DomainKeys Identified Mail](https://en.wikipedia.org/wiki/DomainKeys_Identified_Mail) (DKIM),
which is a more comprehensive form of SPF.
It adds a cryptographic signature to all your emails,
which the receiver's spam filter will check against
the contents and a public key you need to publish in a DNS record.
You should implement *both* SPF and DKIM, despite their overlap.

Lastly, we have [Domain-based Message Authentication, Reporting and Conformance](https://en.wikipedia.org/wiki/DMARC).
which uses another DNS record to specify whether you're using SPF and/or DKIM,
and whether super- and subdomains should be regarded as valid for authentication.
It also gives a contact address to which the receiver should send failure reports.
I highly recommend implementing this too.

To defend yourself against spammers your server should enforce
the SPF, DKIM and DMARC policies of senders, in addition to some other checks.
All of that will be handled by your spam filter.

There's one final problem to bring up:
your emails will be sent across the Internet unencrypted.

For client-server communication, this is effectively solved
by IMAPS and SMTPS, which wrap IMAP and SMTP in [TLS](https://en.wikipedia.org/wiki/Transport_Layer_Security).
To be clear, SMTPS only encrypts email submission by an MUA to an MTA (MSA).

For server-server relaying of messages over SMTP, we have
STARTTLS, which is a system for opportunistic TLS, meaning that
communication is only encrypted if both parties agree
after a short unencrypted discussion.
That last part is vulnerable to [MitM](https://en.wikipedia.org/wiki/Man-in-the-middle_attack) attacks,
where anyone along the path of the email servers' discussion
can alter the exchange to block the use of encryption,
which sometimes actually [happens](https://www.eff.org/deeplinks/2014/11/starttls-downgrade-attacks) in practice.

The only way to make sure that STARTTLS is used
is to refuse any emails unless the TLS handshake succeeds.
That's a risky approach, because fewer mail servers support
STARTTLS than you might expect or hope: I've had airline
booking confirmations, full of personal details,
and made with multi-billion-dollar companies,
sent across the Internet without any protection.
I'll show you how, but do it at your own risk.



## Preparation

Are you still here? Good, let's get started. Here's what you'll need:
* SSH root access to a 24/7-accessible server running Linux or *BSD
* an associated domain name for which you can create or edit DNS records
* a TLS certificate for encryption

The TLS certificate is technically optional,
but you *really* should use one; it's 2019 for goodness' sake.
You may get away with using a self-signed certificate,
but instead I highly recommend getting a proper one from
[Let's Encrypt](https://letsencrypt.org/) (it's free!).

In the rest of this guide I'll assume that
you have your public TLS certificate at `/etc/ssl/certs/example.com.pem`,
and your private encryption key at `/etc/ssl/private/example.com.pem`.
You should also create a file with [DH parameters](https://weakdh.org/sysadmin.html)
using the `openssl` tool, included in OpenSSL and LibreSSL:
```sh
openssl dhparam -out /etc/ssl/dhparam.pem 4096
```
This will take a while, because it's looking for sources
of randomness in your (very non-random) computer.
Just keep doing stuff with it running in the background.
The resulting file is public and expendable.



There exist many options for most of the software roles described earlier.
This guide covers multiple options for most of these,
given here from most to least recommended by me:
* IMAP server + MDA: [Dovecot](https://www.dovecot.org/).
* MTA: [OpenSMTPD](https://opensmtpd.org/), [Postfix](http://www.postfix.org/), or [Exim](https://exim.org/).
* Spam filtering: [Rspamd](https://www.rspamd.com/), or [SpamAssassin](https://spamassassin.apache.org/).
* DKIM signing: [OpenDKIM](http://www.opendkim.org/), or [DKIMproxy](http://dkimproxy.sourceforge.net/).

The MTA feeds arriving emails through the spam filter
before giving them to the MDA, which puts them in an inbox folder.
Likewise, it feeds outgoing emails through the DKIM signer.
The IMAP server then delivers your inbox contents to your MUA.

All these MTAs include an MDA, but nevertheless
I recommend using Dovecot's one because it gives the most control.
This is also important because of how spam filtering works:
according to the email specification, an MTA assumes full responsibility
over any emails it accepts for delivery or relaying,
and promises that it will do its best to get it to its destination.

The takeaway from this is that an MTA must not magically
swallow any emails it doesn't like, so if it uses a spam filter,
that filter may tag emails as "spam" or "not spam",
but the MTA is not allowed to act based on that verdict.
The MDA does not have this restriction, so only there
can we make the decision what to do with spam,
and Dovecot's MDA is by far the best equipped for that.

When setting up an email server, you have the choice between
attaching email addresses to system users or virtual users.
With system users, if an email arrives for `foo@example.com`,
then MTA, MDA and IMAP server will all expect that there
exists a `foo` Unix user on the server to deliver it to.
With virtual users, this is not the case.

This guide only covers virtual users, which I recommend
because it's more flexible, and unless you're using some
ancient mainframe there is no advantage to using system users.

Therefore, create a global email user and group,
which are traditionally both called `vmail`.
Do *not* pass the "system user/group" flags,
because that will get you into trouble with Dovecot:
```sh
# GNU CoreUtils:
groupadd vmail
useradd -M -g vmail vmail
# BusyBox:
addgroup vmail
adduser -HD -G vmail vmail
# *BSD:
no clue, you can work it out
```




## DNS records

First things first, you should create an RSA keypair for DKIM,
which you do using the `openssl` utility again.
The minimum size is 1024 bits, but I recommend using 2048 bits.
Bigger is better, but because DNS is involved we can't stretch it
to 4096 bits without risking causing discomfort to [some](https://serverfault.com/questions/747185/dkim-can-i-use-a-rsa-key-larger-than-2048bit-i-e-4096) servers.
```sh
$ openssl genrsa -out /TODO/private.key 2048
$ openssl rsa -in /path/private.key -out /path/public.key
```

Now we must set up all the necessary DNS records.
It may take up to a day for these to propagate over the Internet,
so I recommend doing this section now and the rest tomorrow.

Now, this might sound obvious, but you must have an A and/or AAAA record
to associate your domain `example.com` with the server's IP address.
For email you also must have [reverse DNS](https://en.wikipedia.org/wiki/Reverse_DNS_lookup) set up correctly.
If you're renting your server remotely, you can often do this from
the provider's configuration tool, or you can just create a PTR-type DNS record.

To inform the rest of the Internet that your server is an email server,
create an MX (Mail eXchanger) DNS record for your domain.
Note the dot at the end of the domain name:
```
MX 42 example.com.
```
When a message is sent to an email address ending in `@example.com`,
the sending server will query DNS for any MX records for `example.com`.
There it will find a domain name (in this case `example.com` again),
for which it will look up the IP address, and send the email to.
The domain name in the record must *not* have an associated CNAME record;
it must be directly translatable to an IP address.

You may have multiple MX records, which must contain different
domain names, each with an associated preference number (`42` here).
The sending server will use all MX records with lower numbers first,
and if those servers are all unavailable, it will try a higher number.
If you have multiple mail servers (which is good for availability),
you can therefore declare those as follows:
```
MX 13 mx1.example.com.
MX 42 mx2.example.com.
```
Here, a server sending an email to your domain `example.com`
will try to send it to the IP address of `mx1.example.com` first,
and if that fails, it will move on to the higher numbered `mx2.example.com`.
If both `mx1` and `mx2` have the same number, then the sender
will randomly choose one, which is useful for load balancing.

Next, publish an SPF policy record so you don't look like a spammer.
This is a TXT (*not* SPF!) record with the following contents:
```
TXT "v=spf1 mx -all"
```
Everything after the version `v=spf1` is a list of *mechanisms*
for a spam filter to try out in the given order.
The `-all` at the end says to reject your email
if all of the previous mechanisms fail verification.
I recommend only using the `mx` mechanism, which tells the verifier
to look at the A/AAAA addresses of the domains in your MX records.
This allows you to add, remove, or change your servers
without needing to update this record.

Your DKIM policy must also be published in a TXT record
as follows, where `<public.key>` is the public RSA key `MI...AB`
stored in `/TODO/public.key`, with the newlines removed:
```
TXT "v=DKIM1; t=s; h=sha256; p=<public.key>"
```
Here, `v=DKIM1` is the version and must be the first tag.
The flag `t=s` enables strict mode, as recommended by the [DKIM spec](https://tools.ietf.org/html/rfc6376#page-29),
meaning emails sent from subdomains immediately fail verification.
The optional tag `h=sha256` blocks the use of the old SHA1 algorithm.

Finally, there is the DMARC policy, which, unlike the others,
will need to be updated at the end of this guide.
For now, create another TXT record with these contents,
where `<admin>` is an email address of your choosing,
which may belong to the domain you're setting up for:
```
TXT "v=DMARC1; aspf=s; adkim=s; p=none; sp=reject; fo=1; ruf=mailto:<admin>"
```
The version tag `v=DMARC1` is required and must come first.
Next, `aspf=s` and `adkim=s` enable strict mode for both SPF and DKIM,
which once again blocks subdomains from passing the test.
Then `p=none` and `sp=reject` control what to do to failed messages
coming from the main domain and subdomains, respectively.
Unsurprisingly, `reject` means that delivery should be refused,
`none` asks to let it through anyway, and `quarantine` tells
the filter to take a closer look at the email or to put it in a spam folder.
Finally, `fo=1` asks the filter to create a forensic report
if any type of verification fails, and `ruf=` gives an address to send it to.



## IMAP server: Dovecot

[Dovecot](https://www.dovecot.org/) is a very popular IMAP server,
focused on being lightweight, simple, and secure.
Its documentation, while extensive and accurate,
is an absolute mess: the information you need is
usually either spread across multiple pages,
or buried somewhere two internal links deep.

If you installed Dovecot via your package manager,
you'll probably have a lot of configuration files
in the `/etc/dovecot` directory and its subdirectories.
I want you to delete all of them. Yes, `rm -rf` that crap.

Dovecot is simple to configure, and doesn't care where
you put its settings, so having all that chaos in `/etc/dovecot`
just makes things unnecessarily confusing.

Create a new blank configuration file `/etc/dovecot/dovecot.conf`,
and start by filling in the details about your TLS certificate,
and making clear that unencrypted connections are unacceptable:
```sh
ssl = required
ssl_cert = </etc/ssl/certs/example.com.pem
ssl_key  = </etc/ssl/private/example.com.key
ssl_dh   = </etc/ssl/dhparam.pem

ssl_prefer_server_ciphers = yes

disable_plaintext_auth = yes
```
The final `disable_plaintext_auth` option tells Dovecot
to reject any passwords that were sent unencrypted.
This means it must be [hashed](https://en.wikipedia.org/wiki/Cryptographic_hash_function)
or sent over a TLS connection, ideally both.

Next, tell Dovecot which protocols to use
and where to expect them as follows:
```sh
protocols = lmtp imap

service lmtp {
	inet_listener lmtp {
		address = 127.0.0.1
		port = 39999
	}
	user = vmail
}
```
LMTP is the Local Mail Transport Protocol, which is basically SMTP
but intended for exchange within a single server or cluster.
When an email is received, Dovecot will start a child process
under the `vmail` Unix user to deliver the message to its recipient.

Since we set `ssl = required` earlier, MUAs (MRAs) will only get their mail
if the STARTTLS handshake was successful during the IMAP exchange,
or if they connect via IMAPS to force the use of encryption.
If you want to, you can set Dovecot to only accept IMAPS
by neutralizing the STARTTLS IMAP login listener:
```sh
service imap-login {
	inet_listener imap {
		port = 0
	}
}
```

Then we need to inform Dovecot which email users it should handle,
and what to do with their messages. Create a file `/etc/dovecot/users` for this,
which describes users in the same format as `/etc/passwd`:
```
user:password:uid:gid::homedir
```
You can leave `uid` and `gid` fields blank, since we're
using our `vmail` virtual mail user for all accounts.
You can even omit `homedir` if all users' directories
follow the same pattern, for example `/var/vmail/<user>/`.
The `user` name may contain the ending `@example.com`, but doesn't need to.
Create the password hash to put in the `password` field as follows:
```sh
# If your server is beefy and has lots of RAM:
doveadm pw -s ARGON2ID-CRYPT
# If you're using an old potato:
doveadm pw -s SHA512-CRYPT
```
After you've entered your password, simply copy-paste the entire
hash string outputted by the program into the `password` field.

Dovecot needs a file describing user accounts on two occasions:
* To check whether a user logging into the IMAP server
  is valid and has given the right password.
  This is handled by the `passdb` block(s) in the configuration.
* To know which email addresses the server is responsible for.
  This is given by the `userdb` block(s) in the configuration.
These functions aren't necessarily fulfilled by the same file:
you can map multiple email addresses to one user acccount,
or multiple user accounts to one email address.
For simplicity, though, we'll use the same file:
```sh
passdb {
	driver = passwd-file
	args = scheme=ARGON2ID-CRYPT username_format=%n /etc/dovecot/users
	#args = scheme=SHA512-CRYPT username_format=%n /etc/dovecot/users
}

userdb {
	driver = passwd-file
	args = username_format=%n /etc/dovecot/users
	# Use vmail for all users, and if all users' inboxes have the same form:
	override_fields = uid=vmail gid=vmail home=/var/vmail/%n
}
```
The `driver` option sets the kind of table Dovecot should expect.
We tell it to use a file in the `passwd`-like format described above,
but other common choices include SQL or the actual `/etc/passwd` file.
The options available in `args` depend on the chosen `driver`.

The password hashing algorithm is given by `scheme`, while
`username_format` desribes the format of user names in the table:
if Dovecot receives an email for `someone@example.com`,
then for `%n` it will expect `someone` in `/etc/dovecot/users`,
but if you use `%u` it will want the full email address instead.

In the `userdb` block we force the use of `vmail:vmail`
for all users, and tell Dovecot to put their mail in `/var/vmail/%n`,
where `%n` means the same as before. You can also use `%u`
for the full address again, or `%d` for the domain name.

Optionally, you can create a catch-all inbox that will accept
all emails sent to your domain that don't match anyone in `/etc/dovecot/users`.
Just add this second `userdb` block after the first:
```sh
userdb {
	driver = static
	args = uid=vmail gid=vmail home=/var/vmail/catchall allow_all_users=yes
}
```
The `static` driver means there is no table file:
all configuration is directly within this `userdb` block.
If we didn't specify `allow_all_users=yes`, then Dovecot
would check whether users existed using the `passdb` table.

Finally, now that we've told Dovecot where the virtual mail users' `home`
folders are, we need to specify how to store the emails within them:
```sh
mail_location = maildir:~:LAYOUT=fs
```
The two standard mailbox formats to choose from are `maildir` and `mbox`.
I highly recommend `maildir`; it's faster and more flexible than `mbox`
because it uses folders, whereas the older `mbox` uses a single database file.
The `~` tells Dovecot to directly put all mails in the account's home folder,
and `LAYOUT=fs` to user filesystem directories for you email folders. TODO?





## MTA: Postfix


## MTA: Exim



## MTA: OpenSMTPD

OpenSMTPD is an MTA by the [OpenBSD](https://www.openbsd.org/) project,
who are known for their focus on security and minimalism.
I really like OpenSMTPD's flexible configuration format,
and its simple and intuitive way of passing around emails.

It doesn't implement milter or any other filtering interface,
so DKIM signing and spam checking must be shoehorned in.
As such, only DKIMproxy can be used for DKIM signing.

To begin, write your email domain on a single line in `/etc/smtpd/mailname`:
```
example.com
```
Next, you must fill in the `/etc/smtpd/aliases` file
which maps recipient addresses to system users:
```
mailuser@example.com    systemuser
```
You can create a wildcard (catch-all) address for your domain
by omitting `mailuser`, such that any unknown recipients end up there.
You may also specify multiple system users as `systemuser1,systemuser2`.

The first part of the actual config `/etc/smtpd/smtpd.conf` is as follows,
with DKIMproxy listening on port 19999 and outputting to 20000:
```sh
# Register TLS certificate to encrypt email transport:
pki "example.com" certificate "/etc/ssl/certs/example.com.pem"
pki "example.com" key "/etc/ssl/private/example.com.key"
pki "example.com" dhe auto

table users "/etc/smtpd/aliases"

# Relay emails submitted by client to DKIM signer on port 19999:
listen on eth0 port 465 smtps       pki "example.com" tag SEND
listen on eth0 port 587 tls-require pki "example.com" tag SEND
accept tagged SEND from any for any relay via smtp://127.0.0.1:19999

# Relay outgoing DKIM-signed emails to their intended destination:
listen on lo port 20000 tag DKIM
accept tagged DKIM from local for any relay
```
The lines starting with `pki` enable [DHE](https://en.wikipedia.org/wiki/Diffie%E2%80%93Hellman_key_exchange)
and tell where the public certificate and private key are for the domain.
We listen for client emails on both ports 465 (SMTPS) and 587 (SMTP),
although for the latter we refuse the submission if STARTTLS fails.

If no spam filtering is desired, let OpenSMTPD deliver the email
by appending the following to the configuration file:
```sh
# Receive incoming emails and write them to the inbox:
listen on eth0 port 25 tls pki "example.com"
accept from any for domain "example.com" virtual <users> deliver to lmtp rcpt-to as vmail
```
Here, we look up which system user corresponds to the recipient in `<users>`,
and deliver it to their maildir `mail` in their home folder.


### With SpamAssassin UNTESTED

For SpamAssassin, we'll need to use [spampd](https://github.com/mpaperno/spampd) as an SMTP shim,
which we set to listen on port 29999 and relay to port 30000.
Add the `--nodetach` option in an init script or systemd service,
but leave it out when starting `spampd` by hand for testing:
```sh
$ spampd --host=127.0.0.1:29999 --relayhost=127.0.0.1:30000 [--nodetach]
```
The rest of `smtpd`'s configuration is then as follows:
```sh
# Receive incoming emails and send them to spampd on port 29999:
listen on eth0 port 25 tls pki "example.com" tag SCAN
accept tagged SCAN from any for domain "example.com" relay via smtp://127.0.0.1:29999

# Receive filtered incoming emails and write them to the inbox:
listen on lo port 30000 tag DONE
accept tagged DONE from local for any virtual <users> deliver to maildir "~/mail"
```
TODO

### With Rspamd









## DKIM signer: DKIMproxy

[DKIMproxy](http://dkimproxy.sourceforge.net/) is a mature and simple SMTP proxy
that signs or verifies all emails passed through it
using the Perl Mail::DKIM module.

In this guide we only use its signing feature,
which is controlled by `/etc/dkimproxy/dkimproxy_out.conf`.
This configuration file is pretty self-explanatory:
```sh
listen    127.0.0.1:19999
relay     127.0.0.1:20000

domain    example.com
selector  mail

keyfile   /etc/dkim/private.key
signature dkim(c=relaxed/simple,a=rsa-sha256)
```
This last line clearly tells it to create a DKIM signature,
because it also supports DKIM's predecessor, Yahoo! DomainKey.
The tag `a=rsa-sha256` specifies the signing algorithm,
while `c=relaxed/simple` gives the [canonicalization](https://tools.ietf.org/html/rfc6376#section-3.4) method.

Canonicalization is a way to prevent the signature from becoming invalid
as the email might get reformatted by the MTAs on its journey.
Our choice `relaxed/simple` allows the header to be reformatted (`relaxed`),
but not the actual body of the message (`simple`).




## DKIM signer: OpenDKIM

[OpenDKIM](http://www.opendkim.org/) is a milter program
that can both create and verify DKIM signatures.




## Spam filter: Rspamd



## Spam filter: SpamAssassin