Add Gerrit email account and send-email configuration

We'll have to store Gerrit's email credentials in plain text. Protecting
from outside connections using these in case they'd ever leak is tricky.
We match the account `gerrit@...` in `user.access` and then the local IP
address of the gerrit container in `gerrit-client.access`, only allowing
authenticated users (`permit_sasl_authenticated`) from this IP.

Alternatively, we could use `permit` which would allow the whole gerrit
container to send emails from `gerrit@...` without login. Then the setup
would also allow more efficient, plain-text communication between Gerrit
and Postfix. The password would still be needed to login to IMAP (assu-
ming no further, invasive changes).
diff --git a/.gitignore b/.gitignore
index f2d0bc9..0b36d07 100644
--- a/.gitignore
+++ b/.gitignore
@@ -16,5 +16,6 @@
 /logs/simpleid/
 /mail/config/
 /mail/data/
+/mail/passwd/
 /mail/rspamd-override.d/
 /mail/state/
diff --git a/docker-compose.yml b/docker-compose.yml
index cbabb0b..a120e6c 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -41,13 +41,18 @@
     build:
       context: .
       dockerfile: gerrit/Dockerfile
-    env_file: gerrit/environment
+    hostname: review.${SA_PUBLIC_DOMAIN_NAME}
+    env_file:
+      - gerrit/environment
+      - environment
     environment:
+      - GERRIT_USER_EMAIL=gerrit@${SA_PUBLIC_DOMAIN_NAME}
       - HTTPD_LISTEN_URL=proxy-https://*:8080/
     networks:
       - gerritnet
     volumes:
       - ./logs/gerrit/:/var/gerrit/logs/:rw
+      - ./mail/passwd/gerrit/:/var/gerrit/passwd/:rw
       - ./gerrit/etc/:/var/gerrit/etc/:rw
       - ./gerrit/db/:/var/gerrit/db/:rw
       - ./gerrit/git/:/var/gerrit/git/:rw
@@ -69,10 +74,13 @@
       - "465:465"  # ESMTP (implicit TLS)
       - "587:587"  # ESMTP (explicit TLS => STARTTLS)
       - "993:993"  # IMAP4 (implicit TLS)
+    networks:
+      - gerritnet
     volumes:
       - ./logs/mail-supervisor/:/var/log/supervisor/:rw
       - ./logs/mail/:/var/log/mail/:rw
       - ./certs/:/etc/letsencrypt/:ro
+      - ./mail/passwd/:/tmp/passwd/:ro
       - ./mail/data/:/var/mail/:rw
       - ./mail/state/:/var/mail-state/:rw
       - ./mail/config/:/tmp/docker-mailserver/:rw
diff --git a/gerrit/Dockerfile.entrypoint b/gerrit/Dockerfile.entrypoint
index 6aa141b..3aa8ae1 100644
--- a/gerrit/Dockerfile.entrypoint
+++ b/gerrit/Dockerfile.entrypoint
@@ -3,7 +3,7 @@
 set -e
 
 # Allows us to bind mount arbitrary owned files
-chown -R gerrit:gerrit /var/gerrit/{logs,etc,db,git,index,cache}/
+chown -R gerrit:gerrit /var/gerrit/{logs,etc,db,git,index,cache,passwd}/
 
 # Drop privileges as we set `USER root` only to change file permissions
 exec setpriv --reuid=gerrit --regid=gerrit --init-groups --inh-caps=-all /unprivileged.sh "$@"
diff --git a/gerrit/Dockerfile.entrypoint-unprivileged b/gerrit/Dockerfile.entrypoint-unprivileged
index 86574b1..5af70c9 100644
--- a/gerrit/Dockerfile.entrypoint-unprivileged
+++ b/gerrit/Dockerfile.entrypoint-unprivileged
@@ -11,4 +11,25 @@
         plugin.gerrit-oauth-provider-github-oauth.client-secret "${GITHUB_OAUTH_CLIENT_SECRET}"
 fi
 
+secret=/var/gerrit/passwd/secret
+
+{
+    if [ ! -f ${secret} ]; then
+        echo $(mktemp -u XXXXXXXXXXXXXXXX) >${secret}
+    fi
+    chmod 400 ${secret}
+}
+
+if [ "${GERRIT_USER_EMAIL}" ]; then
+    passwd=$(cat ${secret})
+
+    git config -f /etc/gerrit/gerrit.config user.email ${GERRIT_USER_EMAIL}
+    git config -f /etc/gerrit/gerrit.config sendemail.smtpServer mail.${SA_PUBLIC_DOMAIN_NAME}
+    git config -f /etc/gerrit/gerrit.config sendemail.smtpServerPort 465
+    git config -f /etc/gerrit/gerrit.config sendemail.smtpEncryption ssl
+    git config -f /etc/gerrit/gerrit.config sendemail.smtpUser ${GERRIT_USER_EMAIL}
+    git config -f /etc/gerrit/gerrit.config sendemail.smtpPass ${passwd}
+    git config -f /etc/gerrit/gerrit.config sendemail.html false
+fi
+
 exec /entrypoint.sh "$@"
diff --git a/mail/config/postfix-main.cf b/mail/config/postfix-main.cf
new file mode 100644
index 0000000..378644a
--- /dev/null
+++ b/mail/config/postfix-main.cf
@@ -0,0 +1,3 @@
+gerrit_sender_check = check_client_access hash:/tmp/docker-mailserver/gerrit-client.access, reject
+smtpd_restriction_classes = gerrit_sender_check
+dms_smtpd_sender_restrictions = check_sender_access hash:/tmp/docker-mailserver/user.access, permit_sasl_authenticated, permit_mynetworks, reject_unknown_sender_domain
diff --git a/mail/config/user-patches.sh b/mail/config/user-patches.sh
index 4be7d15..5a10bbd 100644
--- a/mail/config/user-patches.sh
+++ b/mail/config/user-patches.sh
@@ -2,6 +2,46 @@
 
 set -e
 
+# Add local containers as trusted for postfix relaying.
+add_mynetworks_hosts() {
+    myhosts=
+    for host in mailserver "$@"; do
+        IP=$(host ${host} | sed -n 's/.*has address //p')
+        myhosts="${myhosts} ${IP}/32"
+    done
+    postconf "mynetworks =${myhosts}"
+}
+
+# Create given users, requiring a plain-text password in `/tmp/passwd/`.
+add_users_with_passwd() {
+    for user in "$@"; do
+        i=0
+        while [ -z "$(cat /tmp/passwd/${user}/secret 2>/dev/null)" ]; do
+            if [ ${i} -eq 10 ]; then
+                echo "ERROR: No password file for '${user}' after ${i}s."
+                exit 1
+            fi
+            sleep 1
+            i=$((i+1))
+        done
+
+        if [ ! -d /var/mail/${HOSTNAME#mail.}/${user} ]; then
+            setup email add gerrit@${HOSTNAME#mail.} $(cat /tmp/passwd/${user}/secret)
+        else
+            setup email update gerrit@${HOSTNAME#mail.} $(cat /tmp/passwd/${user}/secret)
+        fi
+    done
+}
+
 {
-	setup email list | grep -q '^\* gerrit@' || setup email add gerrit@${HOSTNAME#mail.} psst,gerrit
+    add_users_with_passwd gerrit
+
+    # Restrict gerrit@ sending to local IP:
+    if ! grep -q gerrit /tmp/docker-mailserver/user.access 2>/dev/null; then
+        echo "gerrit@${HOSTNAME#mail.} gerrit_sender_check" >>/tmp/docker-mailserver/user.access
+        postmap /tmp/docker-mailserver/user.access
+    fi
+    IP=$(host gerrit | sed -n 's/.*has address //p')
+    echo "${IP} permit_sasl_authenticated"  >/tmp/docker-mailserver/gerrit-client.access
+    postmap /tmp/docker-mailserver/gerrit-client.access
 }