Compare commits
No commits in common. "acc089f798d50054ad1dcc673e95ea0f6bca90b0" and "164c37f853e93ed036eb8d99bf9b4b8cb2a82470" have entirely different histories.
acc089f798
...
164c37f853
3 changed files with 5 additions and 471 deletions
|
@ -11,7 +11,7 @@
|
||||||
code[class*="language-"],
|
code[class*="language-"],
|
||||||
pre[class*="language-"] {
|
pre[class*="language-"] {
|
||||||
color: #ebdbb2; /* fg1 / fg */
|
color: #ebdbb2; /* fg1 / fg */
|
||||||
font-family: "Fira Code", "Ubuntu Mono", Consolas, Monaco, "Andale Mono", monospace;
|
font-family: Consolas, Monaco, "Andale Mono", monospace;
|
||||||
direction: ltr;
|
direction: ltr;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
white-space: pre;
|
white-space: pre;
|
||||||
|
@ -141,70 +141,3 @@ pre[class*="language-"] {
|
||||||
.token.deleted {
|
.token.deleted {
|
||||||
background: #fb4934; /* red2 */
|
background: #fb4934; /* red2 */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* css for hover button from https://github.com/panr/hugo-theme-terminal/blob/master/assets/css/prism.css */
|
|
||||||
|
|
||||||
div.code-toolbar {
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
|
|
||||||
div.code-toolbar > .toolbar {
|
|
||||||
position: absolute;
|
|
||||||
top: 0.3em;
|
|
||||||
right: 0.2em;
|
|
||||||
transition: opacity 0.3s ease-in-out;
|
|
||||||
opacity: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
div.code-toolbar:hover > .toolbar {
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Separate line b/c rules are thrown out if selector is invalid.
|
|
||||||
IE11 and old Edge versions don't support :focus-within. */
|
|
||||||
div.code-toolbar:focus-within > .toolbar {
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
div.code-toolbar > .toolbar > .toolbar-item {
|
|
||||||
display: inline-block;
|
|
||||||
}
|
|
||||||
|
|
||||||
div.code-toolbar > .toolbar > .toolbar-item > a {
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
div.code-toolbar > .toolbar > .toolbar-item > button {
|
|
||||||
background: none;
|
|
||||||
border: 0;
|
|
||||||
color: inherit;
|
|
||||||
font: inherit;
|
|
||||||
line-height: normal;
|
|
||||||
overflow: visible;
|
|
||||||
padding: 0;
|
|
||||||
|
|
||||||
/* for button */
|
|
||||||
user-select: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
div.code-toolbar > .toolbar > .toolbar-item > a,
|
|
||||||
div.code-toolbar > .toolbar > .toolbar-item > button,
|
|
||||||
div.code-toolbar > .toolbar > .toolbar-item > span {
|
|
||||||
color: #bbb;
|
|
||||||
font-size: 0.8em;
|
|
||||||
padding: 0 0.5em;
|
|
||||||
background: #f5f2f0;
|
|
||||||
background: rgba(224, 224, 224, 20%);
|
|
||||||
box-shadow: 0 2px 0 0 rgba(0, 0, 0, 20%);
|
|
||||||
border-radius: 0.5em;
|
|
||||||
}
|
|
||||||
|
|
||||||
div.code-toolbar > .toolbar > .toolbar-item > a:hover,
|
|
||||||
div.code-toolbar > .toolbar > .toolbar-item > a:focus,
|
|
||||||
div.code-toolbar > .toolbar > .toolbar-item > button:hover,
|
|
||||||
div.code-toolbar > .toolbar > .toolbar-item > button:focus,
|
|
||||||
div.code-toolbar > .toolbar > .toolbar-item > span:hover,
|
|
||||||
div.code-toolbar > .toolbar > .toolbar-item > span:focus {
|
|
||||||
color: inherit;
|
|
||||||
text-decoration: none;
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,5 +1,2 @@
|
||||||
pre[class*=language-] {
|
/* overriding syntax.css */
|
||||||
margin: 0;
|
|
||||||
overflow: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
|
@ -28,8 +28,8 @@ ports](#unblock-your-ports).
|
||||||
|
|
||||||
I'll cut to the chase: the main reason why you'd want to run your own mail server is for related reasons of privacy and
|
I'll cut to the chase: the main reason why you'd want to run your own mail server is for related reasons of privacy and
|
||||||
digital sovereignty. For privacy benefits, as much as you have control over your server, you can protect your email
|
digital sovereignty. For privacy benefits, as much as you have control over your server, you can protect your email
|
||||||
from the eyes of prying server admins (given that you yourself are the admin). Even email providers that market
|
from the eyes of prying server admins (given that you yourself are the admin). Even for email providers that market
|
||||||
themselves around privacy (e.g. Protonmail) rely on trust that the provider is not reading your unencrypted incoming
|
themselves around privacy such as Protonmail, rely on trust that Proton are not reading your unencrypted incoming
|
||||||
email. This is not an issue exclusive to any particular mail provider; if information arrives unencrypted at a server,
|
email. This is not an issue exclusive to any particular mail provider; if information arrives unencrypted at a server,
|
||||||
those with access to the server (i.e. administrators) can read that information, simple as. And as nice as it would be
|
those with access to the server (i.e. administrators) can read that information, simple as. And as nice as it would be
|
||||||
if everyone used GPG end-to-end encryption for email, the vast majority of emails people receive are not end-to-end
|
if everyone used GPG end-to-end encryption for email, the vast majority of emails people receive are not end-to-end
|
||||||
|
@ -94,18 +94,10 @@ The mail server will be composed of the following software:
|
||||||
<td>Mail delivery agent</td>
|
<td>Mail delivery agent</td>
|
||||||
<td colspan="2">Dovecot</td>
|
<td colspan="2">Dovecot</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
|
||||||
<td>SPF authentication</td>
|
|
||||||
<td colspan="2">postfix-policyd-spf-perl</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
<tr>
|
||||||
<td>DKIM authentication and signing</td>
|
<td>DKIM authentication and signing</td>
|
||||||
<td colspan="2">OpenDKIM</td>
|
<td colspan="2">OpenDKIM</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
|
||||||
<td>DMARC authentication</td>
|
|
||||||
<td colspan="2">OpenDMARC</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
<tr>
|
||||||
<td>Spam filter</td>
|
<td>Spam filter</td>
|
||||||
<td rowspan="2">Amavis</td>
|
<td rowspan="2">Amavis</td>
|
||||||
|
@ -224,7 +216,6 @@ following TCP ports are open on your firewall:
|
||||||
| 465 | Email message submission over TLS |
|
| 465 | Email message submission over TLS |
|
||||||
| 587 | Email message submission |
|
| 587 | Email message submission |
|
||||||
| 993 | IMAPS (IMAP over TLS) |
|
| 993 | IMAPS (IMAP over TLS) |
|
||||||
| 4190 | ManageSieve |
|
|
||||||
|
|
||||||
## Obtain a TLS certificate
|
## Obtain a TLS certificate
|
||||||
|
|
||||||
|
@ -741,65 +732,6 @@ get an error message when restarting.
|
||||||
# rc-update add dovecot default
|
# rc-update add dovecot default
|
||||||
# rc-service dovecot start
|
# rc-service dovecot start
|
||||||
|
|
||||||
## mail\_crypt
|
|
||||||
|
|
||||||
Dovecot has a [mail\_crypt plugin](https://doc.dovecot.org/main/core/plugins/mail_crypt.html) which implements
|
|
||||||
**transparent** encryption at rest for mail. By transparent, I mean "invisible" to email clients; you can use an IMAP
|
|
||||||
client with your server with no changes, and no difference in user experience. Mail is decrypted on the server and sent
|
|
||||||
over IMAP.
|
|
||||||
|
|
||||||
We will optionally set up global key mail\_crypt encryption. This does not provide protection against an attacker with
|
|
||||||
root access, or full disk access (which is basically root access), however it can protect against other processes
|
|
||||||
reading our mail since they can't read the private key.
|
|
||||||
|
|
||||||
If you want to implement it, declare usage of the `mail_crypt` plugin in `/etc/dovecot/dovecot.conf`:
|
|
||||||
|
|
||||||
```conf
|
|
||||||
mail_plugins = $mail_plugins mail_crypt
|
|
||||||
```
|
|
||||||
|
|
||||||
Now let's generate some elliptic curve keys for this.
|
|
||||||
|
|
||||||
See what curves are available:
|
|
||||||
|
|
||||||
$ openssl ecparam -list_curves
|
|
||||||
|
|
||||||
If we pick `prime256v1` as our curve, then run:
|
|
||||||
|
|
||||||
$ openssl ecparam -name prime256v1 -genkey | openssl pkey -out ecprivkey.pem
|
|
||||||
|
|
||||||
to generate the private key. To generate the public key:
|
|
||||||
|
|
||||||
$ openssl pkey -in ecprivkey.pem -pubout -out ecpubkey.pem
|
|
||||||
|
|
||||||
Now move these keys to `/etc/dovecot/` and make sure they are owned by `dovecot`:
|
|
||||||
|
|
||||||
# mv ecpubkey.pem /etc/dovecot
|
|
||||||
# mv ecprivkey.pem /etc/dovecot
|
|
||||||
# chown dovecot:dovecot ecpubkey.pem ecprivkey.pem
|
|
||||||
|
|
||||||
Give them the correct permissions:
|
|
||||||
|
|
||||||
$ cd /etc/dovecot
|
|
||||||
# chmod 644 ecpubkey.pem
|
|
||||||
# chmod 600 ecprivkey.pem
|
|
||||||
|
|
||||||
Anyway, create and edit `/etc/dovecot/conf.d/90-mail_crypt.conf` and configure the plugin as follows:
|
|
||||||
|
|
||||||
```conf
|
|
||||||
plugin {
|
|
||||||
mail_crypt_global_private_key = </etc/dovecot/ecprivkey.pem
|
|
||||||
mail_crypt_global_public_key = </etc/dovecot/ecpubkey.pem
|
|
||||||
mail_crypt_save_version = 2
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Restart Dovecot for the changes to take effect:
|
|
||||||
|
|
||||||
# rc-service dovecot restart
|
|
||||||
|
|
||||||
Note that this will not make any difference to reading unencrypted email that was previously stored in your mailbox.
|
|
||||||
|
|
||||||
# Use a local email client
|
# Use a local email client
|
||||||
|
|
||||||
You are now ready to try logging in on a local email client such as Thunderbird, Evolution, Geary, KMail, etc.
|
You are now ready to try logging in on a local email client such as Thunderbird, Evolution, Geary, KMail, etc.
|
||||||
|
@ -869,8 +801,6 @@ checks.
|
||||||
|
|
||||||
## Sender Policy Framework
|
## Sender Policy Framework
|
||||||
|
|
||||||
### Set up your DNS record
|
|
||||||
|
|
||||||
Add a TXT record for your root domain with the contents `v=spf1 mx ~all`, like:
|
Add a TXT record for your root domain with the contents `v=spf1 mx ~all`, like:
|
||||||
|
|
||||||
```dns
|
```dns
|
||||||
|
@ -933,68 +863,6 @@ Breaking down the TXT data:
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
### Get Postfix to validate SPF
|
|
||||||
|
|
||||||
We're going to use a Postfix SMTPd policy server called postfix-policyd-spf-perl to check SPF of incoming emails.
|
|
||||||
postfix-policyd-spf-perl is very simple and requires almost no configuration.
|
|
||||||
|
|
||||||
Install `postfix-policyd-spf-perl` and create a user, `policyd-spf` for it:
|
|
||||||
|
|
||||||
# apk add postfix-policyd-spf-perl
|
|
||||||
# adduser -S -s /sbin/nologin -h /dev/null -H policyd-spf
|
|
||||||
|
|
||||||
Explanation of `adduser` flags:
|
|
||||||
|
|
||||||
<table>
|
|
||||||
<tr>
|
|
||||||
<th>Option</th>
|
|
||||||
<th>Explanation</th>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td><code>-S</code></td>
|
|
||||||
<td>Create a system user</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td><code>-s /sbin/nologin</code></td>
|
|
||||||
<td>Set shell to <code>/sbin/nologin</code> so the user doesn't have a shell</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td><code>-h /dev/null</code></td>
|
|
||||||
<td>Set home directory to <code>/dev/null</code></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td><code>-H</code></td>
|
|
||||||
<td>
|
|
||||||
Don't create a home directory (if you try to create <code>/dev/null</code> and assign it to
|
|
||||||
<code>policyd-spf</code> there will be all sorts of permissions issues)
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
Now edit `/etc/postfix/master.cf` to tell Postfix to start up the postfix-policyd-spf-perl daemon:
|
|
||||||
|
|
||||||
```conf
|
|
||||||
policyd-spf unix - n n - 0 spawn
|
|
||||||
user=policyd-spf argv=/usr/bin/postfix-policyd-spf-perl
|
|
||||||
```
|
|
||||||
|
|
||||||
Now get Postfix to use postfix-policyd-spf-perl in `/etc/postfix/main.cf` by adding the following lines:
|
|
||||||
|
|
||||||
```conf
|
|
||||||
smtpd_recipient_restrictions =
|
|
||||||
permit_mynetworks,
|
|
||||||
reject_unauth_destination,
|
|
||||||
check_policy_service unix:private/policyd-spf
|
|
||||||
policyd-spf_time_limit = 3600
|
|
||||||
```
|
|
||||||
|
|
||||||
postfix-policyd-spf-perl is now set up, and you can test it by sending yourself an email from a mainstream email
|
|
||||||
provider (which ought to have an SPF record) and checking for the presence of this header:
|
|
||||||
|
|
||||||
```
|
|
||||||
Received-SPF: pass (protonmail.com: Sender is authorized to use 'revsuine@protonmail.com' in 'mfrom' identity (mechanism 'include:_spf.protonmail.ch' matched))
|
|
||||||
```
|
|
||||||
|
|
||||||
## DomainKeys Identified Mail
|
## DomainKeys Identified Mail
|
||||||
|
|
||||||
### Configure OpenDKIM
|
### Configure OpenDKIM
|
||||||
|
@ -1197,18 +1065,13 @@ non_smtpd_milters = $smtpd_milters
|
||||||
This uses the Milter extension, which is something that can be used to process mail; in this case, to add headers to
|
This uses the Milter extension, which is something that can be used to process mail; in this case, to add headers to
|
||||||
emails relating to DKIM.
|
emails relating to DKIM.
|
||||||
|
|
||||||
You can, again, test this on both incoming and outgoing mail. On outgoing mail, there should be a `DKIM-Signature:`
|
|
||||||
header present. On incoming mail from domains implementing DKIM, there should be a
|
|
||||||
`Authentication-Results: master.revsuine.xyz;` header (obviously replacing `master.revsuine.xyz` with your hostname)
|
|
||||||
indicating whether or not the email has passed DKIM authentication.
|
|
||||||
|
|
||||||
## Domain-based Message Authentication, Reporting, and Conformance
|
## Domain-based Message Authentication, Reporting, and Conformance
|
||||||
|
|
||||||
### Ensure your domains are aligned in email headers
|
### Ensure your domains are aligned in email headers
|
||||||
|
|
||||||
Send a test email from your domain and look at the email headers of the sent email.
|
Send a test email from your domain and look at the email headers of the sent email.
|
||||||
|
|
||||||
```plaintext {linenos=false,hl_lines=[1,11,23]}
|
``` {hl_lines=[1,11,23]}
|
||||||
Return-Path: <pid1@revsuine.xyz>
|
Return-Path: <pid1@revsuine.xyz>
|
||||||
Received: from master.revsuine.xyz (master.revsuine.xyz. [93.113.25.226])
|
Received: from master.revsuine.xyz (master.revsuine.xyz. [93.113.25.226])
|
||||||
by mx.google.com with ESMTPS id ffacd0b85a97d-3825fb5a132si1538595f8f.66.2024.11.22.08.53.01
|
by mx.google.com with ESMTPS id ffacd0b85a97d-3825fb5a132si1538595f8f.66.2024.11.22.08.53.01
|
||||||
|
@ -1334,129 +1197,6 @@ The `fo` tag indicates when you would like to receive reports. The options are:
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
### OpenDMARC
|
|
||||||
|
|
||||||
We can use software called OpenDMARC to enforce DMARC policies for incoming mail. OpenDMARC is another milter. Let's
|
|
||||||
install it and enable its service:
|
|
||||||
|
|
||||||
# apk add opendmarc
|
|
||||||
# rc-update add opendmarc
|
|
||||||
# rc-service opendmarc start
|
|
||||||
|
|
||||||
Edit the OpenDMARC config at `/etc/opendmarc/opendmarc.conf`.
|
|
||||||
|
|
||||||
Change
|
|
||||||
|
|
||||||
```conf
|
|
||||||
AuthservID HOSTNAME
|
|
||||||
```
|
|
||||||
|
|
||||||
to
|
|
||||||
|
|
||||||
```conf
|
|
||||||
AuthservID OpenDMARC
|
|
||||||
```
|
|
||||||
|
|
||||||
This is so that the `Authentication-Results` header from OpenDKIM authentication. This will also make it clear which
|
|
||||||
program adds which `Authentication-Results` header.
|
|
||||||
|
|
||||||
Add the following line, replacing `mail.domain.com` with your *hostname* (so in [my
|
|
||||||
instance](#a-note-on-my-dns-records), this is `master.revsuine.xyz`).
|
|
||||||
|
|
||||||
```conf
|
|
||||||
TrustedAuthservIDs mail.domain.com
|
|
||||||
```
|
|
||||||
|
|
||||||
This specifies that OpenDMARC should trust authentication results from `mail.domain.com`. Otherwise you would get the
|
|
||||||
following error message in your syslog:
|
|
||||||
|
|
||||||
ignoring Authentication-Results at 1 from mail.domain.com
|
|
||||||
|
|
||||||
Enable `RejectFailures`, which means your server will comply with `p=reject` in DMARC DNS records.
|
|
||||||
|
|
||||||
```conf
|
|
||||||
RejectFailures true
|
|
||||||
```
|
|
||||||
|
|
||||||
You also probably want to enable `RequiredHeaders`, which rejects emails that don't conform to RFC5322 standards, e.g.
|
|
||||||
are missing a `From:` header.
|
|
||||||
|
|
||||||
```conf
|
|
||||||
RequiredHeaders true
|
|
||||||
```
|
|
||||||
|
|
||||||
In case external SPF validation fails (as in, no SPF results are placed in the message header), you probably want to
|
|
||||||
add
|
|
||||||
|
|
||||||
```conf
|
|
||||||
SPFSelfValidate true
|
|
||||||
```
|
|
||||||
|
|
||||||
which tells OpenDMARC to perform the SPF check itself if it can't find SPF results in the message header.
|
|
||||||
|
|
||||||
Now provide OpenDMARC with a socket to use for communication with sendmail. We will use a TCP socket on port 8893:
|
|
||||||
|
|
||||||
```conf
|
|
||||||
Socket inet:8893@localhost
|
|
||||||
```
|
|
||||||
|
|
||||||
For a Unix socket, you'd use the following format:
|
|
||||||
|
|
||||||
```conf
|
|
||||||
Socket local:/var/run/opendmarc/opendmarc.sock
|
|
||||||
```
|
|
||||||
|
|
||||||
By default, you will have the line
|
|
||||||
|
|
||||||
```conf
|
|
||||||
IgnoreHosts /etc/opendmarc/ignore.hosts
|
|
||||||
```
|
|
||||||
|
|
||||||
in `/etc/opendmarc/opendmarc.conf`. This tells OpenDMARC to not authenticate the list of hosts in
|
|
||||||
`/etc/opendmarc/ignore.hosts`. An example `ignore.hosts` is
|
|
||||||
|
|
||||||
127.0.0.1
|
|
||||||
93.113.25.226
|
|
||||||
|
|
||||||
Keep in mind that if you have specified `IgnoreHosts`, this file needs to exist in order for OpenDMARC to run. If you
|
|
||||||
have the option set, make sure to `touch /etc/opendmarc/ignore.hosts` (or whatever filepath you've specified).
|
|
||||||
Alternatively, comment out this option in order to use the default, which is to not authenticate mail coming from
|
|
||||||
127.0.0.1.
|
|
||||||
|
|
||||||
Restart OpenDMARC for these changes to take effect:
|
|
||||||
|
|
||||||
# rc-service opendmarc restart
|
|
||||||
|
|
||||||
To have Postfix use the OpenDMARC milter, it's simple as adding the socket to the `smptd_milters` and
|
|
||||||
`non_smtpd_milters` variable in `/etc/postfix/main.cf`:
|
|
||||||
|
|
||||||
```conf
|
|
||||||
milter_default_action = accept
|
|
||||||
milter_protocol = 6
|
|
||||||
smtpd_milters = inet:127.0.0.1:8891,inet:127.0.0.1:8893
|
|
||||||
non_smtpd_milters = $smtpd_milters
|
|
||||||
```
|
|
||||||
|
|
||||||
Restart Postfix for the changes to take effect:
|
|
||||||
|
|
||||||
# rc-service postfix restart
|
|
||||||
|
|
||||||
And when you receive emails from a legitimate source that implements DMARC, you should see the following headers in
|
|
||||||
your emails:
|
|
||||||
|
|
||||||
```
|
|
||||||
Received-SPF: pass (protonmail.com: Sender is authorized to use 'revsuine@protonmail.com' in 'mfrom' identity (mechanism 'include:_spf.protonmail.ch' matched)) receiver=master.revsuine.xyz; identity=mailfrom; envelope-from="revsuine@protonmail.com"; helo=mail-40130.protonmail.ch; client-ip=185.70.40.130
|
|
||||||
DMARC-Filter: OpenDMARC Filter v1.4.2 master.revsuine.xyz 88CFF1288D1
|
|
||||||
Authentication-Results: OpenDMARC; dmarc=pass (p=quarantine dis=none) header.from=protonmail.com
|
|
||||||
Authentication-Results: OpenDMARC; spf=pass smtp.mailfrom=protonmail.com
|
|
||||||
Authentication-Results: master.revsuine.xyz;
|
|
||||||
dkim=pass (2048-bit key; secure) header.d=protonmail.com header.i=@protonmail.com header.a=rsa-sha256 header.s=protonmail3 header.b=nc4YWVM/
|
|
||||||
```
|
|
||||||
|
|
||||||
<!--
|
|
||||||
TODO: switch SPF filter to a milter e.g. https://www.acme.com/software/spfmilter/ so that SPF isn't checked twice
|
|
||||||
-->
|
|
||||||
|
|
||||||
### Test SPF, DKIM, and DMARC
|
### Test SPF, DKIM, and DMARC
|
||||||
|
|
||||||
You can use [mail-tester.com](https://www.mail-tester.com/) and send an email from your domain to check that SPF, DKIM,
|
You can use [mail-tester.com](https://www.mail-tester.com/) and send an email from your domain to check that SPF, DKIM,
|
||||||
|
@ -1543,9 +1283,6 @@ smtp-amavis unix - - n - 2 smtp
|
||||||
-o smtpd_client_connection_count_limit=0
|
-o smtpd_client_connection_count_limit=0
|
||||||
-o smtpd_client_connection_rate_limit=0
|
-o smtpd_client_connection_rate_limit=0
|
||||||
-o receive_override_options=no_header_body_checks,no_unknown_recipient_checks,no_address_mappings
|
-o receive_override_options=no_header_body_checks,no_unknown_recipient_checks,no_address_mappings
|
||||||
# avoid double dkim signing by setting smtpd_milters to empty
|
|
||||||
# otherwise will run all milters again after amavis
|
|
||||||
-o smtpd_milters=
|
|
||||||
```
|
```
|
||||||
|
|
||||||
The first block tells Postfix to send emails to Amavis, and the second block tells Postfix to run an extra smtpd daemon
|
The first block tells Postfix to send emails to Amavis, and the second block tells Postfix to run an extra smtpd daemon
|
||||||
|
@ -1688,139 +1425,6 @@ X-Spam-Status: Yes, score=999.802 tagged_above=2 required=6.2
|
||||||
URIBL_ZEN_BLOCKED_OPENDNS=0.001] autolearn=no autolearn_force=no
|
URIBL_ZEN_BLOCKED_OPENDNS=0.001] autolearn=no autolearn_force=no
|
||||||
```
|
```
|
||||||
|
|
||||||
# Pigeonhole
|
|
||||||
|
|
||||||
Dovecot can do server-side mail filtering with sieve scripts. These are user scripts that can perform actions on mail
|
|
||||||
based on particular criteria, e.g.
|
|
||||||
|
|
||||||
```sieve
|
|
||||||
require "fileinto";
|
|
||||||
|
|
||||||
if address :is "to" "postmaster@revsuine.xyz" {
|
|
||||||
fileinto "Postmaster";
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Places mail in the `Postmaster` folder if the `To:` field is `postmaster@revsuine.xyz`. You also can do things
|
|
||||||
unconditionally, like
|
|
||||||
|
|
||||||
```sieve
|
|
||||||
redirect postmaster@revsuine.xyz;
|
|
||||||
```
|
|
||||||
|
|
||||||
unconditionally redirects all mail to `postmaster@revsuine.xyz`.
|
|
||||||
|
|
||||||
Sieve scripts can be both per-user and system-wide.
|
|
||||||
|
|
||||||
For more examples, [this page](https://doc.dovecot.org/main/howto/sieve.html) has some good examples.
|
|
||||||
|
|
||||||
## Installing and setting up Pigeonhole
|
|
||||||
|
|
||||||
To use Sieve, install `dovecot-pigeonhole-plugin`:
|
|
||||||
|
|
||||||
# apk add dovecot-pigeonhole-plugin
|
|
||||||
|
|
||||||
Then edit `/etc/dovecot/conf.d/20-lmtp.conf`, and add the `sieve` plugin like so:
|
|
||||||
|
|
||||||
```conf
|
|
||||||
protocol lmtp {
|
|
||||||
# Space separated list of plugins to load (default is global mail_plugins).
|
|
||||||
mail_plugins = $mail_plugins sieve
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
To configure Pigeonhole and sieve, edit `/etc/dovecot/conf.d/90-sieve.conf`. Sieve's options will be configured in the
|
|
||||||
`plugin {}` block in this file.
|
|
||||||
|
|
||||||
We can set the location of user sieve scripts with the `sieve` option.
|
|
||||||
|
|
||||||
```conf
|
|
||||||
sieve = file:~/sieve;active=~/.dovecot.sieve
|
|
||||||
```
|
|
||||||
|
|
||||||
means that `~/sieve` is a directory of sieve scripts, whilst `~/.dovecot.sieve` is a symlink to the "active" one, e.g.
|
|
||||||
|
|
||||||
```
|
|
||||||
sieve
|
|
||||||
├── script1.sieve
|
|
||||||
├── script2.sieve
|
|
||||||
└── script3.sieve
|
|
||||||
```
|
|
||||||
|
|
||||||
could be your `~/sieve/` directory, and to make `script2.sieve` active, you would do
|
|
||||||
|
|
||||||
$ ln -s ~/sieve/script2.sieve ~/.dovecot.sieve
|
|
||||||
|
|
||||||
`sieve_before` defines a directory of sieve scripts which will be executed *prior* to any user scripts. e.g.
|
|
||||||
|
|
||||||
```conf
|
|
||||||
sieve_before = /etc/dovecot/sieve
|
|
||||||
```
|
|
||||||
|
|
||||||
means that the sieve scripts in `/etc/dovecot/sieve` will be executed first, then the user's personal scripts at
|
|
||||||
`~/.dovecot.sieve`.
|
|
||||||
|
|
||||||
You can specify multiple directories in order, like so:
|
|
||||||
|
|
||||||
```conf
|
|
||||||
sieve_before = /var/lib/dovecot/sieve.d/
|
|
||||||
sieve_before2 = ldap:/etc/sieve-ldap.conf;name=ldap-domain
|
|
||||||
sieve_before3 = /etc/dovecot/sieve
|
|
||||||
```
|
|
||||||
|
|
||||||
etc. The `sieve_after` option also exists, and works the same way.
|
|
||||||
|
|
||||||
This is not the same as `sieve_default`, which is *overridden* by user sieve scripts and only executes when a user has
|
|
||||||
no sieve script.
|
|
||||||
|
|
||||||
You can review [this documentation](https://doc.dovecot.org/main/core/plugins/sieve.html) for a full list of Pigeonhole
|
|
||||||
options.
|
|
||||||
|
|
||||||
## ManageSieve
|
|
||||||
|
|
||||||
Users can configure their own user sieve scripts using a protocol called ManageSieve. Like how IMAP allows users to
|
|
||||||
read their emails without having shell access to the mail server, ManageSieve allows users to write sieve scripts
|
|
||||||
without requiring shell access.
|
|
||||||
|
|
||||||
To enable ManageSieve, edit `/etc/dovecot/conf.d/20-managesieve.conf`. Make sure the following line is uncommented:
|
|
||||||
|
|
||||||
```conf
|
|
||||||
protocols = $protocols sieve
|
|
||||||
```
|
|
||||||
|
|
||||||
By default, ManageSieve will listen on port 4190.
|
|
||||||
|
|
||||||
## Sieve scripts for spam filtering
|
|
||||||
|
|
||||||
Let's use a system-wide sieve script to file SpamAssassin-marked spam into a Spam folder. Create an
|
|
||||||
`/etc/dovecot/sieve/` directory, and add it to your `sieve_before` settings:
|
|
||||||
|
|
||||||
```conf
|
|
||||||
plugin {
|
|
||||||
...
|
|
||||||
sieve_before = /etc/dovecot/sieve/
|
|
||||||
...
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Now create a new sieve script, `/etc/dovecot/sieve/spam_folder.sieve`:
|
|
||||||
|
|
||||||
```sieve
|
|
||||||
require ["fileinto", "mailbox"];
|
|
||||||
if header :contains "X-Spam-Flag" "YES" {
|
|
||||||
fileinto :create "Spam";
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Replace `"Spam"` with the name of your spam folder. If it's a subfolder, e.g.
|
|
||||||
|
|
||||||
```
|
|
||||||
Inbox
|
|
||||||
└── Spam
|
|
||||||
```
|
|
||||||
|
|
||||||
you would write `"Inbox.Spam"` in that case.
|
|
||||||
|
|
||||||
# Miscellaneous suggestions
|
# Miscellaneous suggestions
|
||||||
|
|
||||||
You may want to get your domain whitelisted on [dnswl.org](https://www.dnswl.org/), an email whitelist service where
|
You may want to get your domain whitelisted on [dnswl.org](https://www.dnswl.org/), an email whitelist service where
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue