Services and internal structure ------------------------------- The chatmail relay repository has four directories: - `cmdeploy `_ is a collection of configuration files and a `pyinfra `_ - based deployment script. - `chatmaild `_ is a Python package containing several small services which handle authentication, trigger push notifications on new messages, ensure that outbound mails are encrypted, delete inactive users, and some other minor things. chatmaild can also be installed as a stand-alone Python package. - `www `_ contains the html, css, and markdown files which make up a chatmail relay’s web page. Edit them before deploying to make your chatmail relay stand out. - `scripts `_ offers two convenience tools for beginners; ``initenv.sh`` installs the necessary dependencies to a local virtual environment, and the ``scripts/cmdeploy`` script enables you to run the ``cmdeploy`` command line tool in the local virtual environment. cmdeploy ~~~~~~~~ The ``cmdeploy/src/cmdeploy/cmdeploy.py`` command line tool helps with setting up and managing the chatmail service. ``cmdeploy init`` creates the ``chatmail.ini`` config file. ``cmdeploy run`` uses a `pyinfra `_-based `script `_ to automatically install or upgrade all chatmail components on a relay, according to the ``chatmail.ini`` config. The components of chatmail are: - `Postfix SMTP MTA `_ accepts and relays messages (both from your users and from the wider e-mail MTA network) - `Dovecot IMAP MDA `_ stores messages for your users until they download them - `Nginx `_ shows the web page with your privacy policy and additional information - `acmetool `_ manages TLS certificates for Dovecot, Postfix, and Nginx - `OpenDKIM `_ for signing messages with DKIM and rejecting inbound messages without DKIM - `mtail `_ for collecting anonymized metrics in case you have monitoring - `Iroh relay `_ which helps client devices to establish Peer-to-Peer connections - `TURN `_ to enable relay users to start webRTC calls even if a p2p connection can’t be established - and the chatmaild services, explained in the next section: chatmaild ~~~~~~~~~ ``chatmaild`` implements various systemd-controlled services that integrate with Dovecot and Postfix to achieve instant-onboarding and only relaying OpenPGP end-to-end messages encrypted messages. A short overview of ``chatmaild`` services: - `doveauth `_ implements create-on-login address semantics and is used by Dovecot during IMAP login and by Postfix during SMTP/SUBMISSION login which in turn uses `Dovecot SASL `_ to authenticate logins. - `filtermail `_ prevents unencrypted email from leaving or entering the chatmail service and is integrated into Postfix’s outbound and inbound mail pipelines. - `chatmail-metadata `_ is contacted by a `Dovecot lua script `_ to store user-specific relay-side config. On new messages, it `passes the user’s push notification token `_ to `notifications.delta.chat `_ so the push notifications on the user’s phone can be triggered by Apple/Google/Huawei. - `delete_inactive_users `_ deletes users if they have not logged in for a very long time. The timeframe can be configured in ``chatmail.ini``. - `lastlogin `_ is contacted by Dovecot when a user logs in and stores the date of the login. - `echobot `_ is a small bot for test purposes. It simply echoes back messages from users. - `metrics `_ collects some metrics and displays them at ``https://example.org/metrics``. Mailbox directory layout ~~~~~~~~~~~~~~~~~~~~~~~~ Fresh chatmail addresses have a mailbox directory that contains: - a ``password`` file with the salted password required for authenticating whether a login may use the address to send/receive messages. If you modify the password file manually, you effectively block the user. - ``enforceE2EEincoming`` is a default-created file with each address. If present the file indicates that this chatmail address rejects incoming cleartext messages. If absent the address accepts incoming cleartext messages. - ``dovecot*``, ``cur``, ``new`` and ``tmp`` represent IMAP/mailbox state. If the address is only used by one device, the Maildir directories will typically be empty unless the user of that address hasn’t been online for a while. Active ports ~~~~~~~~~~~~ `Postfix `_ listens on ports 25 (SMTP) and 587 (SUBMISSION) and 465 (SUBMISSIONS). `Dovecot `_ listens on ports 143 (IMAP) and 993 (IMAPS). `Nginx `_ listens on port 8443 (HTTPS-ALT) and 443 (HTTPS). Port 443 multiplexes HTTPS, IMAP and SMTP using ALPN to redirect connections to ports 8443, 465 or 993. `acmetool `_ listens on port 80 (HTTP). `chatmail-turn `_ listens on UDP port 3478 (STUN/TURN), and temporarily opens UDP ports when users request them. UDP port range is not restricted, any free port may be allocated. chatmail-core based apps will, however, discover all ports and configurations automatically by reading the `autoconfig XML file `_ from the chatmail relay server. Email authentication ~~~~~~~~~~~~~~~~~~~~ Chatmail relays enforce `DKIM `_ to authenticate incoming emails. Incoming emails must have a valid DKIM signature with Signing Domain Identifier (SDID, ``d=`` parameter in the DKIM-Signature header) equal to the ``From:`` header domain. This property is checked by OpenDKIM screen policy script before validating the signatures. This correpsonds to strict `DMARC `_ alignment (``adkim=s``), but chatmail does not rely on DMARC and does not consult the sender policy published in DMARC records. Other legacy authentication mechanisms such as `iprev `_ and `SPF `_ are also not taken into account. If there is no valid DKIM signature on the incoming email, the sender receives a “5.7.1 No valid DKIM signature found” error. Outgoing emails must be sent over authenticated connection with envelope MAIL FROM (return path) corresponding to the login. This is ensured by Postfix which maps login username to MAIL FROM with ```smtpd_sender_login_maps`` `_ and rejects incorrectly authenticated emails with ```reject_sender_login_mismatch`` `_ policy. ``From:`` header must correspond to envelope MAIL FROM, this is ensured by ``filtermail`` proxy. TLS requirements ~~~~~~~~~~~~~~~~ Postfix is configured to require valid TLS by setting ```smtp_tls_security_level`` `_ to ``verify``. If emails don’t arrive at your chatmail relay server, the problem is likely that your relay does not have a valid TLS certificate. You can test it by resolving ``MX`` records of your relay domain and then connecting to MX relays (e.g ``mx.example.org``) with ``openssl s_client -connect mx.example.org:25 -verify_hostname mx.example.org -verify_return_error -starttls smtp`` from the host that has open port 25 to verify that certificate is valid. When providing a TLS certificate to your chatmail relay server, make sure to provide the full certificate chain and not just the last certificate. If you are running an Exim server and don’t see incoming connections from a chatmail relay server in the logs, make sure ``smtp_no_mail`` log item is enabled in the config with ``log_selector = +smtp_no_mail``. By default Exim does not log sessions that are closed before sending the ``MAIL`` command. This happens if certificate is not recognized as valid by Postfix, so you might think that connection is not established while actually it is a problem with your TLS certificate.