SendGridでいい感じにメールの配信停止グループを管理する

今、[個人で開発しているサービス](https://anymake.app/) にメールの配信基盤を整えようと思って色々調べていたので、その結果わかったことを備忘録としてまとめておきます。

## メールの配信停止設定で最低限やっておきたいこと

メールの配信設定を行うにあたって、以下の項目が守られていることが個人的に望ましかったです。

1. 簡単にメールを配信停止できること
2. 自分のサービスとメール配信サービスでメールの配信停止設定を共有できること

### 1. 簡単にメールを配信停止できること

まず、送られるメールは簡単に配信停止できるようにすべきです。[配信停止のベストプラクティスと、SendGrid の便利な機能](https://sendgrid.kke.co.jp/blog/?p=10712) にも以下のように書かれています。

> 1. 簡単に配信停止できるようにする

> 配信停止の手順が簡単であればあるほど、受信者と送信者、双方にとってメリットがあります。配信停止のボタンやリンクをどこに置くか決める時、隠すように配置してはいけません。また、リンクがきちんと機能するか複数回チェックしましょう。リンクをフッタに配置するケースをよく見かけますが、どこに配置したとしても、見つけやすくわかりやすくする必要があります。

サービス運営側としては宣伝のためメールを送りたいと思うので、できればメールの配信を続けたいかと思いますが、そのあまり配信停止の設定が不便だとユーザーからの信用を損ないますし、UX も悪いです。

### 2. 自分のサービスとメール配信サービスでメールの配信停止設定を共有できること

SendGrid にて、メールの配信停止を行う手順は [メールの種類ごとに配信停止を管理する \- ドキュメント \| SendGrid](https://sendgrid.kke.co.jp/docs/Tutorials/A_Transaction_Mail/group_unsubscribe.html) にもあるように、わりと簡単に行えそうでした。

しかし、実際にメールの配信設定を管理する際は、自分で作っているサービス側でもメールの配信設定ができる必要があります。

例えば、SendGrid 側でメールの配信を停止した場合、自分で作っているサービス側のメール配信設定もオフになっているべきです。この実装をどのようにすればよいか、あまりメール配信に慣れていない自分は調べるのに苦労しました。

## メールの配信停止設定を管理する方法

いろいろ試した結果、SendGrid の [Suppressions](https://sendgrid.kke.co.jp/docs/API_Reference/Web_API_v3/Suppression_Management/suppressions.html) の API を利用すると、やりたいことが実現できそうでした。

SendGrid ではメールの配信停止グループを設定できるのですが、こちらの API を使うことで特定のメールアドレスと配信停止グループに対して

- メールの配信設定の取得
- メールの配信停止
- メールの配信停止の取り消し

ができます。

あとは、自分のサービス上でこの API を呼び出してあげれば良いです。自分は Node.js を使っていたので、[sendgrid/sendgrid-nodejs](https://github.com/sendgrid/sendgrid-nodejs) でのコードを参考までに載せておきます。

```ts:メールの配信設定の取得
import client from "@sendgrid/client";
import RequestOptions from "@sendgrid/helpers/classes/request";

client.setApiKey("SG.xxxxx.yyyyy");
(async () => {
  const request = {} as RequestOptions;
  const email = "test@example.com";
  request.method = "GET";
  request.url = `/v3/asm/suppressions/${email}`;
  const [response] = await client.request(request);
  console.log(response.body);
})();
```

```ts:メールの配信停止
import client from "@sendgrid/client";
import RequestOptions from "@sendgrid/helpers/classes/request";

client.setApiKey("SG.xxxxx.yyyyy");
(async () => {
  const request = {} as RequestOptions;
  const email = "test@example.com";
  const groupId = 12345;
  const data = {
    recipient_emails: [email]
  };
  request.body = data;
  request.method = "POST";
  request.url = `/v3/asm/groups/${groupId}/suppressions`;
  const [response] = await client.request(request);
  console.log(response.body);
})();
```

```ts:メールの配信停止の取り消し
import client from "@sendgrid/client";
import RequestOptions from "@sendgrid/helpers/classes/request";

client.setApiKey("SG.xxxxx.yyyyy");
(async () => {
  const request = {} as RequestOptions;
  const email = "test@example.com";
  const groupId = 12345;
  request.method = "DELETE";
  request.url = `/v3/asm/groups/${groupId}/suppressions/${email}`;
  const [response] = await client.request(request);
  console.log(response.body);
})();
```

ちなみに、余談ですがメールの送信も以下のような感じでできます。

```ts
import sendgrid from "@sendgrid/mail";

sendgrid.setApiKey("SG.xxxxx.yyyyy");

const msg = {
  to: "test@example.com",
  from: "no-reply@example.com",
  subject: "Sending with Twilio SendGrid is Fun",
  html: `
    <html>
        <body>
            ここが本文です<br />
            <a href="<%asm_preferences_raw_url%>">配信停止を管理する</a><br />
        </body>
    </html>`,
  asm: { groupId: 12345 }
};
(async () => {
  try {
    await sendgrid.send(msg);
  } catch (error) {
    console.error(error);

    if (error.response) {
      console.error(error.response.body);
    }
  }
})();
```

これにより、自分のサービスの設定画面からメールの受信・停止設定を行うことができますし、送信したメールの「メール配信停止」リンクからメールの配信を停止した際も、自分のサービス側で設定を同期できます。

## おわりに

今回は SendGrid を利用しましたが、似たような API があるサービスであれば今回実現したかったことは実装できるかと思います。

ただ自分はあまりこの手のサービスを知らないので、もしおすすめのサービスをご存じの方がいらっしゃれば、ぜひコメント欄にて教えていただけますと嬉しいです！😄

---

というわけで、この記事で書いた内容をもとにメールの配信機能を実装してみました！

[メール通知機能を追加しました！｜AnyMake｜note](https://note.com/anymake/n/n4afde6762bbe)

もしよろしければ、[AnyMake](https://anymake.app) もチェックしてみてください👍