Mailman3(Docker) + Postfix + Nginx 環境の作り方 on Ubuntu

## 概要
Ubuntu22にて、Dockerを用いたMailman3を建てました。
Nginxを用いた手法で日本語のドキュメントがなかったため記録を残します。
細かい説明は、記事最後に添付してある公式ドキュメントをお読みください。

## Mailman3(Docker)の導入

データを永続化するためのディレクトリを生成
githubから一式clone
```sh
$ mkdir -p /opt/mailman/core
$ mkdir -p /opt/mailman/web
$ git clone https://github.com/maxking/docker-mailman
$ cd docker-mailman
```

dockerシークレットキーを生成
```sh
$ sudo apt install python3-django
$ python3
>>> from django.core.management.utils import get_random_secret_key
>>> print(get_random_secret_key())
SECRET_KEYが生成されるのでコピー。
printする度に値が変わる。
>>> [Ctrl]+[D]
```

compose yamlを編集
```sh
$ vim docker-compose-mysql.yaml
```

```diff
diff --git a/docker-compose-mysql.yaml b/docker-compose-mysql.yaml
--- a/docker-compose-mysql.yaml
+++ b/docker-compose-mysql.yaml
@@ -17,6 +17,10 @@ services:
     - DATABASE_TYPE=mysql
     - DATABASE_CLASS=mailman.database.mysql.MySQLDatabase
     - HYPERKITTY_API_KEY=someapikey
+    - MTA=postfix
     ports:
     - "127.0.0.1:8001:8001" # API
     - "127.0.0.1:8024:8024" # LMTP - incoming emails
@@ -38,8 +42,13 @@ services:
     - DATABASE_TYPE=mysql
     - DATABASE_URL=mysql://mailman:mailmanpass@database/mailmandb?charset=utf8mb4
     - HYPERKITTY_API_KEY=someapikey
-    - SECRET_KEY=thisisaverysecretkey
+    - SECRET_KEY=先ほど作成したkeyをペースト
     - DYLD_LIBRARY_PATH=/usr/local/mysql/lib/
+    - SERVE_FROM_DOMAIN=example.com
+    - MAILMAN_ADMIN_USER=admin
+    - MAILMAN_ADMIN_EMAIL=admin@example.com
     #ここで入力したMAILMAN_ADMIN_EMAILがmailmanの管理者ユーザとして登録されるため、疎通可能なメアドにする。
     #初回ログイン時は”パスワードを忘れた”を選択して、パスワード設定をする。
+    - MAILMAN_HOST_IP=*
+    - UWSGI_STATIC_MAP=/static=/opt/mailman-web-data/static
     ports:
     - "127.0.0.1:8000:8000" # HTTP
     - "127.0.0.1:8080:8080" # uwsgi
```

dockerコンテナをビルド&起動
```sh
$ sudo docker compose -f docker-compose-mysql.yaml up --build -d
```

## Postfixの導入
https://www.digitalocean.com/community/tutorials/how-to-install-and-configure-postfix-on-ubuntu-20-04-ja

上記の通りに進める。
s-nailはインストールしないでも良い。

疎通テスト
このコマンドで、指定したメール宛にThisIsTestのメールが送信されるので、メールの受信を確認する。
```sh
echo ThisIsTest |sendmail TARGET@example.com
```


mailman用の設定
```sh
$ sudo vim /etc/postfix/main.cf
```

以下を末尾に追加
```yaml
# main.cf

# Support the default VERP delimiter.
recipient_delimiter = +
unknown_local_recipient_reject_code = 550
owner_request_special = no

transport_maps =
    regexp:/opt/mailman/core/var/data/postfix_lmtp
local_recipient_maps =
    regexp:/opt/mailman/core/var/data/postfix_lmtp
relay_domains =
    regexp:/opt/mailman/core/var/data/postfix_domains
```

設定を確認
```sh
$ docker exec mailman-core cat /etc/mailman.cfg
```

```yaml
[mta]
incoming: mailman.mta.postfix.LMTP
outgoing: mailman.mta.deliver.deliver
lmtp_host: 172.19.199.3
lmtp_port: 8024
smtp_host: 172.19.199.1
smtp_port: 25
configuration: /etc/postfix-mailman.cfg
```

上記で確認したものを参考に、下記の3つのパラメータを設定
```diff
diff --git a/docker-compose-mysql.yaml b/docker-compose-mysql.yaml
--- a/docker-compose-mysql.yaml
+++ b/docker-compose-mysql.yaml
@@ -17,6 +17,10 @@ services:
     - DATABASE_TYPE=mysql
     - DATABASE_CLASS=mailman.database.mysql.MySQLDatabase
     - HYPERKITTY_API_KEY=someapikey
+    - SMTP_HOST=172.19.199.1
+    - SMTP_PORT=25
+    - MM_HOSTNAME=172.19.199.3
     ports:
     - "127.0.0.1:8001:8001" # API
     - "127.0.0.1:8024:8024" # LMTP - incoming emails
```

## mailmanのsite_ownerを生成
```sh
sudo vim /opt/mailman/core/mailman-extra.cfg
```
以下を追加
```yaml
[mailman]
# This address is the "site owner" address.  Certain messages which must be
# delivered to a human, but which can't be delivered to a list owner (e.g. a
# bounce from a list owner), will be sent to this address.  It should point to
# a human.
site_owner: changeme@example.com
```

## dockerを再起動し、一通りテスト
```sh
$ cd
$ cd docker-mailman
$ docker compose down
$ sudo docker compose -f docker-compose-mysql.yaml up --build -d
$ echo ThisIsTest |sendmail TARGET@example.com
$ curl localhost:8000/postorius/lists/
```


## Nginxで外部との疎通

```sh
$ sudo apt install nginx -y
$ sudo vim /etc/nginx/sites-available/default
下記の設定をhttpかhttpsで指定。
$ sudo service nginx restart
```

### http version
```nginx
server {
    listen 80;
    server_name example.com;

    location /static {
        alias /opt/mailman/web/static;
        autoindex off;
    }

    location / {
          uwsgi_pass localhost:8080;
          include uwsgi_params;
          uwsgi_read_timeout 300;
    }
}
```

### https version
```nginx
server {
    listen 80;
    return 301 https://$host$request_uri;
}

server {
  listen 443 ssl;
  server_name example.com;

  ssl_certificate /etc/ssl/certs/example.com.cer;
  ssl_certificate_key /etc/ssl/private/example.com.key;

    location /static {
        alias /opt/mailman/web/static;
        autoindex off;
    }

    location / {
          uwsgi_pass localhost:8080;
          include uwsgi_params;
          uwsgi_read_timeout 300;
    }
}
```


サーバ外部からのアクセスのためにport解放
```sh
$ sudo ufw allow 22
$ sudo ufw allow domain
$ ufw allow http
$ ufw allow https
$ sudo ufw reload
$ sudo ufw enable
```

ブラウザから指定したドメイン　or　ipアドレスにアクセスして確認

### 参考
https://asynchronous.in/docker-mailman/#setting-up-your-mta