Docker上のUbuntu 20.04 にSMTPクライアントのmsmtpを導入して、GmailのSMTPサーバを使ったメール送信の動作確認をする

# 用意した物

1. Docker for WindowsのセットアップされたPC(例えば、https://qiita.com/fkooo/items/d2fddef9091b906675ca を参照。)
    * Windows 10 Pro 64bit
    * AMD Ryzen 7 3700X@2.20GHz
    * 32GB Memory
1. Gmailアカウント

# 前準備

GmailのSMTPサーバをmsmtpから利用するには、サードパーティアプリケーションによるアクセスを有効にする必要があります。

以下のURLから、Googleアカウントでログインし、「安全性の低いアプリのアクセス」欄の「安全性の低いアプリの許可」を「有効」にします。
https://www.google.com/settings/u/2/security/lesssecureapps

次に、PowerShellかコマンドプロンプトで、Ubuntu 20.04のイメージを落としてきて、動作確認のため終了後にコンテナを自動削除するようにrmオプションで起動します。

```bash
docker run --rm -it ubuntu:focal bash
```

起動後はrootアカウントでログインした状態になっています。そのまま、システムアップデートしておきます。

```bash
apt update && apt dist-upgrade -y
```

# msmtpの導入と動作確認

まずは、msmtpをaptで導入します。

```bash
apt install -y msmtp msmtp-mta
```

次に、msmtpの設定ファイルを作成します。

```bash
echo -e "\
defaults\n\
syslog          LOG_MAIL\n\
aliases         /etc/aliases\n\
tls             on\n\
tls_starttls    on\n\
tls_certcheck   off\n\
auth            on\n\
account         gmail\n\
host            smtp.gmail.com\n\
port            587\n\
from            [アカウント名]@gmail.com\n\
user            [アカウント名]@gmail.com\n\
password        [パスワード]\n\
account default : gmail\n\
" | tee -a /etc/msmtprc
```

パスワードに記号が含まれる場合には、エスケープする必要があります。

そして、テストメールを送付します。

```bash
echo 'hello world' | msmtp -v [アカウント名]@gmail.com
```

エラーなく送信できれば成功です。

設定ファイル内にパスワードが平文で書かれたままであるのは、セキュリティ的に良くありません。

そこで、GnuPGでパスワードを暗号化したファイルを作成しておいて、利用時に読み込んで復号化するようにします。

# GnuPGの導入と動作確認

GnuPGをaptで導入します。

```bash
apt install gnupg
```

まずは、プライマリキーを作成します。

```bash
gpg --expert --full-gen-key
```

ここでは対話的に、以下のようにして作成しました。

```bash
gpg (GnuPG) 2.2.4; Copyright (C) 2017 Free Software Foundation, Inc.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

gpg: directory '/root/.gnupg' created
gpg: keybox '/root/.gnupg/pubring.kbx' created
Please select what kind of key you want:
   (1) RSA and RSA (default)
   (2) DSA and Elgamal
   (3) DSA (sign only)
   (4) RSA (sign only)
   (7) DSA (set your own capabilities)
   (8) RSA (set your own capabilities)
   (9) ECC and ECC
  (10) ECC (sign only)
  (11) ECC (set your own capabilities)
  (13) Existing key
Your selection? 11

Possible actions for a ECDSA/EdDSA key: Sign Certify Authenticate
Current allowed actions: Sign Certify

   (S) Toggle the sign capability
   (A) Toggle the authenticate capability
   (Q) Finished

Your selection? s

Possible actions for a ECDSA/EdDSA key: Sign Certify Authenticate
Current allowed actions: Certify

   (S) Toggle the sign capability
   (A) Toggle the authenticate capability
   (Q) Finished

Your selection? q
Please select which elliptic curve you want:
   (1) Curve 25519
   (3) NIST P-256
   (4) NIST P-384
   (5) NIST P-521
   (6) Brainpool P-256
   (7) Brainpool P-384
   (8) Brainpool P-512
   (9) secp256k1
Your selection? 1
Please specify how long the key should be valid.
         0 = key does not expire
      <n>  = key expires in n days
      <n>w = key expires in n weeks
      <n>m = key expires in n months
      <n>y = key expires in n years
Key is valid for? (0) 0
Key does not expire at all
Is this correct? (y/N) y

GnuPG needs to construct a user ID to identify your key.

Real name: [フルネーム]
Email address: [アカウント名]@gmail.com
Comment:
You selected this USER-ID:
    "[フルネーム] <[アカウント名]@gmail.com>"

Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? o
We need to generate a lot of random bytes. It is a good idea to perform
some other action (type on the keyboard, move the mouse, utilize the
disks) during the prime generation; this gives the random number
generator a better chance to gain enough entropy.
gpg: /root/.gnupg/trustdb.gpg: trustdb created
gpg: key E2DE895741D650C5 marked as ultimately trusted
gpg: directory '/root/.gnupg/openpgp-revocs.d' created
gpg: revocation certificate stored as '/root/.gnupg/openpgp-revocs.d/5E28E1E64EA825B98BFCD07AE2DE895741D650C5.rev'
public and secret key created and signed.

pub   ed25519 2021-09-16 [C]
      5E28E1E64EA825B98BFCD07AE2DE895741D650C5
uid                      [フルネーム] <[アカウント名]@gmail.com>
```

Passphraseを聞かれますが、ここではなしにしておきます（Enterを押下）。

無事に作成できているかどうかを、確認しておきます。

```bash
gpg --list-keys
```

```bash
gpg: checking the trustdb
gpg: marginals needed: 3  completes needed: 1  trust model: pgp
gpg: depth: 0  valid:   1  signed:   0  trust: 0-, 0q, 0n, 0m, 0f, 1u
/root/.gnupg/pubring.kbx
------------------------
pub   ed25519 2021-09-16 [C]
      5E28E1E64EA825B98BFCD07AE2DE895741D650C5
uid           [ultimate] [フルネーム] <[アカウント名]@gmail.com>
```

次に、暗号化機能を持つサブキーを作成します。

```bash
gpg --expert --edit-key 5E28E1E64EA825B98BFCD07AE2DE895741D650C5
```

ここでは、対話的に以下のように作成しました。

```bash
gpg (GnuPG) 2.2.4; Copyright (C) 2017 Free Software Foundation, Inc.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Secret key is available.

sec  ed25519/E2DE895741D650C5
     created: 2021-09-16  expires: never       usage: C
     trust: ultimate      validity: ultimate
[ultimate] (1). [フルネーム] <[アカウント名]@gmail.com>

gpg> addkey
Please select what kind of key you want:
   (3) DSA (sign only)
   (4) RSA (sign only)
   (5) Elgamal (encrypt only)
   (6) RSA (encrypt only)
   (7) DSA (set your own capabilities)
   (8) RSA (set your own capabilities)
  (10) ECC (sign only)
  (11) ECC (set your own capabilities)
  (12) ECC (encrypt only)
  (13) Existing key
Your selection? 12
Please select which elliptic curve you want:
   (1) Curve 25519
   (3) NIST P-256
   (4) NIST P-384
   (5) NIST P-521
   (6) Brainpool P-256
   (7) Brainpool P-384
   (8) Brainpool P-512
   (9) secp256k1
Your selection? 1
Please specify how long the key should be valid.
         0 = key does not expire
      <n>  = key expires in n days
      <n>w = key expires in n weeks
      <n>m = key expires in n months
      <n>y = key expires in n years
Key is valid for? (0) 0
Key does not expire at all
Is this correct? (y/N) y
Really create? (y/N) y
We need to generate a lot of random bytes. It is a good idea to perform
some other action (type on the keyboard, move the mouse, utilize the
disks) during the prime generation; this gives the random number
generator a better chance to gain enough entropy.

sec  ed25519/E2DE895741D650C5
     created: 2021-09-16  expires: never       usage: C
     trust: ultimate      validity: ultimate
ssb  cv25519/E2BC99E6A0CE6B17
     created: 2021-09-16  expires: never       usage: E
[ultimate] (1). [フルネーム] <[アカウント名]@gmail.com>

gpg> q
Save changes? (y/N) y
```

ここでもPassphraseを聞かれますが、ここではなしにしておきます（Enterを押下）。

作成が終わったら、再び確認します。

```bash
gpg --list-keys
```

サブキーを示す"sub"と暗号化機能を示す"[E]"を持つ行が、リストに追加されていれば成功です。

```bash
/root/.gnupg/pubring.kbx
------------------------
pub   ed25519 2021-09-16 [C]
      5E28E1E64EA825B98BFCD07AE2DE895741D650C5
uid           [ultimate] [フルネーム] <[アカウント名]@gmail.com>
sub   cv25519 2021-09-16 [E]
```

作成したキーを使って、パスワードを暗号化して保存します。

```bash
gpg --encrypt -o /root/.msmtp-gmail.gpg -r [アカウント名]@gmail.com -
```

キーボードからパスワードを入力し、Enterキーを押してからCtrl+dキーの押下で終了します。

暗号化されたパスワードが書き込まれた/root/msmtp-gmail.gpgというバイナリファイルが、作成されます。

この暗号化パスワードファイルを読み込むように、msmtpの設定ファイルを作成し直します。

```bash
rm /etc/msmtprc
echo -e "\
defaults\n\
syslog          LOG_MAIL\n\
aliases         /etc/aliases\n\
tls             on\n\
tls_starttls    on\n\
tls_certcheck   off\n\
auth            on\n\
account         gmail\n\
host            smtp.gmail.com\n\
port            587\n\
from            [アカウント名]@gmail.com\n\
user            [アカウント名]@gmail.com\n\
passwordeval    \"gpg --quiet --for-your-eyes-only --no-tty --decrypt /root/.msmtp-gmail.gpg\"\n\
account default : gmail\n\
" | tee -a /etc/msmtprc
```

テストメールを送付します。

```bash
echo 'hello world' | msmtp -v [アカウント名]@gmail.com
```

エラーなく送信できれば成功です。

# おわりに

以上で、動作確認が終わりました。コマンドラインから抜けます。

```bash
exit
```

Docker上のUbuntu 20.04のコンテナは、自動的に削除されます。

# 参考サイト

https://www.thefunky-monkey.com/page/googlesmtp/

https://qiita.com/suzutan/items/cbd6fc56c0a50100e7c0

https://wiki.archlinux.jp/index.php/Msmtp

https://text.baldanders.info/remark/2019/06/send-mail-without-mail-service/