Docker環境のMailDevでSMTP認証をする

Docker初心者なので個人的な備忘録として。。。

# はじめに

メール配信は、Sendmail/SMTPの両方に対応しないといけません。
そして、SMTP配信を使う場合は、SMTP Authを使っての認証を使うことが欠かせません。

このためSMTP Authの開発・テスト環境を作っていきます。

前回作成した、[DockerでPHP-alpineのメール配信テスト(SMTP/sendmail)環境を構築する](https://qiita.com/idani/items/e703b8810db219bd57fa)をベースに、[step10-php5-xdebug-redis-mail3](https://github.com/idani/nginx-http2-php-mysql)として作成していきます。

# TL;DR

GitHub上のサンプルコードのStep10をご覧ください。
[step10-php5-xdebug-redis-mail3](https://github.com/idani/nginx-http2-php-mysql)

# MailDevのSMTP Auth対応

SMTP Authへの対応は、[MailDev](https://github.com/djfarrelly/MailDev)のUsageに書いています。
MailDevの起動オプションに、「--incoming-user」と「--incoming-pass」をつければいいそうです。

```conf
maildev [options]

  -h, --help                      output usage information
  -V, --version                   output the version number
  -s, --smtp <port>               SMTP port to catch emails [1025]
  -w, --web <port>                Port to run the Web GUI [1080]
・・・省略・・・
  --incoming-user <user>          SMTP user for incoming emails
  --incoming-pass <pass>          SMTP password for incoming emails
・・・省略・・・
  -o, --open                      Open the Web GUI after startup
  -v, --verbose
  --silent
```

ここまではわかるのですが、じゃ、Dockerとしてはどうしたらいいの？ってなりました。

[MailDevのDockerHubに記載されているDockerfile](https://hub.docker.com/r/djfarrelly/maildev/dockerfile)を見ると、最後に「CMD ["bin/maildev", "--web", "80", "--smtp", "25"]」という記載があります。

```Dockerfile:MailDevのデフォルトのDockerfile
FROM node:6-alpine
MAINTAINER "Dan Farrelly <daniel.j.farrelly@gmail.com>"

ENV NODE_ENV production

RUN mkdir -p /usr/src/app
WORKDIR /usr/src/app

ADD package.json /usr/src/app/

RUN npm install && \
    npm prune && \
    npm cache clean \
    rm -rf /tmp/*

ADD . /usr/src/app/

EXPOSE 80 25

CMD ["bin/maildev", "--web", "80", "--smtp", "25"]
```

ここを書き換えてImageを作り直すのかな？ってとも思いました。

さらに調査すると、docker-compose.ymlでcommandという形で指定ができることがわかりました。

* [Docker Compose file refrence](https://docs.docker.com/compose/compose-file/)
 * 直接リンクがないので、リファンレスページ内でcommand で検索をしてください。
* [コマンドはdocker-compose-ymlとdockerfileのどちらで定義するほうがいい](https://ja.stackoverflow.com/questions/30495/%E3%82%B3%E3%83%9E%E3%83%B3%E3%83%89%E3%81%AFdocker-compose-yml%E3%81%A8dockerfile%E3%81%AE%E3%81%A9%E3%81%A1%E3%82%89%E3%81%A7%E5%AE%9A%E7%BE%A9%E3%81%99%E3%82%8B%E3%81%BB%E3%81%86%E3%81%8C%E3%81%84%E3%81%84)

step10のdocker-compose.ymlを以下のように書き換えます。
SMTP AUTHのID/PWは変更する可能性があるので環境変数指定にします。

```yml:docker-compose.yml
version: '3'
services:
・・・省略・・・
  maildev:
    image: kanemu/maildev-with-iconv
    command: bin/maildev -w 80 -s 25 --incoming-user ${SMTP_USER} --incoming-pass ${SMTP_PASSWORD}
    ports:
      - "1025:25"
      - "8025:80"
・・・省略・・・

```

.envファイルにID/PWを追記します。

```shell:.env
MYSQL_RANDOM_ROOT_PASSWORD=yes
MYSQL_DATABASE=step3
MYSQL_USER=db_user
MYSQL_PASSWORD=password

# REDIS関係
REDIS_PORT=6379
REDIS_PASSWORD=password

# Mail <-ここ
SMTP_USER=smtpuser
SMTP_PASSWORD=password
```

次にsendmailの役割を担っているssmtp.confにもSMTP Authの設定を追記します。
ちなみに、直接記述していますが、環境変数で指定ができるといいんですけど、いい方法はないでしょうか？
まぁ、最終手段として、.envを見てssmtp.confを生成するスクリプトを作成すればよいのですが。。。

```conf:app/ssmtp.conf
root=postmaster
mailhub=maildev:25
hostname=app
FromLineOverride=YES

AuthUser=smtpuser
AuthPass=password
AuthMethod=LOGIN

```

最後に、サンプルファイルであるindex.phpのSMTP送信部分を書き換えます。
sendmailの方は、SMTP Authをssmtpが対応してくれましたので、修正はありません。

```php:data/html/index.php
        use PHPMailer\PHPMailer\PHPMailer;
        use PHPMailer\PHPMailer\Exception;
        
        // Load Composer's autoloader
        require 'vendor/autoload.php';
        
        // Instantiation and passing `true` enables exceptions
        $mail = new PHPMailer;
        
        try {
            //Server settings
            echo '<pre class="log">';
            echo 'SMTPでメール配信' . PHP_EOL;

            $mail->SMTPDebug = 2;                                       // Enable verbose debug output
            $mail->isSMTP();                                            // Set mailer to use SMTP
            $mail->Host       = 'maildev';  // Specify main and backup SMTP servers
            $mail->SMTPAuth   = true;                                   // Enable SMTP authentication
            $mail->Username   = getenv('SMTP_USER');                     // SMTP username
            $mail->Password   = getenv('SMTP_PASSWORD');                               // SMTP password
            $mail->SMTPSecure = false;                                  // Enable TLS encryption, `ssl` also accepted
            $mail->SMTPAutoTLS = false;
            $mail->Port       = 25;                                    // TCP port to connect to
        
            //Recipients
            $mail->setFrom('from@example.com', mb_encode_mimeheader('日本語送信者名SMTP AUTH'));
            $mail->addAddress('smtp@example.net', mb_encode_mimeheader('日本語受信者名SMTP AUTH'));     // Add a recipient
```

# テスト

127.0.0.1にアクセスすると、SMTP/Sendmailでメールが1通ずつ送信されます。
127.0.0.1:8025にアクセスをして、2通のメールの受信ができればOKです。

![2019-06-16_10h33_35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/133291/46ca837d-33a7-581c-c454-4f6bedaa1837.png)


# まとめ

これで一般的なメールのテストに対応ができると思います。