re-order pages. add page on lmtp.
This commit is contained in:
parent
b97d7b03da
commit
759ed36026
5 changed files with 215 additions and 53 deletions
157
src/content/docs/ispmail-trixie/160-postfix.mdx
Normal file
157
src/content/docs/ispmail-trixie/160-postfix.mdx
Normal file
|
|
@ -0,0 +1,157 @@
|
|||
---
|
||||
title: "Postfix"
|
||||
lastUpdated: 2025-08-20
|
||||
slug: ispmail-trixie/postfix
|
||||
sidebar:
|
||||
order: 160
|
||||
---
|
||||
|
||||
import { Aside } from "@astrojs/starlight/components";
|
||||
|
||||
import { Steps } from "@astrojs/starlight/components";
|
||||
|
||||
import Box from "../../../components/Box.astro";
|
||||
|
||||
import StepListReceive from "../../../components/StepListReceive.astro";
|
||||
|
||||
<StepListReceive currentStep={3} />
|
||||
|
||||
Now that other mail servers can locate your mail server, the next step is to make sure it can receive and process
|
||||
incoming emails. This task is handled by Postfix, which communicates using the SMTP protocol.
|
||||
|
||||
Postfix knows if an email address is valid by checking for…
|
||||
|
||||
- **Virtual Domains** (am I responsible for this domain?)
|
||||
- **Virtual Aliases** (do I have to redirect this address to another address?)
|
||||
- **Virtual Mailboxes** (do I have a valid mailbox to store the email to?)
|
||||
|
||||
### Virtual Domains
|
||||
|
||||
There are different ways for Postfix to get that information. From text files, LDAP, MongoDB or PostgreSQL. Or via
|
||||
MariaDB – which is what we will use. But whatever kind of data source you configure, Postfix needs the information as a
|
||||
_mapping_. Consider it as a _question_ and an _answer_.
|
||||
|
||||
- Question: is `example.org` one of our virtual domains?
|
||||
- Answer: yes
|
||||
|
||||
If the information is **not** available you just get no answer:
|
||||
|
||||
- Question: is `example.net` one of our virtual domains?
|
||||
- Answer: _(no answer)_
|
||||
|
||||
In SQL language Postfix has to ask MariaDB the question:
|
||||
|
||||
```sql
|
||||
SELECT "yes" FROM virtual_domains WHERE name='example.net'
|
||||
```
|
||||
|
||||
Run the following code in your shell to create a configuration file creating that mapping:
|
||||
|
||||
```sh
|
||||
cat > /etc/postfix/mariadb-virtual-mailbox-domains.cf << EOF
|
||||
user = mailserver
|
||||
password = SECOND-PASSWORD-HERE
|
||||
hosts = 127.0.0.1
|
||||
dbname = mailserver
|
||||
query = SELECT 1 FROM virtual_domains WHERE name='%s'
|
||||
EOF
|
||||
```
|
||||
|
||||
This has created a configuration file called `/etc/postfix/virtual-mailbox-domains.cf`. The `user`, `password`, `hosts`
|
||||
and `dbname` definitions tell Postfix how to connect to the database. And the `query` asks the _question_ if a certain
|
||||
domain is present in the database table `virtual_domains`. Using `SELECT 1` we return just the number 1 if such an entry
|
||||
was found. In fact it does not matter what we return. Any _answer_ is fine.
|
||||
|
||||
Don't forget to replace the `SECOND-PASSWORD-HERE` by your own password for the `mailserver` user.
|
||||
|
||||
### Virtual Aliases
|
||||
|
||||
Now let's deal with aliases. As shown earlier an alias redirects an email to another email address. So the _question_
|
||||
and _answer_ game goes like this:
|
||||
|
||||
- Question: is there an alias for `jack@example.org`?
|
||||
- Answer: `john@example.org`
|
||||
|
||||
Postfix would then check if there are further aliases:
|
||||
|
||||
- Question: is there an alias for `john@example.org`?
|
||||
- Answer: _(no answer)_
|
||||
|
||||
Apparently, there aren't any more. So the email will go to `john@example.org`.
|
||||
|
||||
Run this code to create the appropriate mapping file:
|
||||
|
||||
```sh
|
||||
cat > /etc/postfix/mariadb-virtual-alias-maps.cf << EOF
|
||||
user = mailserver
|
||||
password = SECOND-PASSWORD-HERE
|
||||
hosts = 127.0.0.1
|
||||
dbname = mailserver
|
||||
query = SELECT destination FROM virtual_aliases WHERE source='%s'
|
||||
EOF
|
||||
```
|
||||
|
||||
The query now gets all the `destination` email addresses from the database for a certain `source` email address.
|
||||
|
||||
### Virtual Mailboxes
|
||||
|
||||
The last mapping we need is a query to find valid mailboxes. Without further ado:
|
||||
|
||||
```sh
|
||||
cat > /etc/postfix/mariadb-virtual-mailbox-maps.cf << EOF
|
||||
user = mailserver
|
||||
password = SECOND-PASSWORD-HERE
|
||||
hosts = 127.0.0.1
|
||||
dbname = mailserver
|
||||
query = SELECT 1 FROM virtual_users WHERE email='%s'
|
||||
EOF
|
||||
```
|
||||
|
||||
Just the same story as with virtual domains. The database returns `1` if there is a `virtual_users` record matching that
|
||||
specific email address.
|
||||
|
||||
Actually the _answer_ is usually not `1` but the path to the mailbox on disk. But that applies only if Postfix would be
|
||||
saving the email to disk on its own. In our setup the email will be passed on to Dovecot in a later step. Dovecot will
|
||||
then handle the files on disk. Postfix just has to know is whether a mailbox exists. And that's why **any** _answer_ is
|
||||
sufficient here.
|
||||
|
||||
### Tell Postfix
|
||||
|
||||
You have created the config files for the three mappings. Now you just need to tell Postfix to use them:
|
||||
|
||||
```sh
|
||||
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_alias_maps=mysql:/etc/postfix/mariadb-virtual-alias-maps.cf
|
||||
|
||||
chown root:postfix /etc/postfix/mariadb-*.cf
|
||||
chmod o= /etc/postfix/mariadb-*.cf
|
||||
```
|
||||
|
||||
`postconf` is a command that changes configuration in `/etc/postfix/main.cf` and applies them instantly. You don't have
|
||||
to restart Postfix.
|
||||
|
||||
The last two lines set the owner of the config files (_user=root, group=postfix_) and make sure that _others_ have no
|
||||
access. After all a database password is found in these files.
|
||||
|
||||
<Aside icon="approve-check-circle" title="Test it">
|
||||
|
||||
Give the mappings a quick test using the `postmap -q` command (_q_ stands for _query_):
|
||||
|
||||
```sh
|
||||
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 john@example.org mysql:/etc/postfix/mariadb-virtual-mailbox-maps.cf
|
||||
```
|
||||
|
||||
These three commands use the three mapping files (`*.cf`) to query your three database tables. The result should show:
|
||||
|
||||
```
|
||||
1
|
||||
john@example.org
|
||||
1
|
||||
```
|
||||
|
||||
If you get anything else, please check those three config files. Perhaps the database password is wrong?
|
||||
|
||||
</Aside>
|
||||
Loading…
Add table
Add a link
Reference in a new issue