Site cover image
Post title iconSendGrid APIでGmailメール送信者ガイドライン「List-Unsubscribe」ヘッダーに対応する

この2月から、Gmailに大量のメールを配信するメール送信者は、受信者が簡単に配信停止できるようにしなければならなくなりました。いわゆるワンクリック解除と呼ばれているものです。

原文は下記のようになっています。

重要: Gmail では 2024 年 2 月以降、Gmail アカウントに 1 日あたり 5,000 件以上のメールを送信する送信者に対し、1. 送信メールを認証すること、2. 未承諾のメールまたは迷惑メールを送信しないようにすること、3. 受信者がメールの配信登録を容易に解除できるようにすること、の 3 つが義務付けられます。

この記事では、上記3の「受信者がメールの配信登録を容易に解除できるようにすること」についてメール配信サービスSendGrid APIを使用した対応例を紹介します。

ワンクリック解除の仕組み

配信メールのワンクリック解除を受信者に提供するためには、2つのメールヘッダーに対応する必要があります。List-UnsubscribeヘッダーとList-Unsubscribe-Postヘッダーです。

このうちList-Unsubscribe-Postヘッダーには固定の値List-Unsubscribe=One-Clickを設定します。List-Unsubscribeヘッダーの値にはPOSTリクエストを送るURLを設定します。

メールにこれらのヘッダーを設定することで、Gmail側では下記のように「メーリングリストの登録解除」というリンクが表示されるようになります。受信者がリンクをクリックするとList-Unsubscribeヘッダーに設定されたURLにPOSTリクエストが送られるというわけです。

Image in a image block
2つのヘッダーを登録するとGmail側で「メーリングリストの登録解除」リンクが表示されるようになる

ただし、2つのヘッダーを設定したからといって必ずしもリンクが表示されるわけではないようです。SendGridのドキュメントでは下記のように説明されています。

配信停止用リンクが表示されるのはレピュテーションの高い送信者が送った場合のみですが、全ての送信者がList-Unsubscribeを利用するよう推奨しています。

小規模サービスではレピュテーションが低いことが考えられるため「メーリングリストの登録解除」リンクが表示されない可能性があります。実際に、私が個人で運営しているサービスでもリンクは表示されませんでした。

Node.jsでの実装例

SendGrid APIクライアントを使ってList-UnsubscribeヘッダーとList-Unsubscribe-Postヘッダーを付加する例と、POSTリクエストを受けるWebエンドポイントの実装例を紹介します。例としてNode.jsを使用します。

メッセージにヘッダーを追加する例

SendGrid APIのNode.jsクライアントを使って、メールにカスタムヘッダーとしてList-UnsubscribeヘッダーとList-Unsubscribe-Postヘッダーを付加する例を見てみましょう。

下記はダイナミックテンプレートを使用している例です。ダイナミックテンプレートを利用していない場合はsubjectなど追加する必要があることにご注意ください。

const sendgrid = require('@sendgrid/mail');
sendgrid.setApiKey(process.env.SENDGRID_API_KEY);

const hash = 'abc...';
const unsubscribeURL = new URL(`/unsubscribe/${hash}`, 'https://example.com');

const message = {
  to: toEmail,
  from: {
    name: name,
    email: fromEmail,
  },
  templateId,
  headers: {
    'List-Unsubscribe-Post': 'List-Unsubscribe=One-Click',
    'List-Unsubscribe': `<${unsubscribeURL.toString()}>`,
  },
};

await sendgrid.send({
  ...message,
  dynamicTemplateData: {
    hash,
  },
});

配信停止用のWebエンドポイントは https://example.com/unsubscribe/<hash> としています。

hashはユーザーごとに違った値を生成しデータベース等に保存しておきます。配信停止処理の際にhashを元にユーザーを検索するからです。

メールのフッター部分に「配信停止」リンクを付加することが一般的であるため、hashパラメータをダイナミックテンプレートにも渡しています。テンプレート側ではURLの一部を{{hash}}のようにしておくことで、渡ってきたhashパラメータで置き換えることができます。

Gmailの「メーリングリストの登録解除」リンクが押されるとList-Unsubscribeヘッダーで指定したURLに対して下記のようなPOSTリクエストが送られます。

POST /unsubscribe/abc... HTTP/1.1
Host: solarmora.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 26
List-Unsubscribe=One-Click

Webエンドポイント側では、このPOSTリクエストをもとにメール配信停止の処理を行います。

Webエンドポイントの実装例

Webエンドポイントではhashパラメータを元にユーザーを検索し、通知を送らないようにデータを更新にします。

Gmailの「メーリングリストの登録解除」リンクが押されたときはPOSTリクエストが送られるのに対して、メールのフッター部分に設置した「配信停止」リンクではGETリクエストによる遷移となります。

後者ではPOSTリクエストを送るためのフォームを表示し、POSTリクエストのエンドポイントは前者と後者で共通化してしまうと良いでしょう。下記はPOSTリクエストを処理するエンドポイントの実装例です。

const user = await getUserByHash(hash)
if (!user) {
  throw new Error('invalid hash')
}
  
if (request.method === 'POST') {
  await turnNotificationOff(user.id)

  if (Astro.request.headers.get('List-Unsubscribe-Post')) {
    return new Response(null, { status: 200 })
  }
}

// Return HTML with the form

Gmailの「メーリングリストの登録解除」リンクが押された場合にはList-Unsubscribe-Postヘッダーがあるため単純に200 OKをレスポンスします。そうでない場合は、ユーザーがブラウザで遷移しフォームからPOSTリクエストを送ってきたと考えることができるので、配信停止完了を示すHTMLをレスポンスすると良いでしょう。

以上です。この記事では、Gmailの送信者ガイドラインのうち「受信者がメールの配信登録を容易に解除できるようにすること」についてメール配信サービスSendGrid APIを使用した対応例を紹介しました。


💕
記事が参考になったら少額を寄付いただけると励みになります。
Thank you!
Thank you!
URLをコピーしました

コメントを送る

コメントはブログオーナーのみ閲覧できます