SendGrid を Mailpit で確認する


# やりたいこと

SendGrid を使ったシステムがいくつかあるのですが、開発環境でのテストやシミュレートをうまくやりたいな、とずっと思っていました。

できれば UI 部分は Mailpit を使いたい。
でもプログラムは可能な限り修正したくない。たとえば開発環境だけは SendGrid ではなく SMTP 送信にする、というのは避けたかったのです。

https://mailpit.axllent.org/

# できた

[sendgrid-dev](https://github.com/yKanazawa/sendgrid-dev) は SendGrid API を受け取り、SMTPサーバーにメール送信する Go プログラムです。

SendGrid ではなく、この sendgrid-dev にメール送信 API をなげるようにすれば、sendgrid-dev が SMTP サーバー( Mailpit) にメールを送ります。私は Mailpit のウェブUIでメールを確認できます。

```Dockerfile:dockerfiles/sendgrid/Dockerfile
FROM golang:1.21-bullseye

# 作業ディレクトリを設定
WORKDIR /app

# 必要なパッケージをインストール
RUN apt-get update && apt-get install -y \
    git \
    && rm -rf /var/lib/apt/lists/*

# sendgrid-dev リポジトリをクローン
RUN git clone https://github.com/yKanazawa/sendgrid-dev.git .

# 依存関係をダウンロード
ENV GOPROXY=https://goproxy.io,direct
RUN go mod download -x

# ビルド
RUN env GOOS=linux GOARCH=amd64 go build -o sendgrid-dev main.go

# 実行コマンドを設定
CMD ["./sendgrid-dev"]
```

```yaml:docker-compose.yml
  sendgrid-dev:
    build: ./dockerfiles/sendgrid
    container_name: sendgrid
    hostname: sendgrid-server
    ports:
      - "3030:3030"
    environment:
      - SENDGRID_DEV_API_SERVER=:3030
      - SENDGRID_DEV_API_KEY=SG.xxxxx
      - SENDGRID_DEV_SMTP_SERVER=mail-server:1025
      - SENDGRID_DEV_SMTP_USERNAME=username
      - SENDGRID_DEV_SMTP_PASSWORD=password

  mailpit:
    image: axllent/mailpit
    container_name: mailpit
    hostname: mail-server
    restart: unless-stopped
    volumes:
      - ./data/mailpit:/data
    ports:
      - 8025:8025
      - 1025:1025
    environment:
      MP_MAX_MESSAGES: 5000
      MP_DATABASE: /data/mailpit.db
      MP_SMTP_AUTH_ACCEPT_ANY: 1
      MP_SMTP_AUTH_ALLOW_INSECURE: 1
```

### 確認用のコマンド

```bash:Dockerホストから
$ curl --request POST \
          --url http://localhost:3030/v3/mail/send \
          --header 'Authorization: Bearer SG.xxxxx' \
          --header 'Content-Type: application/json' \
          --data '{"personalizations": [{
        "to": [{"email": "to@example.com"}]}],
        "from": {"email": "from@example.com"},
        "subject": "Test Subject",
        "content": [{"type": "text/plain", "value": "Test Content"}]
      }'
```

```bash:他のDockerコンテナから
$ curl --request POST \
          --url http://sendgrid-server:3030/v3/mail/send \
          --header 'Authorization: Bearer SG.xxxxx' \
          --header 'Content-Type: application/json' \
          --data '{"personalizations": [{
        "to": [{"email": "to@example.com"}]}],
        "from": {"email": "from@example.com"},
        "subject": "Test Subject",
        "content": [{"type": "text/plain", "value": "Test Content"}]
      }'
```

### Mailpit での確認

![すてき！](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2664828/30c872ee-cbee-188d-53d0-eb1ca118b28c.png)


# 調査経緯

### 問題意識にあった記事をみつける

あるとき以下の記事をみつけました。

https://engineer.blog.lancers.jp/docker/sendgrid-maildev/

冒頭の問題意識をずっともっていた私はすぐに読んでみました。

この方と問題意識は同じでしたし、Dockerイメージまで公開されていたので大変うれしかったのですが、その DockerイメージにはメールウェブUI に Maildev というのが使われていました。

Mailpit がいいなぁ、Mailpit が今はお気に入りなんだよなぁ

と思いました。

よく読んでみますと、

* SendGrid API の受け口は sendgrid-dev
* SMTP の受け口とメール一覧のUIは Maildev

と明確に分離されていましたので、sendgrid-dev のみの Dockerイメージを作ればいいのだな、と思いました。

### sendgrid-dev の Dockerイメージを作る

もうゼロから Dockerfile をつくるの、面倒になりました。perplexity.ai に聞いて作りました。

```Dockerfile:dockerfiles/sendgrid/Dockerfile（perplexity.aiによる提案）
# Golang の公式イメージを使用（1.21以上）
FROM golang:1.21-bullseye

# 作業ディレクトリを設定
WORKDIR /app

# 必要なパッケージをインストール
RUN apt-get update && apt-get install -y \
    git \
    && rm -rf /var/lib/apt/lists/*

# sendgrid-dev リポジトリをクローン
RUN git clone https://github.com/yKanazawa/sendgrid-dev.git .

# 依存関係をダウンロード
RUN go mod download

# 実行コマンドを設定
CMD ["go", "run", "main.go"]
```

問題点は２つありました。

1. `docker-compose build` で、`go mod download` の途中でタイムアウトしてしまう場合がある
2. `docker-compose up` で、結構待たないと SendGrid API リクエストを受け付けてくれない

そこで、1. は GoProxy を変更する、2. はプログラムをビルドしておく、ということで対応しました。

```Dockerfile:dockerfiles/sendgrid/Dockerfile（完成版）
FROM golang:1.21-bullseye

# 作業ディレクトリを設定
WORKDIR /app

# 必要なパッケージをインストール
RUN apt-get update && apt-get install -y \
    git \
    && rm -rf /var/lib/apt/lists/*

# sendgrid-dev リポジトリをクローン
RUN git clone https://github.com/yKanazawa/sendgrid-dev.git .

# 依存関係をダウンロード
ENV GOPROXY=https://goproxy.io,direct
RUN go mod download -x

# ビルド
RUN env GOOS=linux GOARCH=amd64 go build -o sendgrid-dev main.go

# 実行コマンドを設定
#CMD ["go", "run", "main.go"]
CMD ["./sendgrid-dev"]
```

ありがとうございました！