add title to verbatim blocks. finish relaying page
This commit is contained in:
parent
68fbbb5890
commit
3cb34170c7
9 changed files with 194 additions and 237 deletions
|
|
@ -10,7 +10,7 @@ import { Aside } from "@astrojs/starlight/components";
|
||||||
|
|
||||||
Let's install the necessary Debian packages. Run this command as root on your server as _root_:
|
Let's install the necessary Debian packages. Run this command as root on your server as _root_:
|
||||||
|
|
||||||
```sh
|
```sh title="Run this on your server"
|
||||||
apt update
|
apt update
|
||||||
DEBIAN_FRONTEND=noninteractive \
|
DEBIAN_FRONTEND=noninteractive \
|
||||||
apt -y install postfix-mysql dovecot-mysql \
|
apt -y install postfix-mysql dovecot-mysql \
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,7 @@ you’re actually using MariaDB.
|
||||||
|
|
||||||
This step is simple. Connect to the database using the `mariadb` command in your shell:
|
This step is simple. Connect to the database using the `mariadb` command in your shell:
|
||||||
|
|
||||||
```sh
|
```sh title="Run this on your server"
|
||||||
mariadb
|
mariadb
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,7 @@ records:
|
||||||
- **A / AAAA record (`smtp.example.com`)**
|
- **A / AAAA record (`smtp.example.com`)**
|
||||||
The hostname specified in the MX record (`smtp.example.com`) must resolve to an IP address so that other mail servers
|
The hostname specified in the MX record (`smtp.example.com`) must resolve to an IP address so that other mail servers
|
||||||
know how to reach it.
|
know how to reach it.
|
||||||
|
|
||||||
- An **A record** maps the hostname to an IPv4 address.
|
- An **A record** maps the hostname to an IPv4 address.
|
||||||
- An **AAAA record** maps the hostname to an IPv6 address.
|
- An **AAAA record** maps the hostname to an IPv6 address.
|
||||||
|
|
||||||
|
|
@ -63,14 +64,14 @@ servers may be more likely so flag your sent emails as spam if you do not have a
|
||||||
|
|
||||||
Use the `host` command to check your domain's MX record.
|
Use the `host` command to check your domain's MX record.
|
||||||
|
|
||||||
```sh
|
```sh title="Run this on your server"
|
||||||
$> host -t mx example.com
|
$> host -t mx example.com
|
||||||
example.com mail is handled by 10 smtp.example.com.
|
example.com mail is handled by 10 smtp.example.com.
|
||||||
```
|
```
|
||||||
|
|
||||||
Then check if that result resolves to an IP address:
|
Then check if that result resolves to an IP address:
|
||||||
|
|
||||||
```sh
|
```sh title="Run this on your server"
|
||||||
$> host smtp.example.com
|
$> host smtp.example.com
|
||||||
smtp.example.com has address 49.13.89.249
|
smtp.example.com has address 49.13.89.249
|
||||||
smtp.example.com has IPv6 address 2a01:4f8:c012:62d1::1
|
smtp.example.com has IPv6 address 2a01:4f8:c012:62d1::1
|
||||||
|
|
@ -78,7 +79,7 @@ smtp.example.com has IPv6 address 2a01:4f8:c012:62d1::1
|
||||||
|
|
||||||
Preferably the IP addresses should resolve back to the mail server's name:
|
Preferably the IP addresses should resolve back to the mail server's name:
|
||||||
|
|
||||||
```sh
|
```sh title="Run this on your server"
|
||||||
$> host 49.13.89.249
|
$> host 49.13.89.249
|
||||||
249.89.13.49.in-addr.arpa domain name pointer smtp.example.com.
|
249.89.13.49.in-addr.arpa domain name pointer smtp.example.com.
|
||||||
$> host 2a01:4f8:c012:62d1::1
|
$> host 2a01:4f8:c012:62d1::1
|
||||||
|
|
|
||||||
|
|
@ -40,7 +40,7 @@ Please replace `mail.example.org` by the FQDN you chose.
|
||||||
|
|
||||||
</Aside>
|
</Aside>
|
||||||
|
|
||||||
```sh
|
```sh title="Run this on your server"
|
||||||
certbot --apache --register-unsafely-without-email --agree-tos -d mail.example.org
|
certbot --apache --register-unsafely-without-email --agree-tos -d mail.example.org
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
@ -108,7 +108,7 @@ checks your certificate frequently and triggers a renewal one month before it ex
|
||||||
|
|
||||||
These commands will show you the definition and status of the timer and the renewal service:
|
These commands will show you the definition and status of the timer and the renewal service:
|
||||||
|
|
||||||
```sh
|
```sh title="Run this on your server"
|
||||||
systemctl status certbot.timer
|
systemctl status certbot.timer
|
||||||
systemctl cat certbot.timer
|
systemctl cat certbot.timer
|
||||||
systemctl status certbot.service
|
systemctl status certbot.service
|
||||||
|
|
@ -121,7 +121,7 @@ look cooler.
|
||||||
It is important that services that use the certificate load the new certificate after an automatic renewal. This shell
|
It is important that services that use the certificate load the new certificate after an automatic renewal. This shell
|
||||||
command will create a file `/etc/letsencrypt/cli.ini` that handles it:
|
command will create a file `/etc/letsencrypt/cli.ini` that handles it:
|
||||||
|
|
||||||
```sh
|
```sh title="Run this on your server"
|
||||||
echo > /etc/letsencrypt/cli.ini "post-hook = systemctl reload postfix dovecot apache2"
|
echo > /etc/letsencrypt/cli.ini "post-hook = systemctl reload postfix dovecot apache2"
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -47,7 +47,7 @@ SELECT "yes" FROM virtual_domains WHERE name='example.net'
|
||||||
|
|
||||||
Run the following code in your shell to create a configuration file creating that mapping:
|
Run the following code in your shell to create a configuration file creating that mapping:
|
||||||
|
|
||||||
```sh
|
```sh title="Run this on your server"
|
||||||
cat > /etc/postfix/mariadb-virtual-mailbox-domains.cf << EOF
|
cat > /etc/postfix/mariadb-virtual-mailbox-domains.cf << EOF
|
||||||
user = mailserver
|
user = mailserver
|
||||||
password = MAILSERVER-PASSWORD-HERE
|
password = MAILSERVER-PASSWORD-HERE
|
||||||
|
|
@ -81,7 +81,7 @@ Apparently, there aren't any more. So the email will go to `john@example.org`.
|
||||||
|
|
||||||
Run this code to create the appropriate mapping file:
|
Run this code to create the appropriate mapping file:
|
||||||
|
|
||||||
```sh
|
```sh title="Run this on your server"
|
||||||
cat > /etc/postfix/mariadb-virtual-alias-maps.cf << EOF
|
cat > /etc/postfix/mariadb-virtual-alias-maps.cf << EOF
|
||||||
user = mailserver
|
user = mailserver
|
||||||
password = MAILSERVER-PASSWORD-HERE
|
password = MAILSERVER-PASSWORD-HERE
|
||||||
|
|
@ -97,7 +97,7 @@ The query now gets all the `destination` email addresses from the database for a
|
||||||
|
|
||||||
The last mapping we need is a query to find valid mailboxes. Without further ado:
|
The last mapping we need is a query to find valid mailboxes. Without further ado:
|
||||||
|
|
||||||
```sh
|
```sh title="Run this on your server"
|
||||||
cat > /etc/postfix/mariadb-virtual-mailbox-maps.cf << EOF
|
cat > /etc/postfix/mariadb-virtual-mailbox-maps.cf << EOF
|
||||||
user = mailserver
|
user = mailserver
|
||||||
password = MAILSERVER-PASSWORD-HERE
|
password = MAILSERVER-PASSWORD-HERE
|
||||||
|
|
@ -119,7 +119,7 @@ sufficient here.
|
||||||
|
|
||||||
You have created the config files for the three mappings. Now you just need to tell Postfix to use them:
|
You have created the config files for the three mappings. Now you just need to tell Postfix to use them:
|
||||||
|
|
||||||
```sh
|
```sh title="Run this on your server"
|
||||||
postconf virtual_mailbox_domains=mysql:/etc/postfix/mariadb-virtual-mailbox-domains.cf
|
postconf virtual_mailbox_domains=mysql:/etc/postfix/mariadb-virtual-mailbox-domains.cf
|
||||||
postconf virtual_mailbox_maps=mysql:/etc/postfix/mariadb-virtual-mailbox-maps.cf
|
postconf virtual_mailbox_maps=mysql:/etc/postfix/mariadb-virtual-mailbox-maps.cf
|
||||||
postconf virtual_alias_maps=mysql:/etc/postfix/mariadb-virtual-alias-maps.cf
|
postconf virtual_alias_maps=mysql:/etc/postfix/mariadb-virtual-alias-maps.cf
|
||||||
|
|
@ -138,7 +138,7 @@ access. After all a database password is found in these files.
|
||||||
|
|
||||||
Give the mappings a quick test using the `postmap -q` command (_q_ stands for _query_):
|
Give the mappings a quick test using the `postmap -q` command (_q_ stands for _query_):
|
||||||
|
|
||||||
```sh
|
```sh title="Run this on your server"
|
||||||
postmap -q example.org mysql:/etc/postfix/mariadb-virtual-mailbox-domains.cf
|
postmap -q example.org mysql:/etc/postfix/mariadb-virtual-mailbox-domains.cf
|
||||||
postmap -q jack@example.org mysql:/etc/postfix/mariadb-virtual-alias-maps.cf
|
postmap -q jack@example.org mysql:/etc/postfix/mariadb-virtual-alias-maps.cf
|
||||||
postmap -q john@example.org mysql:/etc/postfix/mariadb-virtual-mailbox-maps.cf
|
postmap -q john@example.org mysql:/etc/postfix/mariadb-virtual-mailbox-maps.cf
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@ In this chapter we will mainly configure Dovecot so that it knows how to deliver
|
||||||
On your disk all the mailboxes will live in the directory `/var/vmail`. To separate the mailboxes from the rest of your
|
On your disk all the mailboxes will live in the directory `/var/vmail`. To separate the mailboxes from the rest of your
|
||||||
system, let's create a new user and group that will own the mailboxes:
|
system, let's create a new user and group that will own the mailboxes:
|
||||||
|
|
||||||
```sh
|
```sh title="Run this on your server"
|
||||||
groupadd --system vmail
|
groupadd --system vmail
|
||||||
useradd --system --gid vmail vmail
|
useradd --system --gid vmail vmail
|
||||||
mkdir -p /var/vmail
|
mkdir -p /var/vmail
|
||||||
|
|
@ -161,7 +161,7 @@ a fixed schema for the home directory (`/var/vmail/DOMAIN/USER`) and the user-ID
|
||||||
|
|
||||||
Make sure that only root can access the SQL configuration file so nobody else is reading your database access passwords:
|
Make sure that only root can access the SQL configuration file so nobody else is reading your database access passwords:
|
||||||
|
|
||||||
```sh
|
```sh title="Run this on your server"
|
||||||
chown root:root /etc/dovecot/conf.d/auth-sql.conf.ext
|
chown root:root /etc/dovecot/conf.d/auth-sql.conf.ext
|
||||||
chmod go= /etc/dovecot/conf.d/auth-sql.conf.ext
|
chmod go= /etc/dovecot/conf.d/auth-sql.conf.ext
|
||||||
```
|
```
|
||||||
|
|
@ -170,13 +170,13 @@ chmod go= /etc/dovecot/conf.d/auth-sql.conf.ext
|
||||||
|
|
||||||
Restart Dovecot from the shell:
|
Restart Dovecot from the shell:
|
||||||
|
|
||||||
```sh
|
```sh title="Run this on your server"
|
||||||
systemctl restart dovecot
|
systemctl restart dovecot
|
||||||
```
|
```
|
||||||
|
|
||||||
Check your logs:
|
Check your logs:
|
||||||
|
|
||||||
```sh
|
```sh title="Run this on your server"
|
||||||
journalctl -fu dovecot
|
journalctl -fu dovecot
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
@ -196,20 +196,20 @@ However in the age of _systemd_ the output of the processes is written to system
|
||||||
|
|
||||||
To read the complete logs of Dovecot, run (u=unit):
|
To read the complete logs of Dovecot, run (u=unit):
|
||||||
|
|
||||||
```sh
|
```sh title="Run this on your server"
|
||||||
journalctl -u dovecot
|
journalctl -u dovecot
|
||||||
```
|
```
|
||||||
|
|
||||||
To `tail -f` the logs (f=follow):
|
To `tail -f` the logs (f=follow):
|
||||||
|
|
||||||
```sh
|
```sh title="Run this on your server"
|
||||||
journalctl -fu dovecot
|
journalctl -fu dovecot
|
||||||
```
|
```
|
||||||
|
|
||||||
However on a busy server it will show the entire journal and then follow any changes. You may want to limit the output
|
However on a busy server it will show the entire journal and then follow any changes. You may want to limit the output
|
||||||
to the last 10 lines:
|
to the last 10 lines:
|
||||||
|
|
||||||
```sh
|
```sh title="Run this on your server"
|
||||||
journalctl -n 10 -fu dovecot
|
journalctl -n 10 -fu dovecot
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
@ -221,7 +221,7 @@ If you prefer the old way of having log files, just install the `rsyslog` packag
|
||||||
|
|
||||||
To test the `userdb` query:
|
To test the `userdb` query:
|
||||||
|
|
||||||
```sh
|
```sh title="Run this on your server"
|
||||||
doveadm user john@example.org
|
doveadm user john@example.org
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
@ -237,7 +237,7 @@ mail_path /var/vmail/example.org/john/Maildir
|
||||||
|
|
||||||
To test the `iterate` query that gets a list of all users:
|
To test the `iterate` query that gets a list of all users:
|
||||||
|
|
||||||
```sh
|
```sh title="Run this on your server"
|
||||||
doveadm user '*'
|
doveadm user '*'
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -54,7 +54,7 @@ The “_virtual_transport_" in Postfix defines the service to use for delivering
|
||||||
created a socket file and is ready to listen to incoming LMTP connections. We just need to tell Postfix to send emails
|
created a socket file and is ready to listen to incoming LMTP connections. We just need to tell Postfix to send emails
|
||||||
there. So please run:
|
there. So please run:
|
||||||
|
|
||||||
```sh
|
```sh title="Run this on your server"
|
||||||
postconf virtual_transport=lmtp:unix:private/dovecot-lmtp
|
postconf virtual_transport=lmtp:unix:private/dovecot-lmtp
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
@ -73,7 +73,7 @@ TODO: move to optional chapter
|
||||||
Finally we are ready for our first email. Using the `swaks` command you can create a test email to `john@example.org`
|
Finally we are ready for our first email. Using the `swaks` command you can create a test email to `john@example.org`
|
||||||
and send it to Postfix:
|
and send it to Postfix:
|
||||||
|
|
||||||
```sh
|
```sh title="Run this on your server"
|
||||||
swaks --server localhost --to john@example.org
|
swaks --server localhost --to john@example.org
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
@ -122,7 +122,7 @@ If you see a `250 2.0.0 Ok: queued as…" near the end of this dialog, then Post
|
||||||
|
|
||||||
Check if Postfix managed to pass the email to Dovecot:
|
Check if Postfix managed to pass the email to Dovecot:
|
||||||
|
|
||||||
```sh
|
```sh title="Run this on your server"
|
||||||
journalctl -n 10 -u dovecot
|
journalctl -n 10 -u dovecot
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
@ -134,7 +134,7 @@ Aug 24 21:36:22 mail dovecot[23214]: lmtp(john@example.org)<…><…>: msgid=<20
|
||||||
|
|
||||||
Does it say `saved mail to INBOX`? Awesome. The email should be visible in John's home directory. Check it:
|
Does it say `saved mail to INBOX`? Awesome. The email should be visible in John's home directory. Check it:
|
||||||
|
|
||||||
```sh
|
```sh title="Run this on your server"
|
||||||
find /var/vmail/example.org/john
|
find /var/vmail/example.org/john
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -143,7 +143,7 @@ $config['plugins'] = array(
|
||||||
Plugins are configured through files located in the `/etc/roundcube/plugins` directory. Let's quickly set up the
|
Plugins are configured through files located in the `/etc/roundcube/plugins` directory. Let's quickly set up the
|
||||||
password plugin:
|
password plugin:
|
||||||
|
|
||||||
```sh
|
```sh title="Run this on your server"
|
||||||
cat > /etc/roundcube/plugins/password/config.inc.php << 'EOF'
|
cat > /etc/roundcube/plugins/password/config.inc.php << 'EOF'
|
||||||
<?php
|
<?php
|
||||||
$config['password_driver'] = 'sql';
|
$config['password_driver'] = 'sql';
|
||||||
|
|
|
||||||
|
|
@ -10,34 +10,41 @@ import { Aside } from "@astrojs/starlight/components";
|
||||||
|
|
||||||
Your mail server is almost ready for use. But one puzzle piece is missing. Your users can receive emails but they cannot
|
Your mail server is almost ready for use. But one puzzle piece is missing. Your users can receive emails but they cannot
|
||||||
send them yet. This part of the guide is a bit longer than others because forwarding emails has security implications.
|
send them yet. This part of the guide is a bit longer than others because forwarding emails has security implications.
|
||||||
This is important to understand so don't skip it.
|
|
||||||
|
|
||||||
Let's begin with the difference of how **users** send emails versus how **mail servers** send emails. For comparison:
|
Let's begin with the difference of how **users** send emails versus how **mail servers** send emails.
|
||||||
|
|
||||||
- A **mail server** fetches the _MX_ record for the destination domain of the recipient’s email address from DNS. That
|
- A **mail server** fetches the _MX_ record for the destination domain of the recipient’s email address from DNS. That
|
||||||
tells it which mail server to talk to. Then it opens an SMTP connection (TCP port 25) and sends the email.
|
tells it which mail server to talk to. Then it opens an SMTP connection (TCP port 25) and sends the email. A mail
|
||||||
- An **end user** with a mail client such as Thunderbird or Roundcube does not work that way. Mail clients do not
|
server will not relay an email. It will only accept it for its own users.
|
||||||
include any functionality for fetching MX records. In addition, the user is usually on a dynamic IP address that other
|
- An **end user** with a mail client such as Thunderbird or Roundcube cannot do that. Mail clients do not include any
|
||||||
mail servers will not trust and will likely reject. Instead, end users are expected to send their emails through their
|
functionality for fetching MX records. In addition, the user is usually on a dynamic IP address that other mail
|
||||||
|
servers will not trust and will likely reject. Instead, end users are expected to send their emails through their
|
||||||
provider’s (your) mail server: they authenticate with their login credentials and then send the message. This process
|
provider’s (your) mail server: they authenticate with their login credentials and then send the message. This process
|
||||||
is called relaying, because your mail server acts as an intermediary between the user and other mail servers on the
|
is called relaying, because your mail server acts as an intermediary between the user and other mail servers on the
|
||||||
internet. For security reasons, authentication is required before the user is allowed to send emails. Users are also
|
internet. For security reasons, authentication is required before the user is allowed to send emails. Users are also
|
||||||
expected to use the TCP port 587 which is called the _submission_ port. More on that later.
|
expected to use the TCP port 587 which is called the _submission_ port. More on that later.
|
||||||
|
|
||||||
|
Postfix must only accept an email from a user, if…
|
||||||
|
|
||||||
|
- The user uses the **submission** port (and not the standard **SMTP** port)
|
||||||
|
- The user **authenticates** with the username (in our setup: the email address) and the password
|
||||||
|
- The connection is **encrypted** so that the password can be safely transmitted
|
||||||
|
- The **sender address** of the email matches the user's account
|
||||||
|
|
||||||
## SMTP versus Submission
|
## SMTP versus Submission
|
||||||
|
|
||||||
Let's compare those services and ports side-by-side:
|
Let's compare those services and ports side-by-side:
|
||||||
|
|
||||||
| Service name | SMTP | Submission | Submissions |
|
| Service name | SMTP | Submission | SubmissionS (S=secure) |
|
||||||
| -------------------- | --------------------------- | ---------------------------- | --------------------- |
|
| -------------------- | --------------------------- | ---------------------------- | ---------------------- |
|
||||||
| TCP Port | 25 | 587 | 465 |
|
| TCP Port | 25 | 587 | 465 |
|
||||||
| Transport encryption | **Off**. STARTTLS optional. | **Off**. STARTTLS mandatory. | TLS all the time |
|
| Meant for | Other mail servers | Our users | Our users |
|
||||||
| Authentication | Optional [^1] | Mandatory | Mandatory |
|
| Used by | Mail transport agent (MTA) | Mail user agent (MUA) | Mail user agent (MUA) |
|
||||||
| Accepted sender | Anyone | Our own users | Our own users |
|
| Transport encryption | **Off**. STARTTLS optional. | **Off**. STARTTLS mandatory. | TLS all the time |
|
||||||
| Accepted receivers | Our own users | Anyone | Anyone |
|
| Authentication | Optional [^1] | Mandatory | Mandatory |
|
||||||
| Meant for | Servers | Our users | Our users |
|
| Accepted sender | Anyone | Our own users | Our own users |
|
||||||
| Used by | Mail transport agent (MTA) | Mail user agent (MUA) | Mail user agent (MUA) |
|
| Accepted receivers | Our own users | Anyone | Anyone |
|
||||||
| Your home ISP | may block this port | will allow this port | will allow this port |
|
| Your home ISP | may block this port | will allow this port | will allow this port |
|
||||||
|
|
||||||
[^1]:
|
[^1]:
|
||||||
In previous guides I recommended to set `smtpd_sasl_auth_enable=yes` globally in the `main.cf`. That would indeed
|
In previous guides I recommended to set `smtpd_sasl_auth_enable=yes` globally in the `main.cf`. That would indeed
|
||||||
|
|
@ -54,61 +61,79 @@ communication.
|
||||||
## Configure the submission[s] services
|
## Configure the submission[s] services
|
||||||
|
|
||||||
All Postfix services are declared in the `/etc/postfix/master.cf` file. Most of them are used by Postfix internally,
|
All Postfix services are declared in the `/etc/postfix/master.cf` file. Most of them are used by Postfix internally,
|
||||||
like `pickup`, `cleanup`, `rewrite` or `bounce`. Let's add a new service for `submission` by running:
|
like `pickup`, `cleanup`, `rewrite` or `bounce`. But `submission` is not configured by default. Let's fix that.
|
||||||
|
|
||||||
```sh
|
```sh title="Run this on your server" title="Run this on your server"
|
||||||
postconf -M submission/inet="submission inet n - y - - smtpd"
|
postconf -M submission/inet="submission inet n - y - - smtpd"
|
||||||
postconf -P "submission/inet/syslog_name=postfix/submission"
|
postconf -P "submission/inet/syslog_name=postfix/submission"
|
||||||
postconf -P "submission/inet/smtpd_tls_security_level=encrypt"
|
postconf -P "submission/inet/smtpd_tls_security_level=encrypt"
|
||||||
postconf -P "submission/inet/smtpd_sasl_auth_enable=yes"
|
postconf -P "submission/inet/smtpd_sasl_auth_enable=yes"
|
||||||
|
postconf -P "submission/inet/smtpd_sasl_type=dovecot"
|
||||||
|
postconf -P "submission/inet/smtpd_sasl_path=private/auth"
|
||||||
postconf -P "submission/inet/smtpd_recipient_restrictions=permit_sasl_authenticated,reject"
|
postconf -P "submission/inet/smtpd_recipient_restrictions=permit_sasl_authenticated,reject"
|
||||||
postconf -P "submission/inet/smtpd_sender_restrictions=reject_sender_login_mismatch,permit_sasl_authenticated,reject"
|
postconf -P "submission/inet/smtpd_sender_restrictions=reject_sender_login_mismatch,permit_sasl_authenticated,reject"
|
||||||
|
|
||||||
|
postfix reload
|
||||||
```
|
```
|
||||||
|
|
||||||
That looked confusing, right? What it did was define the `submission` service in the `/etc/postfix/master.cf` service
|
These commands added a `submission` service to the `/etc/postfix/master.cf` file. You could have achieved the same thing
|
||||||
for you using the `postconf` command. You could have achieved the same thing by editing that file and adding this
|
by editing that file and adding the following section, but I wanted to make it simpler for you to just copy/paste the
|
||||||
section:
|
commands into your shell.
|
||||||
|
|
||||||
```
|
```
|
||||||
submission inet n - y - - smtpd
|
submission inet n - y - - smtpd
|
||||||
-o syslog_name=postfix/submission
|
-o syslog_name=postfix/submission
|
||||||
-o smtpd_tls_security_level=encrypt
|
-o smtpd_tls_security_level=encrypt
|
||||||
-o smtpd_sasl_auth_enable=yes
|
-o smtpd_sasl_auth_enable=yes
|
||||||
|
-o smtpd_sasl_type=dovecot
|
||||||
|
-o smtpd_sasl_path=private/auth
|
||||||
-o smtpd_recipient_restrictions=permit_sasl_authenticated,reject
|
-o smtpd_recipient_restrictions=permit_sasl_authenticated,reject
|
||||||
```
|
```
|
||||||
|
|
||||||
Some notes on that:
|
Some notes on that:
|
||||||
|
|
||||||
- Lines with options (`-o`) need to be indented so that Postfix understands that they belong to the same service.
|
- Lines with **options** (`-o`) need to be indented so that Postfix understands that they belong to the same service.
|
||||||
- The word `submission` refers to the definition of the service in the `/etc/services` file. So it translates to TCP
|
- The word **submission** refers to the definition of the service in the `/etc/services` file. So it translates to TCP
|
||||||
port 587.
|
port 587.
|
||||||
- The `smtpd` at the end tells Postfix that connections should be handled as incoming SMTP connections.
|
- The **smtpd** in the last column of the first row tells Postfix that connections should be handled as incoming SMTP
|
||||||
|
connections.
|
||||||
- **syslog_name** is adding `postfix/submission` to log files so that you can distinguish it from other connections.
|
- **syslog_name** is adding `postfix/submission` to log files so that you can distinguish it from other connections.
|
||||||
|
- **smtpd_tls_security_level** enabled and enforces the use of STARTTLS. The connection starts without encryption but
|
||||||
|
the remote party is required to send the `STARTTLS` command to switch to an encrypted connection.
|
||||||
- **smtpd_sasl_auth_enable** enables authentication on this port. SASL is short for _Simple Authentication and Security
|
- **smtpd_sasl_auth_enable** enables authentication on this port. SASL is short for _Simple Authentication and Security
|
||||||
Layer_.
|
Layer_. That way only our own users can use this service.
|
||||||
|
- **smtpd_sasl_type** tells Postfix to use Dovecot's service to authentication a uaser.
|
||||||
|
- **smtpd_sasl_path** tells Postfix that it should talk to Dovecot through the socket file
|
||||||
|
`/var/spool/postfix/private/auth`. Earlier in this guide you told Dovecot to create that socket at that location.
|
||||||
- **smtpd_recipient_restrictions** define that only authenticated connections are permitted. Without a username and a
|
- **smtpd_recipient_restrictions** define that only authenticated connections are permitted. Without a username and a
|
||||||
password your connection will be rejected. The **recipient** keyword tells us that this restricts who the recipient
|
password your connection will be rejected. The **recipient** keyword tells us that this restricts who the recipient
|
||||||
can be.
|
can be.
|
||||||
- **smtpd_sender_restrictions** deals with the **sender**. I will explain that in the next section.
|
- **smtpd_sender_restrictions** restricts who the **sender** may be. I will explain that
|
||||||
|
[later](#protecting-against-forged-sender-addresses).
|
||||||
|
|
||||||
While you are at it, create the `submissions` (with an "s" at the end) service as well:
|
While you are at it, create the `submissions` (with an "s" at the end) service as well:
|
||||||
|
|
||||||
```sh
|
```sh title="Run this on your server"
|
||||||
postconf -M submissions/inet="submissions inet n - y - - smtpd"
|
postconf -M submissions/inet="submissions inet n - y - - smtpd"
|
||||||
postconf -P "submissions/inet/syslog_name=postfix/submissions"
|
postconf -P "submissions/inet/syslog_name=postfix/submissions"
|
||||||
postconf -P "submissions/inet/smtpd_tls_wrappermode=yes"
|
postconf -P "submissions/inet/smtpd_tls_wrappermode=yes"
|
||||||
postconf -P "submissions/inet/smtpd_sasl_auth_enable=yes"
|
postconf -P "submissions/inet/smtpd_sasl_auth_enable=yes"
|
||||||
|
postconf -P "submissions/inet/smtpd_sasl_type=dovecot"
|
||||||
|
postconf -P "submissions/inet/smtpd_sasl_path=private/auth"
|
||||||
postconf -P "submissions/inet/smtpd_recipient_restrictions=permit_sasl_authenticated,reject"
|
postconf -P "submissions/inet/smtpd_recipient_restrictions=permit_sasl_authenticated,reject"
|
||||||
postconf -P "submissions/inet/smtpd_sender_restrictions=reject_sender_login_mismatch,permit_sasl_authenticated,reject"
|
postconf -P "submissions/inet/smtpd_sender_restrictions=reject_sender_login_mismatch,permit_sasl_authenticated,reject"
|
||||||
|
postfix reload
|
||||||
```
|
```
|
||||||
|
|
||||||
The only difference to the `submission` (without the "s" at the end) is the `smtpd_tls_wrappermode` that switches on TLS
|
The only difference to the `submission` (without the "s" at the end) is the `smtpd_tls_wrappermode` that switches on TLS
|
||||||
encryption right from the start of a connection.
|
encryption right from the start of a connection.
|
||||||
|
|
||||||
## Enable encryption
|
## Set up encryption
|
||||||
|
|
||||||
We certainly do not want our users to send their password over the wire without encryption. So the following commands
|
Whenever possible we should encrypt our traffic. For our users' passwords we make it mandatory. But even for
|
||||||
enable encryption, set the key and certificate paths for Postfix. Just run these commands
|
server-to-server connections we should encourage it. Do not confuse it with end-to-end encryption of emails. That
|
||||||
|
required using PGP or S/MIME. What we are dealing here is _transport encryption_. It encrypts the communication between
|
||||||
|
a peer server and your mail server. What the peer server does with our email is beyond our control.
|
||||||
|
|
||||||
<Aside type="danger" title="Important">
|
<Aside type="danger" title="Important">
|
||||||
|
|
||||||
|
|
@ -116,7 +141,7 @@ Please replace `mail.example.org` by the FQDN you chose.
|
||||||
|
|
||||||
</Aside>
|
</Aside>
|
||||||
|
|
||||||
```sh
|
```sh title="Run this on your server"
|
||||||
postconf smtp_tls_security_level=may
|
postconf smtp_tls_security_level=may
|
||||||
postconf smtpd_tls_security_level=may
|
postconf smtpd_tls_security_level=may
|
||||||
postconf smtpd_tls_cert_file=/etc/letsencrypt/live/mail.example.org/fullchain.pem
|
postconf smtpd_tls_cert_file=/etc/letsencrypt/live/mail.example.org/fullchain.pem
|
||||||
|
|
@ -143,153 +168,12 @@ be set for the `submission` service to enable authentication there.[^1]
|
||||||
either from a remote mail server or one of your users.
|
either from a remote mail server or one of your users.
|
||||||
</Aside>
|
</Aside>
|
||||||
|
|
||||||
## Relaying
|
|
||||||
|
|
||||||
Feel free to send a test mail using the `submission` port and encryption (using STARTTLS):
|
|
||||||
|
|
||||||
```
|
|
||||||
swaks --server localhost:587 \
|
|
||||||
--from john@example.org \
|
|
||||||
--to lisa@example.com \
|
|
||||||
-tls \
|
|
||||||
--auth-user john@example.org \
|
|
||||||
--auth-password summersun
|
|
||||||
```
|
|
||||||
|
|
||||||
Also give the `submissions` service a try:
|
|
||||||
|
|
||||||
```
|
|
||||||
swaks --server localhost:465 \
|
|
||||||
--from john@example.org \
|
|
||||||
--to lisa@example.com \
|
|
||||||
--tls-on-connect \
|
|
||||||
--auth-user john@example.org \
|
|
||||||
--auth-password summersun
|
|
||||||
```
|
|
||||||
|
|
||||||
Did you notice the difference? This time we used port **465** and instead of the `-tls` option (which uses STARTTLS to
|
|
||||||
switch to encryption) we use `--tls-on-connect` that uses TLS right from from the start.
|
|
||||||
|
|
||||||
TODO: try sending from roundcube
|
|
||||||
|
|
||||||
Put simply, a mail server will accept an email if…
|
|
||||||
|
|
||||||
- it is responsible for handling mail for the recipient’s domain (the domain is listed as a virtual domain), or
|
|
||||||
- the sender has authenticated successfully with a valid username and password.
|
|
||||||
|
|
||||||
I have created two illustrations to explain it.
|
|
||||||
|
|
||||||
### Without authentication = denied
|
|
||||||
|
|
||||||
`john@example.org` is on the internet somewhere and wants to send an email to `lisa@example.com` (which is another
|
|
||||||
domain). Your mail server is not responsible for the _example.com_ domain so it receives John’s email and would have to
|
|
||||||
forward (relay) it to the actual mail server that is responsible for …@example.com email addresses. This may seem like a
|
|
||||||
harmless scenario but your mail server must deny that:
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
Why? Because anyone can claim to be John and make your mail server forward mail. If an attacker (like a spammer) would
|
|
||||||
send millions of spam emails in John’s name through your server then other organisations will accuse *you* as the
|
|
||||||
operator of the mail server of spamming. Your mail server would be what people call an
|
|
||||||
_[open relay](https://en.wikipedia.org/wiki/Open_mail_relay)_. That is not what you want because your mail server would
|
|
||||||
get blacklisted and you will not be able to send out mail to most other servers. So without any proof that the sender is
|
|
||||||
indeed John, your server must reject the email.
|
|
||||||
|
|
||||||
Try for yourself:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
swaks --server localhost:587 \
|
|
||||||
--from john@example.org \
|
|
||||||
--to list@example.com \
|
|
||||||
-tls
|
|
||||||
```
|
|
||||||
|
|
||||||
TODO: submissions does not work yet
|
|
||||||
|
|
||||||
Towards the end of the output you will find:
|
|
||||||
|
|
||||||
```
|
|
||||||
~> MAIL FROM:<john@example.org>
|
|
||||||
<~ 250 2.1.0 Ok
|
|
||||||
~> RCPT TO:<list@example.com>
|
|
||||||
<~* 554 5.7.1 <list@example.com>: Recipient address rejected: Access denied
|
|
||||||
```
|
|
||||||
|
|
||||||
### With authentication = accepted
|
|
||||||
|
|
||||||
So how does John prove his identity? He needs to use _authenticated_ SMTP. This is similar to the previous case but
|
|
||||||
John’s email program will also send his username and password.
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
We are making sure that his authentication happens over an encrypted connection so John’s password is safe.
|
|
||||||
|
|
||||||
Try for yourself and provide a valid user name and password:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
swaks --server localhost:587 \
|
|
||||||
--from john@example.org \
|
|
||||||
--to list@example.com \
|
|
||||||
-tls \
|
|
||||||
--auth-user john@example.org \
|
|
||||||
--auth-password summersun
|
|
||||||
```
|
|
||||||
|
|
||||||
Towards the end of the output you will find:
|
|
||||||
|
|
||||||
```
|
|
||||||
<~ 250 2.0.0 Ok: queued as 7513F1F54B
|
|
||||||
```
|
|
||||||
|
|
||||||
You can even try a wrong password or a non-existing user. That should lead to…
|
|
||||||
|
|
||||||
```
|
|
||||||
<~* 535 5.7.8 Error: authentication failed: (reason unavailable)
|
|
||||||
```
|
|
||||||
|
|
||||||
TODO: a word on $mynetworks. Perhaps in the troubleshooting section later.
|
|
||||||
|
|
||||||
## Make Postfix use Dovecot for authentication
|
|
||||||
|
|
||||||
Enabling SMTP authentication in Postfix is surprisingly easy. You already configured Dovecot so it knows all about your
|
|
||||||
users from the SQL database. So let’s just make Postfix use that by telling it to ask the Dovecot server to verify the
|
|
||||||
username and password. Postfix just needs some extra configuration. Run these commands on the shell:
|
|
||||||
|
|
||||||
```
|
|
||||||
postconf smtpd_sasl_type=dovecot
|
|
||||||
postconf smtpd_sasl_path=private/dovecot-auth
|
|
||||||
```
|
|
||||||
|
|
||||||
This enables SMTP authentication and tells Postfix that it can talk to Dovecot through a socket file located at
|
|
||||||
`/var/spool/postfix/private/auth`. Do you remember that Postfix runs in a sandboxed *chroot* directory? That’s at
|
|
||||||
/var/spool/postfix. It cannot access any files outside of that directory. But fortunately in a previous section you
|
|
||||||
edited the /etc/dovecot/conf.d/10-master.conf file and made Dovecot place a socket file into
|
|
||||||
`/var/spool/postfix/private/auth` to allow communication from Postfix.
|
|
||||||
|
|
||||||
TODO: collapsible on anti-spoofing
|
|
||||||
|
|
||||||
## Protecting against forged sender addresses
|
## Protecting against forged sender addresses
|
||||||
|
|
||||||
At this stage, a security issue remains. While Postfix is configured to relay emails only after a successful login with
|
Before we can actually test the setup, there is another security issue we need to address. While Postfix is configured
|
||||||
a valid username and password, it does not prevent an authenticated user from impersonating another sender. For example,
|
to relay emails only after a successful login with a valid username and password, it does not prevent an authenticated
|
||||||
someone could log in as `john@example.org` but send an email appearing to come from `brunhilde@example.net`.
|
user from impersonating another sender. For example, someone could log in as `john@example.org` but send an email
|
||||||
|
appearing to come from `brunhilde@example.net`.
|
||||||
You want to see that this work? Let's pretend to be _brunhilde_ while authenticating as _john_:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
swaks --server localhost:587 \
|
|
||||||
--from brunhilde@example.org \
|
|
||||||
--to list@example.com \
|
|
||||||
-tls \
|
|
||||||
--auth-user john@example.org \
|
|
||||||
--auth-password summersun
|
|
||||||
```
|
|
||||||
|
|
||||||
That should not be allowed. But Postfix does not know better and responds with:
|
|
||||||
|
|
||||||
```
|
|
||||||
<~ 250 2.0.0 Ok: queued as EEEB420F51
|
|
||||||
```
|
|
||||||
|
|
||||||
We should fix that. For that purpose Postfix provides a setting called
|
We should fix that. For that purpose Postfix provides a setting called
|
||||||
[smtpd_sender_login_maps](http://www.postfix.org/postconf.5.html#smtpd_sender_login_maps). From the "maps" part you can
|
[smtpd_sender_login_maps](http://www.postfix.org/postconf.5.html#smtpd_sender_login_maps). From the "maps" part you can
|
||||||
|
|
@ -304,7 +188,7 @@ sender, he must also authenticate as `john@example.org`.
|
||||||
As we use the email address also as a user name we simply need a mapping where the email address is listed on both
|
As we use the email address also as a user name we simply need a mapping where the email address is listed on both
|
||||||
sides. Let's create it:
|
sides. Let's create it:
|
||||||
|
|
||||||
```sh
|
```sh title="Run this on your server"
|
||||||
cat > /etc/postfix/mariadb-email2email.cf << EOF
|
cat > /etc/postfix/mariadb-email2email.cf << EOF
|
||||||
user = mailserver
|
user = mailserver
|
||||||
password = MAILSERVER-PASSWORD-HERE
|
password = MAILSERVER-PASSWORD-HERE
|
||||||
|
|
@ -315,24 +199,20 @@ EOF
|
||||||
|
|
||||||
chown root:postfix /etc/postfix/mariadb-email2email.cf
|
chown root:postfix /etc/postfix/mariadb-email2email.cf
|
||||||
chmod u=rw,g=r,o= /etc/postfix/mariadb-email2email.cf
|
chmod u=rw,g=r,o= /etc/postfix/mariadb-email2email.cf
|
||||||
```
|
|
||||||
|
|
||||||
Tell Postfix to use this mapping for our purpose:
|
|
||||||
|
|
||||||
```
|
|
||||||
postconf smtpd_sender_login_maps=mysql:/etc/postfix/mariadb-email2email.cf
|
postconf smtpd_sender_login_maps=mysql:/etc/postfix/mariadb-email2email.cf
|
||||||
```
|
```
|
||||||
|
|
||||||
You have already added `smtpd_sender_restrictions=reject_sender_login_mismatch` earlier in the master.cf for the
|
What you accomplished:
|
||||||
`submission` and `submissions` services. So you have achieved these three steps to prevent sender impersonation:
|
|
||||||
|
|
||||||
1. Create a mapping that matches an email address to itself.
|
1. Create the _mapping_ file
|
||||||
2. Tell Postfix to use that mapping for `smtpd_sender_login_maps` which controls who can be a sender.
|
1. Fix the permissions of it so that only Postfix can read it (there is a password in it)
|
||||||
3. Enforce that restriction for the `submission` and `submissions` services.
|
1. Make Postfix use that mapping for its `smtpd_sender_login_maps` setting
|
||||||
|
1. Add `smtpd_sender_restrictions=reject_sender_login_mismatch` to the `submission` and `submissions` services
|
||||||
|
|
||||||
You can now try to send email as a different user than you are logged in. Let’s us swaks again to send a spoofed email:
|
You can now try to send email as a different user than you are logged in. Let’s us swaks again to send a spoofed email:
|
||||||
|
|
||||||
```sh
|
```sh title="Run this on your server"
|
||||||
swaks --server localhost:587 \
|
swaks --server localhost:587 \
|
||||||
--from brunhilde@example.org \
|
--from brunhilde@example.org \
|
||||||
--to list@example.com \
|
--to list@example.com \
|
||||||
|
|
@ -350,33 +230,113 @@ The server should rightfully reject that wrong sender:
|
||||||
<~ * 553 5.7.1 john@example.com: Sender address rejected: not owned by user john@example.org
|
<~ * 553 5.7.1 john@example.com: Sender address rejected: not owned by user john@example.org
|
||||||
```
|
```
|
||||||
|
|
||||||
You can also see that restriction in action by adding a fake persona in Roundcube and try to use it. In
|
Now let's send a proper email from John:
|
||||||
Settings/Identities you can create another sender email address as in:
|
|
||||||
|
|
||||||

|
```sh title="Run this on your server"
|
||||||
|
swaks --server localhost:587 \
|
||||||
|
--from john@example.org \
|
||||||
|
--to list@example.com \
|
||||||
|
--tls \
|
||||||
|
--auth-user john@example.org \
|
||||||
|
--auth-password summersun
|
||||||
|
```
|
||||||
|
|
||||||
With this wrong sender address any email should get rejected. Roundcube will show you an error that is generated by
|
That will work:
|
||||||
Postfix:
|
|
||||||
|
|
||||||
```
|
```
|
||||||
553 5.7.1 <someoneelse@example.com>:
|
<~ 250 2.0.0 Ok: queued as AFFF12292A
|
||||||
Sender address rejected:
|
|
||||||
not owned by user john@example.org
|
|
||||||
```
|
```
|
||||||
|
|
||||||
<Aside type="tip" title="Allow aliases?">
|
<Aside type="tip" title="Allow aliases?">
|
||||||
If you want to allow users to send as one of their aliases you could create a new \*.cf file with a mapping query like
|
|
||||||
this: `SELECT email FROM virtual_users WHERE email='%s' UNION SELECT destination FROM virtual_aliases WHERE
|
The setup so far works for personal mails from John. But if John would be a member of a distribution list
|
||||||
source='%s'`
|
`pizza@example.org` then would not be able to use `pizza@example.org` as a sender address.
|
||||||
|
|
||||||
|
If you want to allow that, create a new \*.cf file with a mapping query like this:
|
||||||
|
`SELECT email FROM virtual_users WHERE email='%s' UNION SELECT destination FROM virtual_aliases WHERE source='%s'`.
|
||||||
|
|
||||||
</Aside>
|
</Aside>
|
||||||
|
|
||||||
## How does authentication work?
|
## Test it
|
||||||
|
|
||||||
<details class="collapsible">
|
### No encryption, no authentication
|
||||||
<summary>Click here if you want to learn how SMTP authentication works…</summary>
|
|
||||||
|
|
||||||
Are you curious how SMTP authentication looks on a low level? You probably are not. But let’s do it anyway. Just once,
|
So far you have set up the `submission` service(s), enabled encryption and connected Postfix to Dovecot for
|
||||||
so that you get the idea.
|
authentication. Let's try it. Our first test email will be sent without encryption and authentication:
|
||||||
|
|
||||||
|
```sh title="Run this on your server"
|
||||||
|
swaks --server localhost:587 \
|
||||||
|
--from john@example.org \
|
||||||
|
--to lisa@example.com
|
||||||
|
```
|
||||||
|
|
||||||
|
Postfix should tell you that it will not accept an email without encryption:
|
||||||
|
|
||||||
|
```
|
||||||
|
<** 530 5.7.0 Must issue a STARTTLS command first
|
||||||
|
```
|
||||||
|
|
||||||
|
### With encryption, no authentication
|
||||||
|
|
||||||
|
Our second attempt will **enable** (STARTTLS) encryption – but still no authentication:
|
||||||
|
|
||||||
|
```sh title="Run this on your server"
|
||||||
|
swaks --server localhost:587 \
|
||||||
|
--from john@example.org \
|
||||||
|
--to lisa@example.com \
|
||||||
|
-tls
|
||||||
|
```
|
||||||
|
|
||||||
|
Postfix will still reject the email because we refused to authenticate:
|
||||||
|
|
||||||
|
```
|
||||||
|
~> MAIL FROM:<john@example.org>
|
||||||
|
<~ 250 2.1.0 Ok
|
||||||
|
~> RCPT TO:<lisa@example.com>
|
||||||
|
<~* 554 5.7.1 <john@example.org>: Sender address rejected: Access denied
|
||||||
|
```
|
||||||
|
|
||||||
|
### With encryption and authentication
|
||||||
|
|
||||||
|
```sh title="Run this on your server"
|
||||||
|
swaks --server localhost:587 \
|
||||||
|
--from john@example.org \
|
||||||
|
--to lisa@example.com \
|
||||||
|
-tls \
|
||||||
|
--auth-user john@example.org \
|
||||||
|
--auth-password summersun
|
||||||
|
```
|
||||||
|
|
||||||
|
Also give the `submissions` service a try:
|
||||||
|
|
||||||
|
```sh title="Run this on your server"
|
||||||
|
swaks --server localhost:465 \
|
||||||
|
--from john@example.org \
|
||||||
|
--to lisa@example.com \
|
||||||
|
--tls-on-connect \
|
||||||
|
--auth-user john@example.org \
|
||||||
|
--auth-password summersun
|
||||||
|
```
|
||||||
|
|
||||||
|
Did you notice the difference? This time we used port **465** and instead of the `-tls` option (which uses STARTTLS to
|
||||||
|
switch to encryption) we use `--tls-on-connect` that uses TLS right from from the start.
|
||||||
|
|
||||||
|
Put simply, a mail server will accept an email if…
|
||||||
|
|
||||||
|
- it is responsible for handling mail for the recipient’s domain (the domain is listed as a virtual domain), or
|
||||||
|
- the sender has authenticated successfully with a valid username and password.
|
||||||
|
|
||||||
|
I have created two illustrations to explain it.
|
||||||
|
|
||||||
|
## Gory details of authentication
|
||||||
|
|
||||||
|
<Aside type="tip" title="For science">
|
||||||
|
|
||||||
|
This section is just here to show you the communication that happens on the network when relaying an email. It is no
|
||||||
|
mandatory reading matter. But relaying is a complex matter where things can go wrong. So taking a peek under hood may
|
||||||
|
improve your understanding.
|
||||||
|
|
||||||
|
</Aside>
|
||||||
|
|
||||||
```
|
```
|
||||||
telnet localhost submission
|
telnet localhost submission
|
||||||
|
|
@ -387,7 +347,7 @@ The server will let you in:
|
||||||
```
|
```
|
||||||
Trying 127.0.0.1…
|
Trying 127.0.0.1…
|
||||||
Connected to localhost.
|
Connected to localhost.
|
||||||
Escape character is '^\]'.
|
Escape character is '^]'.
|
||||||
220 webmail ESMTP Postfix (Debian/GNU)
|
220 webmail ESMTP Postfix (Debian/GNU)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
@ -426,8 +386,8 @@ Let me briefly explain what these lines mean:
|
||||||
nowadays 40 MB or even more are more common sizes because emails have grown larger. Some mail servers even allow 100 MB.
|
nowadays 40 MB or even more are more common sizes because emails have grown larger. Some mail servers even allow 100 MB.
|
||||||
- VRFY
|
- VRFY
|
||||||
Allows remote servers to verify a given name or email address. For example the remote server could send "VRFY john" and
|
Allows remote servers to verify a given name or email address. For example the remote server could send "VRFY john" and
|
||||||
your server might respond `250 John Doe <john@example.org>`. It can be used to verify that a certain recipient email address
|
your server might respond `250 Jo You can skip it for now.hn Doe <john@example.org>`. It can be used to verify that a certain
|
||||||
is deliverable
|
recipient email address is deliverable
|
||||||
- ETRN
|
- ETRN
|
||||||
A command that a remote system can send to flush the Postfix queue of mails for a certain domain. It can be used if the
|
A command that a remote system can send to flush the Postfix queue of mails for a certain domain. It can be used if the
|
||||||
remote system had technical problems and failed to receive email for a while. Then it could send an ETRN command to make
|
remote system had technical problems and failed to receive email for a while. Then it could send an ETRN command to make
|
||||||
|
|
@ -551,7 +511,3 @@ printf '\0john@example.org\0summersun' | base64
|
||||||
```
|
```
|
||||||
|
|
||||||
As a result you will get the exact same string you used above with "AUTH PLAIN".
|
As a result you will get the exact same string you used above with "AUTH PLAIN".
|
||||||
|
|
||||||
TODO: move further down
|
|
||||||
|
|
||||||
</details>
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue