1
0
mirror of https://blitiri.com.ar/repos/chasquid synced 2026-10-28 15:02:28 +00:00

docs: Auto-format markdown documentation

This patch uses mdformat to auto-format markdown documentation.

To support \ for line breaks (which is what mdformat uses), mkdocs now
requires the pymdownx.escapeall extension.

Because of incompatibilities between mdformat (which formats to
CommonMark) and mkdocs (which expects Python-Markdown), there are now
some limitations: no nested lists, multi-paragraph list items, or
admonitions support.

These limitations are acceptable for now, although some of the docs had
to be adjusted to meet them.
This commit is contained in:
Alberto Bertogli
2026-10-14 15:14:42 +01:00
parent 6cc59ca661
commit 9a59bd77d1
22 changed files with 355 additions and 493 deletions
+2
View File
@@ -14,6 +14,8 @@ markdown_extensions:
guess_lang: false guess_lang: false
- attr_list - attr_list
- admonition - admonition
- pymdownx.escapeall:
hardbreak: true
theme: readthedocs theme: readthedocs
+4 -1
View File
@@ -60,10 +60,13 @@ fmt:
gofmt -s -w . gofmt -s -w .
go fix ./... go fix ./...
clang-format -i $(shell find . -iname '*.proto') clang-format -i $(shell find . -iname '*.proto')
black -l 79 \ black -l 79 --quiet \
test/util/check-hostaliases \ test/util/check-hostaliases \
test/util/chamuyero \ test/util/chamuyero \
test/util/mail_diff test/util/mail_diff
mdformat --wrap 79 --number \
--exclude 'docs/man/*.[15].md' \
README.md docs/
.PHONY: chasquid test \ .PHONY: chasquid test \
chasquid-util smtp-check mda-lmtp dovecot-auth-cli \ chasquid-util smtp-check mda-lmtp dovecot-auth-cli \
+39 -45
View File
@@ -1,4 +1,3 @@
# chasquid # chasquid
[chasquid](https://blitiri.com.ar/p/chasquid) is an SMTP (email) server with a [chasquid](https://blitiri.com.ar/p/chasquid) is an SMTP (email) server with a
@@ -11,64 +10,45 @@ It's written in [Go](https://golang.org), and distributed under the
[![Go tests](https://github.com/albertito/chasquid/actions/workflows/gotests.yml/badge.svg?branch=main)](https://github.com/albertito/chasquid/actions) [![Go tests](https://github.com/albertito/chasquid/actions/workflows/gotests.yml/badge.svg?branch=main)](https://github.com/albertito/chasquid/actions)
[![Go Report Card](https://goreportcard.com/badge/github.com/albertito/chasquid)](https://goreportcard.com/report/github.com/albertito/chasquid) [![Go Report Card](https://goreportcard.com/badge/github.com/albertito/chasquid)](https://goreportcard.com/report/github.com/albertito/chasquid)
[![Coverage](https://coveralls.io/repos/github/albertito/chasquid/badge.svg?branch=next)](https://coveralls.io/github/albertito/chasquid?branch=next) [![Coverage](https://coveralls.io/repos/github/albertito/chasquid/badge.svg?branch=next)](https://coveralls.io/github/albertito/chasquid?branch=next)\
[![Docs](https://img.shields.io/badge/docs-reference-blue.svg)](https://blitiri.com.ar/p/chasquid/) [![Docs](https://img.shields.io/badge/docs-reference-blue.svg)](https://blitiri.com.ar/p/chasquid/)
[![OFTC IRC](https://img.shields.io/badge/chat-oftc-blue.svg)](https://webchat.oftc.net/?channels=%23chasquid) [![OFTC IRC](https://img.shields.io/badge/chat-oftc-blue.svg)](https://webchat.oftc.net/?channels=%23chasquid)
## Features ## Features
* Easy - Easy
* Easy to configure. - Easy to configure.
* Hard to mis-configure in ways that are harmful or insecure (e.g. no open - Hard to mis-configure in ways that are harmful or insecure (e.g. no open
relay, or clear-text authentication). relay, or clear-text authentication).
* [Monitoring] HTTP server, with exported variables and tracing to help - [Monitoring] HTTP server, with exported variables and tracing to help
debugging. debugging.
* Integrated with [Debian], [Ubuntu], [Arch], and [Alpine]. - Integrated with [Debian], [Ubuntu], [Arch], and [Alpine].
* Supports using [Dovecot] for authentication. - Supports using [Dovecot] for authentication.
* Useful - Useful
* Multiple/virtual domains, with per-domain users and aliases. - Multiple/virtual domains, with per-domain users and aliases.
* Suffix dropping (`user+something@domain` → `user@domain`). - Suffix dropping (`user+something@domain` → `user@domain`).
* [Hooks] for integration with greylisting, anti-virus, and anti-spam. - [Hooks] for integration with greylisting, anti-virus, and anti-spam.
* International usernames ([SMTPUTF8]) and domain names ([IDNA]). - International usernames ([SMTPUTF8]) and domain names ([IDNA]).
* Secure - Secure
* [Tracking] of per-domain TLS support, prevents connection downgrading. - [Tracking] of per-domain TLS support, prevents connection downgrading.
* Multiple TLS certificates. - Multiple TLS certificates.
* Easy integration with [Let's Encrypt]. - Easy integration with [Let's Encrypt].
* [SPF] and [MTA-STS] checking. - [SPF] and [MTA-STS] checking.
* [DKIM] support (signing and verification). - [DKIM] support (signing and verification).
[Arch]: https://blitiri.com.ar/p/chasquid/install/#arch
[Alpine]: https://blitiri.com.ar/p/chasquid/install/#alpine
[DKIM]: https://en.wikipedia.org/wiki/DomainKeys_Identified_Mail
[Debian]: https://blitiri.com.ar/p/chasquid/install/#debianubuntu
[Dovecot]: https://blitiri.com.ar/p/chasquid/dovecot/
[Hooks]: https://blitiri.com.ar/p/chasquid/hooks/
[IDNA]: https://en.wikipedia.org/wiki/Internationalized_domain_name
[Let's Encrypt]: https://letsencrypt.org
[MTA-STS]: https://tools.ietf.org/html/rfc8461
[Monitoring]: https://blitiri.com.ar/p/chasquid/monitoring/
[SMTPUTF8]: https://en.wikipedia.org/wiki/Extended_SMTP#SMTPUTF8
[SPF]: https://en.wikipedia.org/wiki/Sender_Policy_Framework
[Tracking]: https://blitiri.com.ar/p/chasquid/sec-levels/
[Ubuntu]: https://blitiri.com.ar/p/chasquid/install/#debianubuntu
## Documentation ## Documentation
The [how-to guide](https://blitiri.com.ar/p/chasquid/howto/) and the The [how-to guide](https://blitiri.com.ar/p/chasquid/howto/) and the
[installation guide](https://blitiri.com.ar/p/chasquid/install/) are the [installation guide](https://blitiri.com.ar/p/chasquid/install/) are the best
best starting points on how to install, configure and run chasquid. starting points on how to install, configure and run chasquid.
You will find [all documentation here](https://blitiri.com.ar/p/chasquid/). You will find [all documentation here](https://blitiri.com.ar/p/chasquid/).
## Contact ## Contact
If you have any questions, comments or patches, please send them to the [mailing If you have any questions, comments or patches, please send them to the
list](https://groups.google.com/forum/#!forum/chasquid), [mailing list](https://groups.google.com/forum/#!forum/chasquid),
chasquid@googlegroups.com. chasquid@googlegroups.com.\
To subscribe, send an email to chasquid+subscribe@googlegroups.com. To subscribe, send an email to chasquid+subscribe@googlegroups.com.
Security issues can be reported privately to albertito@blitiri.com.ar. Security issues can be reported privately to albertito@blitiri.com.ar.
@@ -78,3 +58,17 @@ Bug reports and pull requests on
You can also reach out via IRC, `#chasquid` on [OFTC](https://oftc.net/). You can also reach out via IRC, `#chasquid` on [OFTC](https://oftc.net/).
[alpine]: https://blitiri.com.ar/p/chasquid/install/#alpine
[arch]: https://blitiri.com.ar/p/chasquid/install/#arch
[debian]: https://blitiri.com.ar/p/chasquid/install/#debianubuntu
[dkim]: https://en.wikipedia.org/wiki/DomainKeys_Identified_Mail
[dovecot]: https://blitiri.com.ar/p/chasquid/dovecot/
[hooks]: https://blitiri.com.ar/p/chasquid/hooks/
[idna]: https://en.wikipedia.org/wiki/Internationalized_domain_name
[let's encrypt]: https://letsencrypt.org
[monitoring]: https://blitiri.com.ar/p/chasquid/monitoring/
[mta-sts]: https://tools.ietf.org/html/rfc8461
[smtputf8]: https://en.wikipedia.org/wiki/Extended_SMTP#SMTPUTF8
[spf]: https://en.wikipedia.org/wiki/Sender_Policy_Framework
[tracking]: https://blitiri.com.ar/p/chasquid/sec-levels/
[ubuntu]: https://blitiri.com.ar/p/chasquid/install/#debianubuntu
+12 -16
View File
@@ -1,4 +1,3 @@
# Docker # Docker
chasquid comes with a Dockerfile to create a container running [chasquid], chasquid comes with a Dockerfile to create a container running [chasquid],
@@ -7,18 +6,13 @@ chasquid comes with a Dockerfile to create a container running [chasquid],
Note these are less thoroughly tested than the [traditional setup](howto.md), Note these are less thoroughly tested than the [traditional setup](howto.md),
which is the recommended way to use chasquid. which is the recommended way to use chasquid.
[chasquid]: https://blitiri.com.ar/p/chasquid
[dovecot]: https://dovecot.org
[Let's Encrypt]: https://letsencrypt.org
## Images ## Images
There are pre-built images at the There are pre-built images at the
[gitlab registry](https://gitlab.com/albertito/chasquid/container_registry) [gitlab registry](https://gitlab.com/albertito/chasquid/container_registry) and
and [dockerhub](https://hub.docker.com/r/albertito/chasquid). [dockerhub](https://hub.docker.com/r/albertito/chasquid). They are
They are automatically built, and tagged with the corresponding branch name. automatically built, and tagged with the corresponding branch name. Use the
Use the *main* tag for a stable version. *main* tag for a stable version.
If, instead, you want to build the image yourself, just run: If, instead, you want to build the image yourself, just run:
@@ -59,12 +53,12 @@ Password:
pepe@example.com added to /data/dovecot/users pepe@example.com added to /data/dovecot/users
``` ```
Upon startup, the image will obtain a TLS certificate for you using [Let's Upon startup, the image will obtain a TLS certificate for you using
Encrypt](https://letsencrypt.com/). You need to tell it the domain(s) to get a [Let's Encrypt](https://letsencrypt.com/). You need to tell it the domain(s) to
certificate from by setting the `AUTO_CERTS` variable. get a certificate from by setting the `AUTO_CERTS` variable.
Because certificates expire, you should restart the container every week or Because certificates expire, you should restart the container every week or so.
so. Certificates will be renewed automatically upon startup if needed. Certificates will be renewed automatically upon startup if needed.
In order for chasquid to get access to the source IP address, you will need to In order for chasquid to get access to the source IP address, you will need to
use host networking, or create a custom docker network that does IP forwarding use host networking, or create a custom docker network that does IP forwarding
@@ -79,10 +73,12 @@ $ docker run -e AUTO_CERTS=mail.yourdomain.com \
registry.gitlab.com/albertito/chasquid:main registry.gitlab.com/albertito/chasquid:main
``` ```
## Debugging ## Debugging
To get a shell on the running container for debugging, you can use `docker ps` To get a shell on the running container for debugging, you can use `docker ps`
to find the container ID, and then `docker exec -it CONTAINERID /bin/bash` to to find the container ID, and then `docker exec -it CONTAINERID /bin/bash` to
open a shell on the running container. open a shell on the running container.
[chasquid]: https://blitiri.com.ar/p/chasquid
[dovecot]: https://dovecot.org
[let's encrypt]: https://letsencrypt.org
+16 -23
View File
@@ -1,9 +1,7 @@
# Aliases # Aliases
[chasquid] supports [email aliases], which is a mechanism to redirect mail [chasquid] supports [email aliases], which is a mechanism to redirect mail from
from one account to others. one account to others.
## File format ## File format
@@ -42,8 +40,8 @@ email will be forwarded using
While the content of the message will not be changed, the envelope sender will While the content of the message will not be changed, the envelope sender will
be the constructed from the alias user. be the constructed from the alias user.
User names cannot contain spaces, ":" or commas, for parsing reasons. This is User names cannot contain spaces, ":" or commas, for parsing reasons. This is a
a tradeoff between flexibility and keeping the file format easy to edit for tradeoff between flexibility and keeping the file format easy to edit for
people. User names will be normalized internally to lower-case. UTF-8 is people. User names will be normalized internally to lower-case. UTF-8 is
allowed and fully supported. allowed and fully supported.
@@ -52,8 +50,8 @@ allowed and fully supported.
A pipe alias is of the form `user: | command`, and causes mail to be sent as A pipe alias is of the form `user: | command`, and causes mail to be sent as
standard input to the given command. standard input to the given command.
The command can have space-separated arguments (no quotes or escaping The command can have space-separated arguments (no quotes or escaping expansion
expansion will be performed). will be performed).
For example: For example:
@@ -76,13 +74,12 @@ pepe: jose
*: pepe, rose@backgarden *: pepe, rose@backgarden
``` ```
If the destination address has `*` as its user, then it will be replaced If the destination address has `*` as its user, then it will be replaced by the
by the sender user. Note that in this case, the user is copied as-is, no sender user. Note that in this case, the user is copied as-is, no characters or
characters or suffixes will be dropped. suffixes will be dropped.
For example, `*: *@pond` will redirect `lilly@domain` to `lilly@pond`. For example, `*: *@pond` will redirect `lilly@domain` to `lilly@pond`.
### "Via" aliases {#via} ### "Via" aliases {#via}
A "via" alias is like an email alias, but it explicitly specifies which A "via" alias is like an email alias, but it explicitly specifies which
@@ -111,7 +108,6 @@ flowers: lilly@pond via mail1.pond/mail2.pond
*: * via mail1.example.com *: * via mail1.example.com
``` ```
### Overrides ### Overrides
If the same left-side address appears more than once, the last one will take If the same left-side address appears more than once, the last one will take
@@ -156,31 +152,29 @@ juana.perez+fruta -> fruta
juanaperez+fruta -> fruta juanaperez+fruta -> fruta
``` ```
This allows addresses with suffixes to have specific aliases, without having This allows addresses with suffixes to have specific aliases, without having to
to worry about drop characters, which is the most common use case. worry about drop characters, which is the most common use case.
If different semantics are needed, they can be implemented using the If different semantics are needed, they can be implemented using the
[hook](#hooks). [hook](#hooks).
## Processing ## Processing
Aliases files are read upon start-up and refreshed every 30 seconds, so Aliases files are read upon start-up and refreshed every 30 seconds, so changes
changes to them don't require a daemon restart. to them don't require a daemon restart.
The resolver will perform lookups recursively, until it finds all the final The resolver will perform lookups recursively, until it finds all the final
recipients. There are recursion limits to avoid alias loops. If the limit (10 recipients. There are recursion limits to avoid alias loops. If the limit (10
levels) is reached, the entire resolution will fail. levels) is reached, the entire resolution will fail.
Commands are given 30s to run, after which it will be killed and the execution Commands are given 30s to run, after which it will be killed and the execution
will fail. If the command exits with an error (non-0 exit code), the delivery will fail. If the command exits with an error (non-0 exit code), the delivery
will be considered failed. will be considered failed.
The `chasquid-util` command-line tool can be used to check and resolve The `chasquid-util` command-line tool can be used to check and resolve aliases
aliases manually. It talks to the running server, so the response is fully manually. It talks to the running server, so the response is fully
authoritative. authoritative.
## Hooks ## Hooks
There is a hook that allows more sophisticated aliases resolution: There is a hook that allows more sophisticated aliases resolution:
@@ -191,6 +185,5 @@ are merged with the file-based resolution results.
See the [hooks](hooks.md) documentation for more details. See the [hooks](hooks.md) documentation for more details.
[chasquid]: https://blitiri.com.ar/p/chasquid [chasquid]: https://blitiri.com.ar/p/chasquid
[email aliases]: https://en.wikipedia.org/wiki/Email_alias [email aliases]: https://en.wikipedia.org/wiki/Email_alias
+4 -10
View File
@@ -1,18 +1,15 @@
# Clients # Clients
chasquid supports most SMTP clients, but requires them to have some features: chasquid supports most SMTP clients, but requires them to have some features:
- Support TLS (either - Support TLS (either [STARTTLS](https://datatracker.ietf.org/doc/html/rfc3207)
[STARTTLS](https://datatracker.ietf.org/doc/html/rfc3207) or or [implicit TLS](https://datatracker.ietf.org/doc/html/rfc8314#section-3.3))
[implicit TLS](https://datatracker.ietf.org/doc/html/rfc8314#section-3.3))
- Support the - Support the
[PLAIN authentication method](https://datatracker.ietf.org/doc/html/rfc4954#section-4). [PLAIN authentication method](https://datatracker.ietf.org/doc/html/rfc4954#section-4).
All modern clients should support both, and thus have no problems talking to All modern clients should support both, and thus have no problems talking to
chasquid. chasquid.
## Configuration examples ## Configuration examples
### [msmtp](https://marlam.de/msmtp/) ### [msmtp](https://marlam.de/msmtp/)
@@ -42,13 +39,10 @@ password SECRET
Replace the `SERVER`, `USER@DOMAIN` and `SECRET` strings with the appropriate Replace the `SERVER`, `USER@DOMAIN` and `SECRET` strings with the appropriate
values. values.
## Problematic clients ## Problematic clients
These clients are known to have issues talking to chasquid: These clients are known to have issues talking to chasquid:
- [ssmtp](https://packages.debian.org/source/unstable/ssmtp): does not - [ssmtp](https://packages.debian.org/source/unstable/ssmtp): does not support
support the PLAIN authentication method. It is also unmaintained. the PLAIN authentication method. It is also unmaintained.\
Please use [msmtp](https://marlam.de/msmtp/) instead. Please use [msmtp](https://marlam.de/msmtp/) instead.
+14 -20
View File
@@ -1,19 +1,17 @@
# Contributing # Contributing
## Questions and bug reports ## Questions and bug reports
Please send questions and bug reports via [Github Issues], or to the [mailing Please send questions and bug reports via [Github Issues], or to the
list], chasquid@googlegroups.com. [mailing list], chasquid@googlegroups.com.\
To subscribe to the [mailing list], send an email to To subscribe to the [mailing list], send an email to
`chasquid+subscribe@googlegroups.com`. `chasquid+subscribe@googlegroups.com`.
To privately report a suspected security issue, please see [Reporting a To privately report a suspected security issue, please see
security issue](security.md). [Reporting a security issue](security.md).
<a name="irc"></a>
You can also reach out via IRC, `#chasquid` on [OFTC](https://oftc.net/).
<a name="irc"></a> You can also reach out via IRC, `#chasquid` on
[OFTC](https://oftc.net/).
## Patches and pull requests ## Patches and pull requests
@@ -24,12 +22,11 @@ Before sending any non-trivial change, it's ideal to discuss the proposal (via
[Github Issues], [mailing list], or [IRC](#irc)). This helps make the most out [Github Issues], [mailing list], or [IRC](#irc)). This helps make the most out
of the contribution, and minimize friction frustration during code reviews. of the contribution, and minimize friction frustration during code reviews.
### Commit message, coding style, tests ### Commit message, coding style, tests
Ideally, patches would have descriptive commit messages, adhere to Go's coding Ideally, patches would have descriptive commit messages, adhere to Go's coding
style, and include comprehensive tests. However, that is a lot to ask, and style, and include comprehensive tests. However, that is a lot to ask, and very
very subjective. subjective.
It is okay to propose patches without those things. In those cases, the It is okay to propose patches without those things. In those cases, the
maintainer will usually amend the patches to add them. maintainer will usually amend the patches to add them.
@@ -39,22 +36,19 @@ For how to write commit messages,
[this](https://git-scm.com/docs/SubmittingPatches#describe-changes) articles [this](https://git-scm.com/docs/SubmittingPatches#describe-changes) articles
contain great advise. contain great advise.
### Workflow ### Workflow
Patches will be cherry-picked, and are typically first incorporated into the Patches will be cherry-picked, and are typically first incorporated into the
`next` branch. `next` branch.
The `next` branch is where patches are staged, tested and reviewed. This The `next` branch is where patches are staged, tested and reviewed. This branch
branch is rebased frequently, to make adjustments and fixes as needed. is rebased frequently, to make adjustments and fixes as needed. Once patches
Once patches have received enough testing (usually after a couple of weeks), have received enough testing (usually after a couple of weeks), they are moved
they are moved to the `main` branch. to the `main` branch.
The `main` branch is the stable branch and where releases are cut from. It is The `main` branch is the stable branch and where releases are cut from. It is
never rebased. never rebased.
[github issues]: https://github.com/albertito/chasquid/issues
[Github Issues]: https://github.com/albertito/chasquid/issues [github pull requests]: https://github.com/albertito/chasquid/pulls
[mailing list]: https://groups.google.com/forum/#!forum/chasquid [mailing list]: https://groups.google.com/forum/#!forum/chasquid
[GitHub's Security tab]: https://github.com/albertito/chasquid/security
[Github Pull requests]: https://github.com/albertito/chasquid/pulls
+21 -29
View File
@@ -1,4 +1,3 @@
# DKIM integration # DKIM integration
[chasquid] supports verifying and generating [DKIM] signatures since version [chasquid] supports verifying and generating [DKIM] signatures since version
@@ -9,25 +8,22 @@ have a private DKIM key set up will be signed.
In versions older than 1.13, support is possible via the [hooks] mechanism. In In versions older than 1.13, support is possible via the [hooks] mechanism. In
particular, the [example hook] included support for some command-line particular, the [example hook] included support for some command-line
implementations. That continues to be an option, especially if customization implementations. That continues to be an option, especially if customization is
is needed. needed.
## Easy setup ## Easy setup
- Run `chasquid-util dkim-keygen DOMAIN` to generate a DKIM private key for - Run `chasquid-util dkim-keygen DOMAIN` to generate a DKIM private key for
your domain. The file will be in `/etc/chasquid/domains/DOMAIN/dkim:*.pem`. your domain. The file will be in `/etc/chasquid/domains/DOMAIN/dkim:*.pem`.
- Publish the DKIM DNS record which was shown by the - Publish the DKIM DNS record which was shown by the previous command (e.g. by
previous command (e.g. by following following [this guide](https://support.dnsimple.com/articles/dkim-record/)).
[this guide](https://support.dnsimple.com/articles/dkim-record/)).
- Change the key file's permissions, to ensure it is readable by chasquid (and - Change the key file's permissions, to ensure it is readable by chasquid (and
nobody else). nobody else).
- Restart chasquid. - Restart chasquid.
It is highly recommended that you use a DKIM checker (like It is highly recommended that you use a DKIM checker (like
[Learn DMARC](https://www.learndmarc.com/)) to confirm that your setup is [Learn DMARC](https://www.learndmarc.com/)) to confirm that your setup is fully
fully functional. functional.
## Advanced setup ## Advanced setup
@@ -38,16 +34,15 @@ It needs to be either RSA or Ed25519.
### Key rotation ### Key rotation
To rotate a key, you can remove the old key file, and generate a new one as To rotate a key, you can remove the old key file, and generate a new one as per
per the previous step. the previous step.
It is important to remove the old key from the directory, because chasquid It is important to remove the old key from the directory, because chasquid will
will use *all* the keys in it. use *all* the keys in it.
You should use a different selector each time. If you don't specify a
selector when using `chasquid-util dkim-keygen`, the current date will be
used, which is a safe default to prevent accidental reuse.
You should use a different selector each time. If you don't specify a selector
when using `chasquid-util dkim-keygen`, the current date will be used, which is
a safe default to prevent accidental reuse.
### Multiple keys ### Multiple keys
@@ -57,18 +52,16 @@ support multiple signing algorithms).
This is well supported: chasquid will sign email with all keys it find that This is well supported: chasquid will sign email with all keys it find that
match `dkim:*.pem` in a domain directory. match `dkim:*.pem` in a domain directory.
## Verification ## Verification
[chasquid] will verify all DKIM signatures of incoming mail, and record the [chasquid] will verify all DKIM signatures of incoming mail, and record the
results in an [`Authentication-Results:`] header, as per [RFC 8601]. results in an [`Authentication-Results:`] header, as per [RFC 8601].
Note that emails will *not* be rejected even if they fail verification, as Note that emails will *not* be rejected even if they fail verification, as this
this is not recommended is not recommended
([source 1](https://tools.ietf.org/html/rfc6376#section-6.3), ([source 1](https://tools.ietf.org/html/rfc6376#section-6.3),
[source 2](https://tools.ietf.org/html/rfc7601#section-2.7.1)). [source 2](https://tools.ietf.org/html/rfc7601#section-2.7.1)).
## Other implementations ## Other implementations
[chasquid] also supports [DKIM] via the [hooks] mechanism. This can be useful [chasquid] also supports [DKIM] via the [hooks] mechanism. This can be useful
@@ -79,12 +72,11 @@ Implementations that have been tried:
- [driusan/dkim] - [driusan/dkim]
- [dkimpy] - [dkimpy]
[chasquid]: https://blitiri.com.ar/p/chasquid [chasquid]: https://blitiri.com.ar/p/chasquid
[DKIM]: https://en.wikipedia.org/wiki/DomainKeys_Identified_Mail [dkim]: https://en.wikipedia.org/wiki/DomainKeys_Identified_Mail
[hooks]: hooks.md
[example hook]: https://blitiri.com.ar/git/r/chasquid/b/next/t/etc/chasquid/hooks/f=post-data.html
[driusan/dkim]: https://github.com/driusan/dkim
[dkimpy]: https://launchpad.net/dkimpy/ [dkimpy]: https://launchpad.net/dkimpy/
[RFC 8601]: https://datatracker.ietf.org/doc/html/rfc8601 [driusan/dkim]: https://github.com/driusan/dkim
[`Authentication-Results:`]: https://en.wikipedia.org/wiki/Email_authentication#Authentication-Results [example hook]: https://blitiri.com.ar/git/r/chasquid/b/next/t/etc/chasquid/hooks/f=post-data.html
[hooks]: hooks.md
[rfc 8601]: https://datatracker.ietf.org/doc/html/rfc8601
[`authentication-results:`]: https://en.wikipedia.org/wiki/Email_authentication#Authentication-Results
+3 -8
View File
@@ -1,4 +1,3 @@
# Dovecot integration # Dovecot integration
As of version 0.04 (2018-02), [chasquid] has integration with [dovecot] for As of version 0.04 (2018-02), [chasquid] has integration with [dovecot] for
@@ -7,7 +6,6 @@ authenticating users.
This means that chasquid can ask dovecot to authenticate users, instead/in This means that chasquid can ask dovecot to authenticate users, instead/in
addition to having its own per-domain user databases. addition to having its own per-domain user databases.
## Configuring dovecot ## Configuring dovecot
The following needs to be added to the Dovecot configuration, usually in The following needs to be added to the Dovecot configuration, usually in
@@ -35,7 +33,6 @@ Authentication requests sent by chasquid to dovecot will pass on the username
as specified by the client. This will usually be either `user@domain`, or just as specified by the client. This will usually be either `user@domain`, or just
`user`. `user`.
## Configuring chasquid ## Configuring chasquid
Add the following line to `/etc/chasquid/chasquid.conf`: Add the following line to `/etc/chasquid/chasquid.conf`:
@@ -51,14 +48,13 @@ CentOS, and NixOS).
If chasquid can't find them, the paths can be set with the If chasquid can't find them, the paths can be set with the
`dovecot_userdb_path` and `dovecot_client_path` options. `dovecot_userdb_path` and `dovecot_client_path` options.
## Troubleshooting ## Troubleshooting
Dovecot authentication can be tricky to troubleshoot. Dovecot authentication can be tricky to troubleshoot.
If you think it is not working as it should, or chasquid isn't correctly If you think it is not working as it should, or chasquid isn't correctly
talking with it, the easiest way to check is to [increase dovecot auth logging talking with it, the easiest way to check is to
verbosity](https://doc.dovecot.org/admin_manual/logging/?highlight=logging#logging-verbosity): [increase dovecot auth logging verbosity](https://doc.dovecot.org/admin_manual/logging/?highlight=logging#logging-verbosity):
``` ```
auth_verbose = yes auth_verbose = yes
@@ -69,6 +65,5 @@ One common gotcha is when dovecot is set up to use `user` instead of
`user@domain`. In that case you can try setting `auth_username_format = %n` to `user@domain`. In that case you can try setting `auth_username_format = %n` to
make it ignore the domain if present. make it ignore the domain if present.
[dovecot]: https://dovecot.org
[chasquid]: https://blitiri.com.ar/p/chasquid [chasquid]: https://blitiri.com.ar/p/chasquid
[dovecot]: https://dovecot.org
+22 -27
View File
@@ -1,34 +1,31 @@
# Message flows # Message flows
This document explains at a high level some parts of chasquid's message This document explains at a high level some parts of chasquid's message
processing, in particular how messages flow through the system. processing, in particular how messages flow through the system.
## Message reception ## Message reception
- Client connects to chasquid on the smtp or submission ports, and issues - Client connects to chasquid on the smtp or submission ports, and issues
HELO/EHLO. HELO/EHLO.
- Client optionally performs STARTTLS. - Client optionally performs STARTTLS.
- Client optionally performs AUTH. - Client optionally performs AUTH, which must be done over TLS.
- Check that this is done over TLS. - Client sends MAIL FROM, and we check SPF and the connection security level.
- Client sends MAIL FROM. - Client sends one or more RCPT TO. If the destination is remote, then the user
- Check SPF. must have authenticated. If the destination is local, check that the user
- Check connection security level. exists.
- Client sends one or more RCPT TO.
- If the destination is remote, then the user must have authenticated.
- If the destination is local, check that the user exists.
- Client sends DATA. - Client sends DATA.
- Client sends actual data, and ends it with '.' - Client sends actual data, and ends it with '.'
- Parse the data contents to perform loop detection.
- If the sender is authenticated, DKIM-sign the email with the
corresponding key.
- If the sender is not authenticated, verify the DKIM signature (if the
email has one).
- Add the required headers (Received, SPF results, post-data hook output).
- Run the post-data hook. If the hook fails, return an error.
- Put it in the queue and reply success.
Then, to process the data:
- Parse the data contents to perform loop detection.
- If the sender is authenticated, DKIM-sign the email with the corresponding
key.
- If the sender is not authenticated, verify the DKIM signature (if the email
has one).
- Add the required headers (Received, SPF results, post-data hook output).
- Run the post-data hook. If the hook fails, return an error.
- Put it in the queue and reply success.
### Authenticated mail, and email spoofing ### Authenticated mail, and email spoofing
@@ -41,9 +38,9 @@ Users who want to be strict about "MAIL FROM" or even "From:" validation can
add additional checks in the [post-DATA hook](hooks.md). add additional checks in the [post-DATA hook](hooks.md).
In the future, chasquid may get some option to be strict about it by default, In the future, chasquid may get some option to be strict about it by default,
or on a per-domain or per-user basis. But for now, using a [post-DATA or on a per-domain or per-user basis. But for now, using a
hook](hooks.md) is the best way to make chasquid more strict about this. [post-DATA hook](hooks.md) is the best way to make chasquid more strict about
this.
## Queue processing ## Queue processing
@@ -57,11 +54,9 @@ Before accepting a message:
Queue processing runs asynchronously, there's a goroutine for each message Queue processing runs asynchronously, there's a goroutine for each message
which does, in a loop: which does, in a loop:
- For each recipient which we have not delivered yet: - For each recipient which we have not delivered yet, attempt delivery, and
- Attempt delivery. write the results to disk.
- Write to disk the results.
- If there are mails still pending, wait for some time (incrementally). - If there are mails still pending, wait for some time (incrementally).
- When all the recipients have completed delivery, or enough time has passed: - When all the recipients have completed delivery, or enough time has passed:
- If all were successful, remove from the queue. if all were successful, remove from the queue; if some failed, send a
- If some failed, send a delivery status notification back to the sender. delivery status notification back to the sender.
+1 -5
View File
@@ -1,10 +1,8 @@
# HAProxy integration # HAProxy integration
As of version 1.6, [chasquid] supports being deployed behind a [HAProxy] As of version 1.6, [chasquid] supports being deployed behind a [HAProxy]
instance. instance.
## Configuring HAProxy ## Configuring HAProxy
In the backend server line, set the [send-proxy] parameter to turn on the use In the backend server line, set the [send-proxy] parameter to turn on the use
@@ -14,7 +12,6 @@ You need to set this for each of the ports that are forwarded.
Only PROXY protocol v1 is supported for now. Only PROXY protocol v1 is supported for now.
## Configuring chasquid ## Configuring chasquid
Add the following line to `/etc/chasquid/chasquid.conf`: Add the following line to `/etc/chasquid/chasquid.conf`:
@@ -25,7 +22,6 @@ haproxy_incoming: true
That turns HAProxy support on for all incoming SMTP connections. That turns HAProxy support on for all incoming SMTP connections.
[chasquid]: https://blitiri.com.ar/p/chasquid [chasquid]: https://blitiri.com.ar/p/chasquid
[HAProxy]: https://www.haproxy.org/ [haproxy]: https://www.haproxy.org/
[send-proxy]: http://cbonte.github.io/haproxy-dconv/2.0/configuration.html#5.2-send-proxy [send-proxy]: http://cbonte.github.io/haproxy-dconv/2.0/configuration.html#5.2-send-proxy
+26 -32
View File
@@ -1,4 +1,3 @@
# Hooks # Hooks
chasquid supports some functionality via hooks, which are binaries that get chasquid supports some functionality via hooks, which are binaries that get
@@ -6,7 +5,6 @@ executed at specific points in time during delivery.
They are optional, and will be skipped if they don't exist. They are optional, and will be skipped if they don't exist.
## Post-DATA hook ## Post-DATA hook
After completion of DATA, but before accepting the mail for queueing, chasquid After completion of DATA, but before accepting the mail for queueing, chasquid
@@ -15,19 +13,16 @@ will run the command at `$config_dir/hooks/post-data`.
The contents of the mail will be written to the command's stdin, and the The contents of the mail will be written to the command's stdin, and the
environment is detailed below. environment is detailed below.
If the exit status is 0, chasquid will move forward processing the command, If the exit status is 0, chasquid will move forward processing the command, and
and its stdout should contain headers which will be added to contents of its stdout should contain headers which will be added to contents of the email
the email (at the top). (at the top).
Otherwise, chasquid will respond with an error, and the last line of stdout Otherwise, chasquid will respond with an error, and the last line of stdout
will be passed back to the client as the error message. will be passed back to the client as the error message. If the exit status is
If the exit status is 20 the error code will be permanent, otherwise it will 20 the error code will be permanent, otherwise it will be temporary.
be temporary.
This hook can be used to block based on contents, for example to check for
spam or virus. See `etc/hooks/post-data` for an example.
This hook can be used to block based on contents, for example to check for spam
or virus. See `etc/hooks/post-data` for an example.
### Environment ### Environment
@@ -36,27 +31,26 @@ privileges.
The environment will contain the following variables: The environment will contain the following variables:
- `$USER`: The server's `$USER` env variable. - `$USER`: The server's `$USER` env variable.
- `$SHELL`: The server's `$SHELL` env variable. - `$SHELL`: The server's `$SHELL` env variable.
- `$PATH`: The server's `$PATH` env variable. - `$PATH`: The server's `$PATH` env variable.
- `$PWD`: The working directory, which will be the config directory. - `$PWD`: The working directory, which will be the config directory.
- `$REMOTE_ADDR`: IP address of the remote side of the connection. - `$REMOTE_ADDR`: IP address of the remote side of the connection.
- `$EHLO_DOMAIN`: EHLO/HELO domain, as given by the client; sanitized for - `$EHLO_DOMAIN`: EHLO/HELO domain, as given by the client; sanitized for
safety (only letters, digits, and `-.[]:` are kept). If there are no valid safety (only letters, digits, and `-.[]:` are kept). If there are no valid
characters, it is `no-valid-characters.invalid`. characters, it is `no-valid-characters.invalid`.
- `$EHLO_DOMAIN_RAW`: Same as `$EHLO_DOMAIN`. Kept for backwards - `$EHLO_DOMAIN_RAW`: Same as `$EHLO_DOMAIN`. Kept for backwards compatibility;
compatibility; it used to be the unsanitized value. it used to be the unsanitized value.
- `$MAIL_FROM`: MAIL FROM address. - `$MAIL_FROM`: MAIL FROM address.
- `$RCPT_TO`: RCPT TO addresses, space separated. - `$RCPT_TO`: RCPT TO addresses, space separated.
- `$AUTH_AS`: Authenticated user; empty if the connection has not - `$AUTH_AS`: Authenticated user; empty if the connection has not authenticated
authenticated successfully. successfully.
- `$ON_TLS`: 1 if using TLS, 0 if not. - `$ON_TLS`: 1 if using TLS, 0 if not.
- `$FROM_LOCAL_DOMAIN`: 1 if the mail comes from a local domain, 0 if not. - `$FROM_LOCAL_DOMAIN`: 1 if the mail comes from a local domain, 0 if not.
- `$SPF_PASS`: 1 if it passed SPF, 0 if not. - `$SPF_PASS`: 1 if it passed SPF, 0 if not.
There is a 1 minute timeout for hook execution.
It will be run at the config directory.
There is a 1 minute timeout for hook execution. It will be run at the config
directory.
## Alias resolve hook ## Alias resolve hook
+50 -65
View File
@@ -1,4 +1,3 @@
# chasquid how-to guide # chasquid how-to guide
This is a practical guide for setting up an email server for personal or small This is a practical guide for setting up an email server for personal or small
@@ -7,34 +6,22 @@ detailed references where possible.
While a lot of the contents are generic, for simplicity it will use: While a lot of the contents are generic, for simplicity it will use:
- [Debian] as base operating system ([Ubuntu] also works) - [Debian] as base operating system ([Ubuntu] also works)
- [Dovecot] for [POP3]+[IMAP] - [Dovecot] for [POP3]+[IMAP]
- [chasquid] for [SMTP] - [chasquid] for [SMTP]
- [Let's Encrypt] for [TLS] certificates - [Let's Encrypt] for [TLS] certificates
[Debian]: https://debian.org
[Ubuntu]: https://ubuntu.com
[Dovecot]: https://dovecot.org
[chasquid]: https://blitiri.com.ar/p/chasquid
[Let's Encrypt]: https://letsencrypt.org
[POP3]: https://en.wikipedia.org/wiki/Post_Office_Protocol
[IMAP]: https://en.wikipedia.org/wiki/Internet_Message_Access_Protocol
[SMTP]: https://en.wikipedia.org/wiki/Simple_Mail_Transfer_Protocol
[TLS]: https://en.wikipedia.org/wiki/Transport_Layer_Security
## Example data ## Example data
This guide will use the following data for illustration purposes, replace them This guide will use the following data for illustration purposes, replace them
with your own where appropriate. with your own where appropriate.
- Domain name: `example.com`. - Domain name: `example.com`.
- IPv4 address of your mail server: `198.51.100.7`. - IPv4 address of your mail server: `198.51.100.7`.
- IPv6 address of your mail server: `2001:db8::7`. - IPv6 address of your mail server: `2001:db8::7`.
Note IPv6 is optional but highly encouraged, and supported by most providers. Note IPv6 is optional but highly encouraged, and supported by most providers.
## Getting a server ## Getting a server
You first need to have a server to use. This could be an existing one (for You first need to have a server to use. This could be an existing one (for
@@ -43,33 +30,26 @@ exclusive for email.
In this guide we will use a separate server, mostly for clarity. In this guide we will use a separate server, mostly for clarity.
For small groups the size of the server does not matter, any small VPS For small groups the size of the server does not matter, any small VPS (virtual
(virtual private server) will do just fine. private server) will do just fine.
Specifically for hosting email servers, there are some things to check when Specifically for hosting email servers, there are some things to check when
selecting a provider: selecting a provider:
- Make sure they allow traffic on TCP port 25 (SMTP). While almost all VPS - Make sure they allow traffic on TCP port 25 (SMTP). While almost all VPS and
and dedicated server providers are fine, some "cloud" providers (like dedicated server providers are fine, some "cloud" providers (like Google
Google Cloud) block port 25, which is used for sending and receiving mails. Cloud) block port 25, which is used for sending and receiving mails.
- Once you get a server, make sure the IP addresses are not listed in any - Once you get a server, make sure the IP addresses are not listed in any
[blackhole lists]. [blackhole lists]. There are many services to check them, for example
There are many services to check them, for example [the [the Anti-Abuse project] or [multirbl.valli.org].
Anti-Abuse project] or [multirbl.valli.org].
Remember to update your server regularly, setting up [unattended upgrades] is Remember to update your server regularly, setting up [unattended upgrades] is
highly recommended. highly recommended.
[the Anti-Abuse project]: http://www.anti-abuse.org/multi-rbl-check/
[blackhole lists]: https://en.wikipedia.org/wiki/DNSBL
[unattended upgrades]: https://wiki.debian.org/UnattendedUpgrades
[multirbl.valli.org]: http://multirbl.valli.org/
## DNS ## DNS
Set up the following DNS records for `example.com`. This is usually done Set up the following DNS records for `example.com`. This is usually done either
either in your DNS server, or in the user interface of your DNS provider. in your DNS server, or in the user interface of your DNS provider.
``` ```
; Assign "mail.example.com" to the server's IP addresses. ; Assign "mail.example.com" to the server's IP addresses.
@@ -86,20 +66,18 @@ mail AAAA 2001:db8::7
``` ```
Finally, you should go to your server provider and configure the "reverse DNS" Finally, you should go to your server provider and configure the "reverse DNS"
(also known as "PTR") for the IP addresses to be to "mail.example.com". This (also known as "PTR") for the IP addresses to be to "mail.example.com". This is
is important, as some spam checkers will consider it a factor. important, as some spam checkers will consider it a factor.
*References: *References: [A record](https://en.wikipedia.org/wiki/A_record),
[A record](https://en.wikipedia.org/wiki/A_record),
[MX record](https://en.wikipedia.org/wiki/MX_record), [MX record](https://en.wikipedia.org/wiki/MX_record),
[Sender Policy Framework (SPF)](https://en.wikipedia.org/wiki/Sender_Policy_Framework).* [Sender Policy Framework (SPF)](https://en.wikipedia.org/wiki/Sender_Policy_Framework).*
## TLS certificate ## TLS certificate
[TLS] certificates are needed to send and receive email securely. [TLS] certificates are needed to send and receive email securely. [letsencrypt]
[letsencrypt] will provide us with a free certificate, which needs to be will provide us with a free certificate, which needs to be renewed every 90
renewed every 90 days, so the following relies on automatic renewal. days, so the following relies on automatic renewal.
Note `certbot` is the recommended letsencrypt command line client. Note `certbot` is the recommended letsencrypt command line client.
@@ -124,10 +102,6 @@ EOF
sudo chmod +x /etc/letsencrypt/renewal-hooks/post/restart sudo chmod +x /etc/letsencrypt/renewal-hooks/post/restart
``` ```
[TLS]: https://en.wikipedia.org/wiki/Transport_Layer_Security
[letsencrypt]: https://letsencrypt.org
## Configure dovecot ## Configure dovecot
First, install dovecot, and let chasquid use it for authorizing users. That First, install dovecot, and let chasquid use it for authorizing users. That
@@ -151,12 +125,11 @@ service auth {
EOF EOF
``` ```
You will need to configure dovecot authentication depending on your needs. You will need to configure dovecot authentication depending on your needs. For
For example, if you want to use only system users, or virtual users. example, if you want to use only system users, or virtual users. See the
See the `/etc/dovecot/conf.d/10-auth.conf` file, and the [dovecot `/etc/dovecot/conf.d/10-auth.conf` file, and the
documentation](https://wiki.dovecot.org/HowTo/SimpleVirtualInstall) for more [dovecot documentation](https://wiki.dovecot.org/HowTo/SimpleVirtualInstall)
details. for more details.
## Configure chasquid ## Configure chasquid
@@ -191,13 +164,12 @@ EOF
## Add users ## Add users
With this configuration, chasquid will use dovecot to manage users, so refer With this configuration, chasquid will use dovecot to manage users, so refer to
to the [dovecot documentation](https://wiki.dovecot.org/BasicConfiguration) the [dovecot documentation](https://wiki.dovecot.org/BasicConfiguration) for
for the details. the details.
You can also add chasquid-specific users with `chasquid-util user-add`. You can also add chasquid-specific users with `chasquid-util user-add`.
## Additional domains ## Additional domains
To make chasquid manage an additional domain `otherdomain.com`, first add the To make chasquid manage an additional domain `otherdomain.com`, first add the
@@ -208,13 +180,13 @@ following records to `otherdomain.com`:
@ TXT "v=spf1 mx -all" @ TXT "v=spf1 mx -all"
``` ```
Then, tell chasquid about it by running `mkdir Then, tell chasquid about it by running
/etc/chasquid/domains/otherdomain.com`. Don't forget to restart it afterwards. `mkdir /etc/chasquid/domains/otherdomain.com`. Don't forget to restart it
afterwards.
Alternatively, you can use a different MX record, as long as you can get Alternatively, you can use a different MX record, as long as you can get
chasquid a certificate for it. chasquid a certificate for it.
## Optional software ## Optional software
- To use [SpamAssassin] to filter spam, run `apt install spamassassin spamc`. - To use [SpamAssassin] to filter spam, run `apt install spamassassin spamc`.
@@ -223,6 +195,19 @@ chasquid a certificate for it.
That's all it takes. chasquid default hooks will pass incoming mail through That's all it takes. chasquid default hooks will pass incoming mail through
both if (and only if) they are installed. both if (and only if) they are installed.
[SpamAssassin]: https://spamassassin.apache.org/ [blackhole lists]: https://en.wikipedia.org/wiki/DNSBL
[ClamAV]: https://www.clamav.net/ [chasquid]: https://blitiri.com.ar/p/chasquid
[clamav]: https://www.clamav.net/
[debian]: https://debian.org
[dovecot]: https://dovecot.org
[imap]: https://en.wikipedia.org/wiki/Internet_Message_Access_Protocol
[let's encrypt]: https://letsencrypt.org
[letsencrypt]: https://letsencrypt.org
[multirbl.valli.org]: http://multirbl.valli.org/
[pop3]: https://en.wikipedia.org/wiki/Post_Office_Protocol
[smtp]: https://en.wikipedia.org/wiki/Simple_Mail_Transfer_Protocol
[spamassassin]: https://spamassassin.apache.org/
[the anti-abuse project]: http://www.anti-abuse.org/multi-rbl-check/
[tls]: https://en.wikipedia.org/wiki/Transport_Layer_Security
[ubuntu]: https://ubuntu.com
[unattended upgrades]: https://wiki.debian.org/UnattendedUpgrades
+3 -8
View File
@@ -1,4 +1,3 @@
# chasquid # chasquid
[chasquid](https://blitiri.com.ar/p/chasquid) is an SMTP (email) server with a [chasquid](https://blitiri.com.ar/p/chasquid) is an SMTP (email) server with a
@@ -9,16 +8,12 @@ This is the documentation index.
Please see the [project page](https://blitiri.com.ar/p/chasquid) for more Please see the [project page](https://blitiri.com.ar/p/chasquid) for more
details. details.
## Contact ## Contact
If you have any questions, comments or patches please send them to the [mailing If you have any questions, comments or patches please send them to the
list](https://groups.google.com/forum/#!forum/chasquid), [mailing list](https://groups.google.com/forum/#!forum/chasquid),
chasquid@googlegroups.com. chasquid@googlegroups.com.
To subscribe, send an email to chasquid+subscribe@googlegroups.com. To subscribe, send an email to chasquid+subscribe@googlegroups.com.
You can also reach out via IRC, `#chasquid` on You can also reach out via IRC, `#chasquid` on [OFTC](https://oftc.net/).
[OFTC](https://oftc.net/).
+21 -33
View File
@@ -1,4 +1,3 @@
# Installing and configuring [chasquid](https://blitiri.com.ar/p/chasquid) # Installing and configuring [chasquid](https://blitiri.com.ar/p/chasquid)
## Installation ## Installation
@@ -17,9 +16,9 @@ sudo apt install chasquid
If you're using Arch, there is a If you're using Arch, there is a
[chasquid AUR package](https://aur.archlinux.org/packages/chasquid/) you can [chasquid AUR package](https://aur.archlinux.org/packages/chasquid/) you can
use. See the [official Arch use. See the
documentation](https://wiki.archlinux.org/index.php/Arch_User_Repository) for [official Arch documentation](https://wiki.archlinux.org/index.php/Arch_User_Repository)
how to install it. If you use the [pacaur](https://github.com/E5ten/pacaur) for how to install it. If you use the [pacaur](https://github.com/E5ten/pacaur)
[helper](https://wiki.archlinux.org/index.php/AUR_helpers), you can just run: [helper](https://wiki.archlinux.org/index.php/AUR_helpers), you can just run:
```shell ```shell
@@ -29,7 +28,6 @@ pacaur -S chasquid
[Binary packages](https://maddy.email/archlinux/README.txt) are also available, [Binary packages](https://maddy.email/archlinux/README.txt) are also available,
courtesy of [foxcpp](https://github.com/foxcpp/). courtesy of [foxcpp](https://github.com/foxcpp/).
### Alpine ### Alpine
If you're using If you're using
@@ -43,7 +41,6 @@ apk add chasquid
Thanks to [raspbeguy](https://github.com/raspbeguy) for maintaining the Alpine Thanks to [raspbeguy](https://github.com/raspbeguy) for maintaining the Alpine
package. package.
### From source ### From source
To get, build and install from source, you will need a working To get, build and install from source, you will need a working
@@ -63,7 +60,6 @@ sudo make install-binaries
sudo make install-config-skeleton sudo make install-config-skeleton
``` ```
## Configuration ## Configuration
The configuration is in `/etc/chasquid/` by default, and has the following The configuration is in `/etc/chasquid/` by default, and has the following
@@ -88,28 +84,24 @@ structure:
### Certificates ### Certificates
The certs/ directory layout matches the one from The certs/ directory layout matches the one from
[certbot](https://certbot.eff.org/), [certbot](https://certbot.eff.org/), [letsencrypt](https://letsencrypt.org)'s
[letsencrypt](https://letsencrypt.org)'s default client, to make it easier to integrate. The layout from the
default client, to make it easier to integrate. [NixOS ACME module](https://wiki.nixos.org/wiki/ACME) (`/var/lib/acme`) is also
The layout from the [NixOS ACME module](https://wiki.nixos.org/wiki/ACME) supported.
(`/var/lib/acme`) is also supported.
A convenient way to set this up is: A convenient way to set this up is:
1) Obtain TLS certificates using `certbot` as needed. 1. Obtain TLS certificates using `certbot` as needed.
2) Symlink chasquid's `certs/` to `/etc/letsencrypt/live`:\ 2. Symlink chasquid's `certs/` to `/etc/letsencrypt/live`:\
`sudo ln -s /etc/letsencrypt/live/ /etc/chasquid/certs` `sudo ln -s /etc/letsencrypt/live/ /etc/chasquid/certs`
3) Give chasquid permissions to read the certificates:\ 3. Give chasquid permissions to read the certificates:\
`sudo setfacl -R -m u:chasquid:rX /etc/letsencrypt/{live,archive}` `sudo setfacl -R -m u:chasquid:rX /etc/letsencrypt/{live,archive}`
4) Set up [automatic renewal] to restart chasquid when certificates are 4. Set up [automatic renewal] to restart chasquid when certificates are
renewed. renewed.
Please see the [how-to guide](howto.md#tls-certificate) for more detailed Please see the [how-to guide](howto.md#tls-certificate) for more detailed
examples. examples.
[automatic renewal]: https://eff-certbot.readthedocs.io/en/stable/using.html#setting-up-automated-renewal
### Adding users ### Adding users
You can add users with: You can add users with:
@@ -120,24 +112,21 @@ chasquid-util user-add user@domain
This will also create the corresponding domain directory if it doesn't exist. This will also create the corresponding domain directory if it doesn't exist.
### Checking your configuration ### Checking your configuration
Run `chasquid-util print-config` to parse your configuration and display the Run `chasquid-util print-config` to parse your configuration and display the
resulting values. resulting values.
### Checking your setup ### Checking your setup
Run `smtp-check yourdomain.com`, it will check: Run `smtp-check yourdomain.com`, it will check:
* MX DNS records. - MX DNS records.
* SPF DNS records (will just warn if not present). - SPF DNS records (will just warn if not present).
* TLS certificates. - TLS certificates.
It needs to access port 25, which is often blocked by ISPs, so it's likely
that you need to run it from your server.
It needs to access port 25, which is often blocked by ISPs, so it's likely that
you need to run it from your server.
### Greylisting, anti-spam and anti-virus ### Greylisting, anti-spam and anti-virus
@@ -146,12 +135,11 @@ greylisting, and run anti-spam and anti-virus filters.
The hook should be at `/etc/chasquid/hooks/post-data`. The hook should be at `/etc/chasquid/hooks/post-data`.
The one installed by default is a bash script supporting: The one installed by default is a bash script supporting:
* greylisting using greylistd. - greylisting using greylistd.
* anti-spam using spamassassin or rspamd. - anti-spam using spamassassin or rspamd.
* anti-virus using clamav. - anti-virus using clamav.
To use them, they just need to be available in your system. To use them, they just need to be available in your system.
@@ -163,6 +151,6 @@ usermod -a -G greylist mail
``` ```
Note that the default hook may not work in all cases, it is provided as a Note that the default hook may not work in all cases, it is provided as a
practical example but you should adjust it to your particular system if practical example but you should adjust it to your particular system if needed.
needed.
[automatic renewal]: https://eff-certbot.readthedocs.io/en/stable/using.html#setting-up-automated-renewal
+2 -5
View File
@@ -1,14 +1,12 @@
# Known issues # Known issues
This file contains a list of the most common known issues, and the release This file contains a list of the most common known issues, and the release
range affected. It can be useful for people running older versions, to range affected. It can be useful for people running older versions, to identify
identify problems (and workarounds) faster. problems (and workarounds) faster.
Entries are eventually be purged once their affected versions become uncommon, Entries are eventually be purged once their affected versions become uncommon,
to prevent confusion. to prevent confusion.
## Dovecot auth occasionally not functional after a reboot (0.04 to 1.6) ## Dovecot auth occasionally not functional after a reboot (0.04 to 1.6)
After a reboot, if chasquid starts *before* dovecot, it's possible that After a reboot, if chasquid starts *before* dovecot, it's possible that
@@ -30,7 +28,6 @@ After=dovecot.service
The issue is fixed in 1.7. The issue is fixed in 1.7.
## `dkimsign` causes parsing errors in post-data hook (0.07 to 1.5) ## `dkimsign` causes parsing errors in post-data hook (0.07 to 1.5)
The default post-data hook in versions 0.07 to 1.5 has a bug where if the The default post-data hook in versions 0.07 to 1.5 has a bug where if the
+3 -5
View File
@@ -2,8 +2,8 @@
From the latest Debian package: From the latest Debian package:
- [chasquid(1)](https://manpages.debian.org/unstable/chasquid/chasquid.1): - [chasquid(1)](https://manpages.debian.org/unstable/chasquid/chasquid.1): the
the main binary. main binary.
- [chasquid.conf(5)](https://manpages.debian.org/unstable/chasquid/chasquid.conf.5): - [chasquid.conf(5)](https://manpages.debian.org/unstable/chasquid/chasquid.conf.5):
the configuration file and structure. the configuration file and structure.
- [chasquid-util(1)](https://manpages.debian.org/unstable/chasquid/chasquid-util.1): - [chasquid-util(1)](https://manpages.debian.org/unstable/chasquid/chasquid-util.1):
@@ -17,9 +17,7 @@ From the current branch (more likely to change, but useful when doing
development or running experimental versions): development or running experimental versions):
- [chasquid(1)](chasquid.1.md): the main binary. - [chasquid(1)](chasquid.1.md): the main binary.
- [chasquid.conf(5)](chasquid.conf.5.md): the configuration file and - [chasquid.conf(5)](chasquid.conf.5.md): the configuration file and structure.
structure.
- [chasquid-util(1)](chasquid-util.1.md): the command-line utility helper. - [chasquid-util(1)](chasquid-util.1.md): the command-line utility helper.
- [mda-lmtp(1)](mda-lmtp.1.md): helper to integrate with LMTP delivery. - [mda-lmtp(1)](mda-lmtp.1.md): helper to integrate with LMTP delivery.
- [smtp-check(1)](smtp-check.1.md): SMTP setup checker. - [smtp-check(1)](smtp-check.1.md): SMTP setup checker.
+45 -48
View File
@@ -1,13 +1,12 @@
# Monitoring # Monitoring
chasquid includes an HTTP server for monitoring purposes, which for security chasquid includes an HTTP server for monitoring purposes, which for security it
it is not enabled by default. is not enabled by default.
You can use the `monitoring_address` configuration option to enable it. You can use the `monitoring_address` configuration option to enable it.
Then just browse the address and human-friendly links to various monitoring Then just browse the address and human-friendly links to various monitoring and
and debugging tools should appear. debugging tools should appear.
These include: These include:
@@ -19,7 +18,6 @@ These include:
- [Exported variables](#variables) for whitebox monitoring. - [Exported variables](#variables) for whitebox monitoring.
- Profiling endpoints, for use with `go tool pprof` or similar tools. - Profiling endpoints, for use with `go tool pprof` or similar tools.
## Variables ## Variables
chasquid exports some variables for monitoring, via the standard chasquid exports some variables for monitoring, via the standard
@@ -30,8 +28,7 @@ whitebox monitoring.
They're accessible on the monitoring HTTP server, at `/debug/vars` (default They're accessible on the monitoring HTTP server, at `/debug/vars` (default
endpoint for expvars) and `/metrics` (common endpoint for openmetrics). endpoint for expvars) and `/metrics` (common endpoint for openmetrics).
<a name="prometheus"></a> <a name="prometheus"></a> The `/metrics` endpoint is also compatible with
The `/metrics` endpoint is also compatible with
[Prometheus](https://prometheus.io/). [Prometheus](https://prometheus.io/).
*Note these are still subject to change, although breaking changes will be *Note these are still subject to change, although breaking changes will be
@@ -40,86 +37,86 @@ avoided whenever possible, and will be noted in the
List of exported variables: List of exported variables:
- **chasquid/aliases/hookResults** (hook result -> counter) - **chasquid/aliases/hookResults** (hook result -> counter)\
count of aliases hook results, by hook and result. count of aliases hook results, by hook and result.
- **chasquid/queue/deliverAttempts** (recipient type -> counter) - **chasquid/queue/deliverAttempts** (recipient type -> counter)\
attempts to deliver mail, by recipient type (pipe/local email/remote email). attempts to deliver mail, by recipient type (pipe/local email/remote email).
- **chasquid/queue/dsnQueued** (counter) - **chasquid/queue/dsnQueued** (counter)\
count of DSNs that we generated (queued). count of DSNs that we generated (queued).
- **chasquid/queue/itemsWritten** (counter) - **chasquid/queue/itemsWritten** (counter)\
count of items the queue wrote to disk. count of items the queue wrote to disk.
- **chasquid/queue/putCount** (counter) - **chasquid/queue/putCount** (counter)\
number of envelopes put in the queue. number of envelopes put in the queue.
- **chasquid/smtpIn/acceptErrors** (counter) - **chasquid/smtpIn/acceptErrors** (counter)\
count of errors accepting incoming connections. count of errors accepting incoming connections.
- **chasquid/smtpIn/activeConnections** (gauge) - **chasquid/smtpIn/activeConnections** (gauge)\
number of active incoming connections. number of active incoming connections.
- **chasquid/smtpIn/commandCount** (map of command -> count) - **chasquid/smtpIn/commandCount** (map of command -> count)\
count of SMTP commands received, by command. Note that for unknown commands count of SMTP commands received, by command. Note that for unknown commands
we use `unknown<COMMAND>`. we use `unknown<COMMAND>`.
- **chasquid/smtpIn/connectionsOverLimit** (counter) - **chasquid/smtpIn/connectionsOverLimit** (counter)\
count of incoming connections closed due to the connection limit, which is count of incoming connections closed due to the connection limit, which is
half of the file descriptor limit. half of the file descriptor limit.
- **chasquid/smtpIn/dkimSignErrors** (counter) - **chasquid/smtpIn/dkimSignErrors** (counter)\
count of DKIM sign errors count of DKIM sign errors
- **chasquid/smtpIn/dkimSigned** (counter) - **chasquid/smtpIn/dkimSigned** (counter)\
count of successful DKIM signs count of successful DKIM signs
- **chasquid/smtpIn/dkimVerifyErrors** (counter) - **chasquid/smtpIn/dkimVerifyErrors** (counter)\
count of DKIM verification errors count of DKIM verification errors
- **chasquid/smtpIn/dkimVerifyFound** (counter) - **chasquid/smtpIn/dkimVerifyFound** (counter)\
count of messages with at least one DKIM signature count of messages with at least one DKIM signature
- **chasquid/smtpIn/dkimVerifyNotFound** (counter) - **chasquid/smtpIn/dkimVerifyNotFound** (counter)\
count of messages with no DKIM signatures count of messages with no DKIM signatures
- **chasquid/smtpIn/dkimVerifyValid** (counter) - **chasquid/smtpIn/dkimVerifyValid** (counter)\
count of messages with at least one valid DKIM signature count of messages with at least one valid DKIM signature
- **chasquid/smtpIn/hookResults** (result -> counter) - **chasquid/smtpIn/hookResults** (result -> counter)\
count of hook invocations, by result. count of hook invocations, by result.
- **chasquid/smtpIn/loopsDetected** (counter) - **chasquid/smtpIn/loopsDetected** (counter)\
count of email loops detected. count of email loops detected.
- **chasquid/smtpIn/responseCodeCount** (code -> counter) - **chasquid/smtpIn/responseCodeCount** (code -> counter)\
count of response codes returned to incoming SMTP connections, by result count of response codes returned to incoming SMTP connections, by result
code. code.
- **chasquid/smtpIn/securityLevelChecks** (result -> counter) - **chasquid/smtpIn/securityLevelChecks** (result -> counter)\
count of security level checks on incoming connections, by result. count of security level checks on incoming connections, by result.
- **chasquid/smtpIn/spfResultCount** (result -> counter) - **chasquid/smtpIn/spfResultCount** (result -> counter)\
count of SPF checks, by result. count of SPF checks, by result.
- **chasquid/smtpIn/tlsCount** (tls status -> counter) - **chasquid/smtpIn/tlsCount** (tls status -> counter)\
count of TLS statuses (plain/tls) for incoming SMTP connections. count of TLS statuses (plain/tls) for incoming SMTP connections.
- **chasquid/smtpIn/wrongProtoCount** (command -> counter) - **chasquid/smtpIn/wrongProtoCount** (command -> counter)\
count of commands for other protocols (e.g. HTTP commands). count of commands for other protocols (e.g. HTTP commands).
- **chasquid/smtpOut/securityLevelChecks** (result -> counter) - **chasquid/smtpOut/securityLevelChecks** (result -> counter)\
count of security level checks on outgoing connections, by result. count of security level checks on outgoing connections, by result.
- **chasquid/smtpOut/sts/mode** (mode -> counter) - **chasquid/smtpOut/sts/mode** (mode -> counter)\
count of STS checks on outgoing connections, by mode (enforce/testing). count of STS checks on outgoing connections, by mode (enforce/testing).
- **chasquid/smtpOut/sts/security** (result -> counter) - **chasquid/smtpOut/sts/security** (result -> counter)\
count of STS security checks on outgoing connections, by result (pass/fail). count of STS security checks on outgoing connections, by result (pass/fail).
- **chasquid/smtpOut/tlsCount** (status -> counter) - **chasquid/smtpOut/tlsCount** (status -> counter)\
count of TLS status (insecure TLS/secure TLS/plain) on outgoing connections. count of TLS status (insecure TLS/secure TLS/plain) on outgoing connections.
- **chasquid/sourceDateStr** (string) - **chasquid/sourceDateStr** (string)\
timestamp when the binary was built, in human readable format. timestamp when the binary was built, in human readable format.
- **chasquid/sourceDateTimestamp** (int) - **chasquid/sourceDateTimestamp** (int)\
timestamp when the binary was built, in seconds since epoch. timestamp when the binary was built, in seconds since epoch.
- **chasquid/sts/cache/expired** (counter) - **chasquid/sts/cache/expired** (counter)\
count of expired entries in the STS cache. count of expired entries in the STS cache.
- **chasquid/sts/cache/failedFetch** (counter) - **chasquid/sts/cache/failedFetch** (counter)\
count of failed fetches in the STS cache. count of failed fetches in the STS cache.
- **chasquid/sts/cache/fetches** (counter) - **chasquid/sts/cache/fetches** (counter)\
count of total fetches in the STS cache. count of total fetches in the STS cache.
- **chasquid/sts/cache/hits** (counter) - **chasquid/sts/cache/hits** (counter)\
count of hits in the STS cache. count of hits in the STS cache.
- **chasquid/sts/cache/invalid** (counter) - **chasquid/sts/cache/invalid** (counter)\
count of invalid policies in the STS cache. count of invalid policies in the STS cache.
- **chasquid/sts/cache/ioErrors** (counter) - **chasquid/sts/cache/ioErrors** (counter)\
count of I/O errors when maintaining the STS cache. count of I/O errors when maintaining the STS cache.
- **chasquid/sts/cache/marshalErrors** (counter) - **chasquid/sts/cache/marshalErrors** (counter)\
count of marshaling errors when maintaining the STS cache. count of marshaling errors when maintaining the STS cache.
- **chasquid/sts/cache/refreshCycles** (counter) - **chasquid/sts/cache/refreshCycles** (counter)\
count of STS cache refresh cycles. count of STS cache refresh cycles.
- **chasquid/sts/cache/refreshErrors** (counter) - **chasquid/sts/cache/refreshErrors** (counter)\
count of STS cache refresh errors. count of STS cache refresh errors.
- **chasquid/sts/cache/refreshes** (counter) - **chasquid/sts/cache/refreshes** (counter)\
count of STS cache refreshes. count of STS cache refreshes.
- **chasquid/sts/cache/unmarshalErrors** (counter) - **chasquid/sts/cache/unmarshalErrors** (counter)\
count of unmarshaling errors in the STS cache. count of unmarshaling errors in the STS cache.
- **chasquid/version** (string) - **chasquid/version** (string)\
version string. version string.
+19 -47
View File
@@ -1,10 +1,8 @@
# Release notes # Release notes
This file contains notes for each release, summarizing changes and explicitly This file contains notes for each release, summarizing changes and explicitly
noting backward-incompatible changes or known security issues. noting backward-incompatible changes or known security issues.
## 1.18.0 (2026-06-07) ## 1.18.0 (2026-06-07)
- Conform to the stricter OpenMetrics format in the monitoring exporter, which - Conform to the stricter OpenMetrics format in the monitoring exporter, which
@@ -12,7 +10,6 @@ noting backward-incompatible changes or known security issues.
- Fix extra newlines in the authentication log entries. - Fix extra newlines in the authentication log entries.
- Docker image improvements, including updating the Dovecot config to 2.4. - Docker image improvements, including updating the Dovecot config to 2.4.
## 1.17.0 (2025-11-30) ## 1.17.0 (2025-11-30)
- Fix `Received` header format when including the IP address. - Fix `Received` header format when including the IP address.
@@ -20,7 +17,6 @@ noting backward-incompatible changes or known security issues.
- Docker image improvements and bug fixes. - Docker image improvements and bug fixes.
- Minor fixes for systems without /bin. - Minor fixes for systems without /bin.
## 1.16.0 (2025-06-08) ## 1.16.0 (2025-06-08)
- Minor bug fixes to `chasquid-util`. - Minor bug fixes to `chasquid-util`.
@@ -31,7 +27,6 @@ noting backward-incompatible changes or known security issues.
- Make the max queue size and give up time - Make the max queue size and give up time
[configurable](man/chasquid.conf.5.md) *(experimental)*. [configurable](man/chasquid.conf.5.md) *(experimental)*.
## 1.15.0 (2025-01-17) ## 1.15.0 (2025-01-17)
- Exit if there's an error reading users/aliases files on startup. - Exit if there's an error reading users/aliases files on startup.
@@ -40,15 +35,14 @@ noting backward-incompatible changes or known security issues.
### 1.15.1 (2025-03-30) ### 1.15.1 (2025-03-30)
Implement a workaround for a Microsoft bug in TLS session ticket handling, Implement a workaround for a Microsoft bug in TLS session ticket handling, that
that is causing deliverability issues, and they are being too slow at fixing. is causing deliverability issues, and they are being too slow at fixing.
See this [chasquid issue](https://github.com/albertito/chasquid/issues/64), See this [chasquid issue](https://github.com/albertito/chasquid/issues/64),
this [Go issue](https://github.com/golang/go/issues/70232) and this this [Go issue](https://github.com/golang/go/issues/70232) and this
[Postfix thread](https://www.mail-archive.com/postfix-users@postfix.org/msg104308.html) [Postfix thread](https://www.mail-archive.com/postfix-users@postfix.org/msg104308.html)
for more details. for more details.
## 1.14.0 (2024-04-21) ## 1.14.0 (2024-04-21)
- Add built-in [DKIM](dkim.md) signing and verification. - Add built-in [DKIM](dkim.md) signing and verification.
@@ -59,17 +53,16 @@ for more details.
[SemVer](https://semver.org/)-compatible, to help integration with other [SemVer](https://semver.org/)-compatible, to help integration with other
software that expects it (e.g. [pkg.go.dev](https://pkg.go.dev/)). software that expects it (e.g. [pkg.go.dev](https://pkg.go.dev/)).
## 1.13 (2023-12-24) ## 1.13 (2023-12-24)
Security fixes: Security fixes:
- Strict CRLF enforcement in DATA contents, to prevent [SMTP smuggling - Strict CRLF enforcement in DATA contents, to prevent
attacks](https://www.postfix.org/smtp-smuggling.html) [SMTP smuggling attacks](https://www.postfix.org/smtp-smuggling.html)
([CVE-2023-52354](https://nvd.nist.gov/vuln/detail/CVE-2023-52354)). \ ([CVE-2023-52354](https://nvd.nist.gov/vuln/detail/CVE-2023-52354)). \
[RFC5322](https://www.rfc-editor.org/rfc/rfc5322#section-2.3) and [RFC5322](https://www.rfc-editor.org/rfc/rfc5322#section-2.3) and
[RFC5321](https://www.rfc-editor.org/rfc/rfc5321#section-2.3.8) say [RFC5321](https://www.rfc-editor.org/rfc/rfc5321#section-2.3.8) say that the
that the only valid newline terminator in SMTP is CRLF. \ only valid newline terminator in SMTP is CRLF. \
When an invalid newline terminator is found in an incoming message, the When an invalid newline terminator is found in an incoming message, the
connection is now aborted immediately (previous releases also accepted connection is now aborted immediately (previous releases also accepted
LF-terminated lines). \ LF-terminated lines). \
@@ -84,11 +77,10 @@ Other changes:
entry in the config. entry in the config.
- `docker/add-user.sh`: Support getting email and password from env variables. - `docker/add-user.sh`: Support getting email and password from env variables.
## 1.12 (2023-10-07) ## 1.12 (2023-10-07)
- Support [aliases with drop characters and - Support
suffix separators](aliases.md#drop-characters-and-suffix-separators). [aliases with drop characters and suffix separators](aliases.md#drop-characters-and-suffix-separators).
- Improved delivery on some low-level TLS negotiation errors. - Improved delivery on some low-level TLS negotiation errors.
- `smtp-check`: Add flag to specify local name. - `smtp-check`: Add flag to specify local name.
- `chasquid-util`: `aliases-resolve` and `domaininfo-remove` subcommands now - `chasquid-util`: `aliases-resolve` and `domaininfo-remove` subcommands now
@@ -98,7 +90,6 @@ Other changes:
command that was added a while ago, and there is no need for it anymore. command that was added a while ago, and there is no need for it anymore.
- Handle symlinks under the `certs/` directory. - Handle symlinks under the `certs/` directory.
## 1.11 (2023-02-19) ## 1.11 (2023-02-19)
- New tracing library for improved observability. - New tracing library for improved observability.
@@ -110,14 +101,12 @@ Backport the security fixes from 1.13 (*Strict CRLF enforcement in DATA
contents*, fixes contents*, fixes
[CVE-2023-52354](https://nvd.nist.gov/vuln/detail/CVE-2023-52354)). [CVE-2023-52354](https://nvd.nist.gov/vuln/detail/CVE-2023-52354)).
## 1.10 (2022-09-01) ## 1.10 (2022-09-01)
- Support [catch-all aliases](aliases.md#catch-all). - Support [catch-all aliases](aliases.md#catch-all).
- Fix bug in Docker image with user-provided certificates. - Fix bug in Docker image with user-provided certificates.
- Miscellaneous test improvements. - Miscellaneous test improvements.
## 1.9 (2022-03-05) ## 1.9 (2022-03-05)
- Improve certificate validation logic in the SMTP courier. - Improve certificate validation logic in the SMTP courier.
@@ -125,11 +114,10 @@ contents*, fixes
- Support `""` values for `drop_characters` and `suffix_separators` in the - Support `""` values for `drop_characters` and `suffix_separators` in the
configuration file. configuration file.
## 1.8 (2021-07-30) ## 1.8 (2021-07-30)
- Stricter error checking to help prevent cross-protocol attacks - Stricter error checking to help prevent cross-protocol attacks (like
(like [ALPACA](https://alpaca-attack.com/)). [ALPACA](https://alpaca-attack.com/)).
- Allow authenticating users without an `@domain` part. - Allow authenticating users without an `@domain` part.
- Add integration for - Add integration for
[chasquid-rspamd](https://github.com/Thor77/chasquid-rspamd) and [chasquid-rspamd](https://github.com/Thor77/chasquid-rspamd) and
@@ -138,18 +126,16 @@ contents*, fixes
- Use `application/openmetrics-text` as content type in the openmetrics - Use `application/openmetrics-text` as content type in the openmetrics
exporter. exporter.
## 1.7 (2021-05-31) ## 1.7 (2021-05-31)
- chasquid-util no longer depends on the unmaintained docopt-go. - chasquid-util no longer depends on the unmaintained docopt-go. If you relied
If you relied on undocumented parsing behaviour before, your invocations may on undocumented parsing behaviour before, your invocations may need
need adjustment. In particular, `--a b` is no longer supported, and `--a=b` adjustment. In particular, `--a b` is no longer supported, and `--a=b` must
must be used instead. be used instead.
- Improve handling of errors when talking to Dovecot for authentication. - Improve handling of errors when talking to Dovecot for authentication.
- Fix handling of `hostname` option in the Docker image. - Fix handling of `hostname` option in the Docker image.
- Miscellaneous documentation and test improvements. - Miscellaneous documentation and test improvements.
## 1.6 (2020-11-22) ## 1.6 (2020-11-22)
- Pass the EHLO domain to the post-data hook. - Pass the EHLO domain to the post-data hook.
@@ -157,7 +143,6 @@ contents*, fixes
- Implement HAProxy protocol support (experimental). - Implement HAProxy protocol support (experimental).
- Documentation updates. - Documentation updates.
## 1.5 (2020-09-12) ## 1.5 (2020-09-12)
- Add OpenMetrics exporter (compatible with Prometheus). - Add OpenMetrics exporter (compatible with Prometheus).
@@ -166,14 +151,12 @@ contents*, fixes
- Fix rspamd greylist action handling in the default hook. - Fix rspamd greylist action handling in the default hook.
- Miscellaneous monitoring server improvements. - Miscellaneous monitoring server improvements.
## 1.4 (2020-05-22) ## 1.4 (2020-05-22)
- Use the configured hostname in outgoing SMTP HELO/EHLO. - Use the configured hostname in outgoing SMTP HELO/EHLO.
- Allow config overrides from the command line. - Allow config overrides from the command line.
- Miscellaneous test improvements and code cleanups. - Miscellaneous test improvements and code cleanups.
## 1.3 (2020-04-12) ## 1.3 (2020-04-12)
- Improved handling of DNS temporary errors. - Improved handling of DNS temporary errors.
@@ -181,7 +164,6 @@ contents*, fixes
Arch installation instructions). Arch installation instructions).
- Miscellaneous test improvements and cleanups. - Miscellaneous test improvements and cleanups.
## 1.2 (2019-12-06) ## 1.2 (2019-12-06)
Security fixes: Security fixes:
@@ -197,7 +179,6 @@ Release notes:
- New documentation sections (monitoring, release notes). - New documentation sections (monitoring, release notes).
- Many miscellaneous test improvements. - Many miscellaneous test improvements.
## 1.1 (2019-10-26) ## 1.1 (2019-10-26)
- Added hooks for aliases resolution. - Added hooks for aliases resolution.
@@ -207,7 +188,6 @@ Release notes:
- Documentation and test improvements. - Documentation and test improvements.
- Minor bug fixes. - Minor bug fixes.
## 1.0 (2019-07-15) ## 1.0 (2019-07-15)
No backwards-incompatible changes. No more are expected within this major No backwards-incompatible changes. No more are expected within this major
@@ -217,7 +197,6 @@ version.
- Make DSN tidier, especially in handling multi-line errors. - Make DSN tidier, especially in handling multi-line errors.
- Miscellaneous test improvements. - Miscellaneous test improvements.
## 0.07 (2019-01-19) ## 0.07 (2019-01-19)
No backwards-incompatible changes. No backwards-incompatible changes.
@@ -227,14 +206,12 @@ No backwards-incompatible changes.
- Miscellaneous test improvements. - Miscellaneous test improvements.
- DKIM integration examples and test. - DKIM integration examples and test.
## 0.06 (2018-07-22) ## 0.06 (2018-07-22)
No backwards-incompatible changes. No backwards-incompatible changes.
- New MTA-STS (Strict Transport Security) checking. - New MTA-STS (Strict Transport Security) checking.
## 0.05 (2018-06-05) ## 0.05 (2018-06-05)
No backwards-incompatible changes. No backwards-incompatible changes.
@@ -244,7 +221,6 @@ No backwards-incompatible changes.
- Periodic reload of domaininfo, support removing entries manually. - Periodic reload of domaininfo, support removing entries manually.
- Dovecot auth support no longer considered experimental. - Dovecot auth support no longer considered experimental.
## 0.04 (2018-02-10) ## 0.04 (2018-02-10)
No backwards-incompatible changes. No backwards-incompatible changes.
@@ -252,18 +228,16 @@ No backwards-incompatible changes.
- Add Dovecot authentication support (experimental). - Add Dovecot authentication support (experimental).
- Miscellaneous bug fixes to mda-lmtp and tests. - Miscellaneous bug fixes to mda-lmtp and tests.
## 0.03 (2017-07-15) ## 0.03 (2017-07-15)
**Backwards-incompatible changes:** **Backwards-incompatible changes:**
- The default MTA binary has changed. It's now maildrop by default. - The default MTA binary has changed. It's now maildrop by default. If you
If you relied on procmail being the default, add the following to relied on procmail being the default, add the following to
`/etc/chasquid/chasquid.conf`: `mail_delivery_agent_bin: "procmail"`. `/etc/chasquid/chasquid.conf`: `mail_delivery_agent_bin: "procmail"`.
- chasquid now listens on a third port, submission-on-TLS. - chasquid now listens on a third port, submission-on-TLS. If using systemd,
If using systemd, copy the `etc/systemd/system/chasquid-submission_tls.socket` copy the `etc/systemd/system/chasquid-submission_tls.socket` file to
file to `/etc/systemd/system/`, and start it. `/etc/systemd/system/`, and start it.
Release notes: Release notes:
@@ -271,7 +245,6 @@ Release notes:
- Change the default MDA binary to `maildrop`. - Change the default MDA binary to `maildrop`.
- Add a very basic MDA that uses LMTP to do the mail delivery. - Add a very basic MDA that uses LMTP to do the mail delivery.
## 0.02 (2017-03-03) ## 0.02 (2017-03-03)
No backwards-incompatible changes. No backwards-incompatible changes.
@@ -280,7 +253,6 @@ No backwards-incompatible changes.
- Fall back through the MX list on errors. - Fall back through the MX list on errors.
- Experimental MTA-STS implementation (disabled by default). - Experimental MTA-STS implementation (disabled by default).
## 0.01 (2016-11-03) ## 0.01 (2016-11-03)
Initial release. Initial release.
+26 -33
View File
@@ -1,4 +1,3 @@
# Security level checks # Security level checks
chasquid tracks per-domain TLS support, and uses it to prevent connection chasquid tracks per-domain TLS support, and uses it to prevent connection
@@ -11,28 +10,26 @@ servers.
This is very different from other MTAs, and has some tradeoffs. This is very different from other MTAs, and has some tradeoffs.
## Outgoing connections ## Outgoing connections
An outgoing connection has one of 3 security levels, which are (in order): An outgoing connection has one of 3 security levels, which are (in order):
1. Plain: connection is plain-text (the server does not support TLS). 1. Plain: connection is plain-text (the server does not support TLS).
2. TLS insecure: TLS connection established, but the certificate itself was 2. TLS insecure: TLS connection established, but the certificate itself was not
not valid. valid.
3. TLS secure: TLS connection established, with a valid certificate. 3. TLS secure: TLS connection established, with a valid certificate.
When establishing an outgoing connection, chasquid will always attempt to When establishing an outgoing connection, chasquid will always attempt to
negotiate up to the *TLS secure* level. After the negotiation, it will negotiate up to the *TLS secure* level. After the negotiation, it will compare
compare which level it got, with the previously recorded value for this which level it got, with the previously recorded value for this domain:
domain:
* If the connection level is lower than the recorded value, then the - If the connection level is lower than the recorded value, then the connection
connection will be dropped, and the delivery will fail (with a transient will be dropped, and the delivery will fail (with a transient failure). The
failure). The delivery will be retried as usual (using other MXs if delivery will be retried as usual (using other MXs if available, and repeat
available, and repeat after some delay). after some delay).
* If the connection level is the same as the recorded value, then the - If the connection level is the same as the recorded value, then the
connection will proceed. connection will proceed.
* If the connection level is higher, chasquid will record this new value, and - If the connection level is higher, chasquid will record this new value, and
proceed. proceed.
If there is no previously recorded value for this domain, a *plain* level is If there is no previously recorded value for this domain, a *plain* level is
@@ -55,25 +52,24 @@ with MTA-STS and HTTPS, but it is not universally agreed upon. It's also why
the "TLS insecure" state exists, instead of the connection being rejected the "TLS insecure" state exists, instead of the connection being rejected
directly. directly.
### Tradeoffs ### Tradeoffs
Almost all other MTAs do TLS negotiation but accept *all* certificates, even Almost all other MTAs do TLS negotiation but accept *all* certificates, even
self-signed or expired ones. chasquid operates differently, as described self-signed or expired ones. chasquid operates differently, as described above.
above.
The main advantage is that, *with domains where secure connections were The main advantage is that, *with domains where secure connections were
previously established*, chasquid will detect connection downgrading (caused previously established*, chasquid will detect connection downgrading (caused by
by malicious interception such as STARTTLS blocking, as well as malicious interception such as STARTTLS blocking, as well as misconfiguration
misconfiguration such as incorrectly configured or expired certificates), and such as incorrectly configured or expired certificates), and avoid
avoid communicating insecurely. communicating insecurely.
The main disadvantage is that if a domain changes the configuration to a lower The main disadvantage is that if a domain changes the configuration to a lower
security level, chasquid will fail the delivery (returning a message to the security level, chasquid will fail the delivery (returning a message to the
sender explaining why). Because there is no formal standard for TLS sender explaining why). Because there is no formal standard for TLS certificate
certificate validation, and most MTAs will deliver email in this situation, validation, and most MTAs will deliver email in this situation, the domain
the domain owners might not see this as a problem and thus require [manual owners might not see this as a problem and thus require
intervention](#manual-override) on the chasquid side to explicitly allow it. [manual intervention](#manual-override) on the chasquid side to explicitly
allow it.
### MTA-STS ### MTA-STS
@@ -85,7 +81,6 @@ It is supported by chasquid, out of the box, and in practice it means that for
domains that advertise MTA-STS support, the *secure* level will be enforced domains that advertise MTA-STS support, the *secure* level will be enforced
even if the domain was previously unknown. even if the domain was previously unknown.
## Incoming connections ## Incoming connections
Incoming connections from authenticated users are always done over TLS Incoming connections from authenticated users are always done over TLS
@@ -107,11 +102,11 @@ security levels, which are (in order):
At this point, chasquid will compare the level with the previously recorded At this point, chasquid will compare the level with the previously recorded
value for this domain: value for this domain:
* If the connection level is lower than the recorded value, then the - If the connection level is lower than the recorded value, then the connection
connection is rejected with an SMTP error. is rejected with an SMTP error.
* If the connection level is the same as the recorded value, then the - If the connection level is the same as the recorded value, then the
connection is allowed. connection is allowed.
* If the connection level is higher, chasquid will record this new value, and - If the connection level is higher, chasquid will record this new value, and
the connection is allowed. the connection is allowed.
If there is no previously recorded value for this domain, a *plain* level is If there is no previously recorded value for this domain, a *plain* level is
@@ -136,14 +131,12 @@ MTAs will accept the connection anyway, domain owners might not even notice
there is a problem, and might require [manual intervention](#manual-override) there is a problem, and might require [manual intervention](#manual-override)
on the chasquid side to explicitly allow it. on the chasquid side to explicitly allow it.
## Accepting lower security levels {#manual-override} ## Accepting lower security levels {#manual-override}
If a domain changes its configuration to a lower security level and is causing If a domain changes its configuration to a lower security level and is causing
chasquid to fail delivery, you can use chasquid to fail delivery, you can use
`chasquid-util domaininfo-remove <domain>` to make the server forget about `chasquid-util domaininfo-remove <domain>` to make the server forget about that
that domain. domain.
Then, the next time there is a connection, there is no high security Then, the next time there is a connection, there is no high security
expectation so it will proceed just fine, regardless of the level that was expectation so it will proceed just fine, regardless of the level that was
+1 -2
View File
@@ -5,5 +5,4 @@ albertito@blitiri.com.ar, or do it via [GitHub's Security tab].
Thank you! Thank you!
[github's security tab]: https://github.com/albertito/chasquid/security
[GitHub's Security tab]: https://github.com/albertito/chasquid/security
+21 -31
View File
@@ -1,4 +1,3 @@
# Testing # Testing
## Go tests ## Go tests
@@ -6,46 +5,43 @@
All Go packages have their own test suite, which provides easy and portable All Go packages have their own test suite, which provides easy and portable
tests with decent enough coverage. tests with decent enough coverage.
## Integration tests ## Integration tests
In the `test/` directory there is a set of end to end integration tests, In the `test/` directory there is a set of end to end integration tests,
written usually in a combination of bash and Python 3. written usually in a combination of bash and Python 3.
They're not expected to be portable, as that gets impractical very quickly, They're not expected to be portable, as that gets impractical very quickly, but
but should be usable in most Linux environments. should be usable in most Linux environments.
They provide critical coverage and integration tests for real life scenarios, They provide critical coverage and integration tests for real life scenarios,
as well as interactions with other software (like Exim or Dovecot). as well as interactions with other software (like Exim or Dovecot).
### Dependencies ### Dependencies
The tests depend on the following things being installed on the system (listed The tests depend on the following things being installed on the system (listed
as Debian package, for consistency): as Debian package, for consistency):
- `msmtp` - `msmtp`
- `util-linux` (for `/usr/bin/setsid`) - `util-linux` (for `/usr/bin/setsid`)
Some individual tests have additional dependencies, and the tests are skipped Some individual tests have additional dependencies, and the tests are skipped
if the dependencies are not found: if the dependencies are not found:
- `t-02-exim` [Exim](https://www.exim.org/) interaction tests: - `t-02-exim` [Exim](https://www.exim.org/) interaction tests: `gettext-base`
- `gettext-base` (for `/usr/bin/envsubst`) (for `/usr/bin/envsubst`), and the `exim` binary available somewhere, but it
- The `exim` binary available somewhere, but it doesn't have to be doesn't have to be installed. There's a script `get-exim4-debian.sh` to get
installed. There's a script `get-exim4-debian.sh` to get it from the it from the archives.
archives.
- `t-11-dovecot` [Dovecot](https://www.dovecot.org/) interaction tests: - `t-11-dovecot` [Dovecot](https://www.dovecot.org/) interaction tests:
- `dovecot` `dovecot`.
- `t-15-driusan_dkim` DKIM integration tests: - `t-15-driusan_dkim` DKIM integration tests: the
- The `dkimsign dkimverify dkimkeygen` binaries, from `dkimsign dkimverify dkimkeygen` binaries, from
[driusan/dkim](https://github.com/driusan/dkim) (no Debian package yet). [driusan/dkim](https://github.com/driusan/dkim) (no Debian package yet).
- `t-18-haproxy` [HAProxy](https://www.haproxy.org/) integration tests: - `t-18-haproxy` [HAProxy](https://www.haproxy.org/) integration tests:
- `haproxy` `haproxy`.
- `t-19-dkimpy`: [dkimpy](https://pypi.org/project/dkimpy/) integration tests: - `t-19-dkimpy`: [dkimpy](https://pypi.org/project/dkimpy/) integration tests:
- `python3-dkim` `python3-dkim`.
- `t-23-prometheus`: [Prometheus](https://prometheus.io/) integration tests: - `t-23-prometheus`: [Prometheus](https://prometheus.io/) integration tests:
- `prometheus promtool` `prometheus promtool`.
For some tests, python >= 3.5 is required; they will be skipped if it's not For some tests, python >= 3.5 is required; they will be skipped if it's not
available. available.
@@ -56,7 +52,6 @@ environment variable being functional, and will be skipped if it isn't. This
works by default in most Linux systems, but note that the use of works by default in most Linux systems, but note that the use of
`systemd-resolved` can prevent it from working properly. `systemd-resolved` can prevent it from working properly.
## Stress tests ## Stress tests
Also in the `test/` directory there is a set of stress tests, which generate Also in the `test/` directory there is a set of stress tests, which generate
@@ -65,7 +60,6 @@ load against chasquid to measure performance and resource consumption.
While they are not exhaustive, they are useful to catch regressions and track While they are not exhaustive, they are useful to catch regressions and track
improvements on the main code paths. improvements on the main code paths.
## Fuzz tests ## Fuzz tests
Some Go packages also have instrumentation to run fuzz testing against them, Some Go packages also have instrumentation to run fuzz testing against them,
@@ -74,13 +68,11 @@ using the [Go native fuzzing support](https://go.dev/security/fuzz/).
This is critical for packages that handle sensitive user input, such as This is critical for packages that handle sensitive user input, such as
authentication encoding, aliases files, or username normalization. authentication encoding, aliases files, or username normalization.
## Command-line tool tests ## Command-line tool tests
Each command-line tool has their own set of tests, see the `test.sh` file on Each command-line tool has their own set of tests, see the `test.sh` file on
their corresponding directories. their corresponding directories.
## Docker ## Docker
The `test/Dockerfile` can be used to set up a suitable isolated environment to The `test/Dockerfile` can be used to set up a suitable isolated environment to
@@ -89,20 +81,18 @@ run the integration and stress tests.
This is very useful for automated tests, or running the integration tests in This is very useful for automated tests, or running the integration tests in
constrained or non supported environments. constrained or non supported environments.
## Automated tests ## Automated tests
There are two sets of automated tests which are run on every commit to There are two sets of automated tests which are run on every commit to
upstream, and also weekly: upstream, and also weekly:
* [Github Actions](https://github.com/albertito/chasquid/actions), - [Github Actions](https://github.com/albertito/chasquid/actions), configured
configured in the `.github` directory, runs the Go tests, the integration in the `.github` directory, runs the Go tests, the integration tests, checks
tests, checks for vulnerabilities, and finally for vulnerabilities, and finally also builds the
also builds the [public Docker images](docker.md). [public Docker images](docker.md).
* [Cirrus CI](https://cirrus-ci.com/github/albertito/chasquid),
configured in the `.cirrus.yml` file, runs Go tests on FreeBSD.
- [Cirrus CI](https://cirrus-ci.com/github/albertito/chasquid), configured in
the `.cirrus.yml` file, runs Go tests on FreeBSD.
## Coverage ## Coverage