File: flow.md

package info (click to toggle)
chasquid 1.16.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 2,744 kB
  • sloc: sh: 1,325; python: 341; makefile: 78
file content (67 lines) | stat: -rw-r--r-- 2,559 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67

# Message flows

This document explains at a high level some parts of chasquid's message
processing, in particular how messages flow through the system.


## Message reception

- Client connects to chasquid on the smtp or submission ports, and issues
  HELO/EHLO.
- Client optionally performs STARTTLS.
- Client optionally performs AUTH.
    - Check that this is done over TLS.
- Client sends MAIL FROM.
    - Check SPF.
    - Check connection security level.
- 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 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.


### Authenticated mail, and email spoofing

By default, authenticated users can send emails as any other user or domain.
For example, you can authenticate as `a@a`, and send email as `b@b`.

This is a design choice made to balance simplicity of operation and use.

Users who want to be strict about "MAIL FROM" or even "From:" validation can
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,
or on a per-domain or per-user basis. But for now, using a [post-DATA
hook](hooks.md) is the best way to make chasquid more strict about this.


## Queue processing

Before accepting a message:

- Create a (pseudo) random internal ID for it.
- For each recipient, use the alias database to expand it, add the results to
  the list of final recipients (which may not be email).
- Save the resulting envelope (with the final recipients) to disk.

Queue processing runs asynchronously, there's a goroutine for each message
which does, in a loop:

- For each recipient which we have not delivered yet:
    - Attempt delivery.
    - Write to disk the results.
- If there are mails still pending, wait for some time (incrementally).
- When all the recipients have completed delivery, or enough time has passed:
    - If all were successful, remove from the queue.
    - If some failed, send a delivery status notification back to the sender.