1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

blastengineでList-Unsubscribeヘッダーを追加する方法(mailto+URL対応)

Posted at

メール配信の信頼性を高めるうえで欠かせないのが、List-Unsubscribeヘッダーです。主要なメールクライアントに「配信停止」リンクを自動表示させることで、ユーザーの離脱を円滑にし、送信者のレピュテーションを守ります。この記事では、その仕組みとBlastengineでの実装方法をわかりやすく紹介します。

List-Unsubscribeヘッダーとは

List-Unsubscribe は、メーリングリストやメールマガジンなどの大量送信メールにおいて、受信者が配信停止を申請するためのURLやメールアドレスを指定するメールヘッダーです。

主要なメールクライアント(Gmail、Outlook、Apple Mail等)は、このヘッダーが存在する場合、メール本文内のリンクとは別に、UI上に「購読解除」「配信停止」などのリンクを自動的に表示します。これにより、ユーザーは迷惑メール報告をせずに配信を停止できるため、送信元のレピュテーションが保護され、結果的にスパム判定を避けやすくなります。

List-Unsubscribeヘッダーの主な利点:

  • Gmail等の主要メールクライアントでワンクリック配信停止UIが表示される
  • ユーザーが「迷惑メール報告」ではなく「配信停止」を選ぶため、送信者レピュテーションが維持される
  • RFC 2369、RFC 8058に準拠した標準的な実装により、スパムフィルターの評価が向上する
  • メール配信サービスによっては、List-Unsubscribeヘッダーの設定が推奨または必須となっている

実装の基本形(mailto+URL併用)

RFC 8058では、List-Unsubscribe ヘッダーに mailto:https: の両方を併記することが推奨されています。これにより、メールクライアントは利用可能な方式を選択して配信停止機能を提供できます。

基本的なヘッダー構文:

List-Unsubscribe: <mailto:unsubscribe@example.com?subject=unsubscribe>, <https://example.com/unsubscribe?id=12345>

重要なポイント:

  • 各URLは < > で囲む必要がある
  • 複数のURLはカンマ , で区切る
  • mailto: スキームでは、件名や本文をクエリパラメータで指定可能(例:?subject=unsubscribe&body=Please%20remove
  • https: スキームでは、ユーザー識別のためのトークンやIDをクエリパラメータに含める
  • URLエンコードを適切に行う(スペースは %20、日本語は UTF-8 エンコード)

List-Unsubscribe-Post ヘッダーの併用(RFC 8058):

Gmailなどの最新のメールクライアントは、ワンクリック配信停止のために List-Unsubscribe-Post ヘッダーも要求します。

List-Unsubscribe: <https://example.com/unsubscribe?id=12345>
List-Unsubscribe-Post: List-Unsubscribe=One-Click

List-Unsubscribe-Post ヘッダーが存在する場合、メールクライアントは指定されたURLに対してPOSTリクエストを送信し、ボディに List-Unsubscribe=One-Click を含めます。

Blastengine APIによる送信例(curl+Python SDK)

Blastengineは、日本国内向けに最適化されたメール配信APIサービスで、List-Unsubscribeヘッダーの指定が可能です。list_unsubscribe パラメータを使用して、List-Unsubscribeヘッダーを簡単に追加できます。

API認証方法

Blastengine APIはBearer認証を使用します。リクエストには、ログインIDとAPIキーから生成したBearerトークンが必要です。

Bearerトークンの生成手順:

  1. ログインIDとAPIキーを連結
  2. SHA256でハッシュ化
  3. 小文字に変換
  4. Base64でエンコード

Pythonでのトークン生成例:

import hashlib
import base64

def generate_bearer_token(login_id, api_key):
    # 1. ログインIDとAPIキーを連結
    combined = login_id + api_key

    # 2. SHA256でハッシュ化
    hashed = hashlib.sha256(combined.encode()).hexdigest()

    # 3. 小文字に変換(hexdigest()は既に小文字)
    hashed_lower = hashed.lower()

    # 4. Base64でエンコード
    token = base64.b64encode(hashed_lower.encode()).decode()

    return token

# 使用例
login_id = "YOUR_LOGIN_ID"
api_key = "YOUR_API_KEY"
bearer_token = generate_bearer_token(login_id, api_key)
print(f"Bearer Token: {bearer_token}")

curlによる送信例

# 事前にBearerトークンを生成しておく
BEARER_TOKEN="YOUR_BEARER_TOKEN"

curl -X POST https://app.engn.jp/api/v1/deliveries/transaction \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer ${BEARER_TOKEN}" \
  -d '{
    "to": "user@example.com",
    "subject": "メールマガジン - 2025年1月号",
    "encode": "UTF-8",
    "text_part": "こんにちは、\n\n2025年1月号のメールマガジンをお届けします。\n\n配信停止: https://example.com/unsubscribe?id=12345",
    "from": {
      "email": "noreply@example.com",
      "name": "Example Corp"
    },
    "list_unsubscribe": {
      "mailto": "mailto:unsubscribe@example.com?subject=unsubscribe",
      "url": "https://example.com/unsubscribe?id=12345"
    }
  }'

Python SDKによる送信例

Blastengineの公式Python SDKを使用する場合、SDKが自動的にBearerトークンを生成して認証を処理します。

from blastengine.Client import Blastengine
from blastengine.Transaction import Transaction

# Blastengineクライアントの初期化
# SDKが内部でBearerトークンを生成します
Blastengine('YOUR_USER_NAME', 'YOUR_API_KEY')

def send_newsletter_with_unsubscribe(to_email, user_id):
    # 配信停止URL(ユーザーIDごとに動的に生成)
    unsubscribe_url = f"https://example.com/unsubscribe?id={user_id}"

    # Transactionインスタンスを作成
    transaction = Transaction()

    # メール内容を設定
    transaction.subject('メールマガジン - 2025年1月号')
    transaction.text_part(f'''こんにちは、

2025年1月号のメールマガジンをお届けします。

...本文...

配信停止: {unsubscribe_url}

--
Example Corp
''')
    transaction.from_address('noreply@example.com', 'Example Corp')
    transaction.to(to_email)

    # List-Unsubscribeヘッダーの指定
    transaction.unsubscribe(
        url=unsubscribe_url,
        email='unsubscribe@example.com'
    )

    # メール送信
    try:
        delivery_id = transaction.send()
        print(f"送信成功: {delivery_id}")
        return delivery_id
    except Exception as e:
        print(f"送信エラー: {e}")
        raise

# 使用例
send_newsletter_with_unsubscribe(
    to_email="user@example.com",
    user_id="12345"
)

HTML形式のメールを送信する場合

def send_html_newsletter_with_unsubscribe(to_email, user_id):
    unsubscribe_url = f"https://example.com/unsubscribe?id={user_id}"

    html_body = f"""
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
</head>
<body>
    <h1>メールマガジン - 2025年1月号</h1>
    <p>こんにちは、</p>
    <p>2025年1月号のメールマガジンをお届けします。</p>
    <!-- 本文 -->
    <hr>
    <p style="font-size: 12px; color: #666;">
        このメールの配信を停止したい場合は、
        <a href="{unsubscribe_url}">こちら</a>からお手続きください。
    </p>
</body>
</html>
    """

    text_body = f"""
こんにちは、

2025年1月号のメールマガジンをお届けします。

配信停止: {unsubscribe_url}
    """

    # Transactionインスタンスを作成
    transaction = Transaction()

    # メール内容を設定
    transaction.subject('メールマガジン - 2025年1月号')
    transaction.text_part(text_body)
    transaction.html_part(html_body)
    transaction.from_address('noreply@example.com', 'Example Corp')
    transaction.to(to_email)

    # List-Unsubscribeヘッダーの指定
    transaction.unsubscribe(
        url=unsubscribe_url,
        email='mailto:unsubscrib@example.com?subject=unsubscribe'
    )

    # メール送信
    try:
        delivery_id = transaction.send()
        print(f"送信成功: {delivery_id}")
        return delivery_id
    except Exception as e:
        print(f"送信エラー: {e}")
        raise

Blastengine SDKのポイント:

  • unsubscribe() メソッドで urlemail の両方を指定可能
  • メソッドチェーン方式で直感的にメール内容を設定できる
  • UTF-8エンコードに対応しており、日本語メールの送信が容易
  • DKIM署名が自動的に適用される(設定済みの場合)
  • List-Unsubscribeヘッダーも署名対象に含まれるため、改ざん検知が可能
  • unsubscribe() を指定すると、List-Unsubscribe-Postヘッダーも自動的に追加される

DKIM署名とURLエンコードの注意点

List-Unsubscribeヘッダーを実装する際には、DKIM署名とURLエンコードに関する注意が必要です。

DKIM署名における注意点

DKIM(DomainKeys Identified Mail)は、メールの送信元ドメインを認証し、メールが改ざんされていないことを証明する仕組みです。DKIM署名では、署名対象となるヘッダーを h= タグで指定します。

List-Unsubscribeヘッダーを署名対象に含める理由:

  • ヘッダーが署名対象に含まれていないと、中間サーバーで改ざんされるリスクがある
  • Gmailなどの主要メールプロバイダーは、署名されていないList-Unsubscribeヘッダーを信頼しない場合がある
  • 署名によって、配信停止URLの正当性が保証される

DKIM署名の設定例(OpenDKIMの設定ファイル):

# /etc/opendkim.conf
SignHeaders    From,To,Subject,Date,Message-ID,List-Unsubscribe,List-Unsubscribe-Post

Blastengine APIを使用する場合、DKIM署名は自動的に適用され、headers パラメータで指定したカスタムヘッダーも署名対象に含まれるため、特別な設定は不要です。

URLエンコードの注意点

List-Unsubscribeヘッダーに含めるURLには、適切なURLエンコードが必要です。エンコードを忘れると、メールクライアントがURLを正しく解析できず、リンクが機能しなくなります。

エンコードが必要な文字:

文字 エンコード後 用途
スペース %20 件名や本文にスペースを含める場合
& %26 クエリパラメータの区切りと混同されるため
= %3D クエリパラメータの値内で使用する場合
? %3F URL内で2つ目以降の ? を使う場合
日本語 UTF-8エンコード 例: 配信停止%E9%85%8D%E4%BF%A1%E5%81%9C%E6%AD%A2

誤った例(エンコードなし):

List-Unsubscribe: <mailto:unsubscribe@example.com?subject=配信停止>

このまま送信すると、日本語部分が正しく処理されず、リンクが機能しません。

正しい例(URLエンコード済み):

from urllib.parse import quote

subject = quote("配信停止")
# 結果: '%E9%85%8D%E4%BF%A1%E5%81%9C%E6%AD%A2'

mailto_url = f"mailto:unsubscribe@example.com?subject={subject}"
# 結果: mailto:unsubscribe@example.com?subject=%E9%85%8D%E4%BF%A1%E5%81%9C%E6%AD%A2

クエリパラメータ内の特殊文字のエンコード例:

from urllib.parse import quote

# ユーザーIDに特殊文字が含まれる場合
user_id = "user@example.com"
encoded_user_id = quote(user_id, safe='')
# 結果: 'user%40example.com'

unsubscribe_url = f"https://example.com/unsubscribe?email={encoded_user_id}"
# 結果: https://example.com/unsubscribe?email=user%40example.com

注意: urllib.parse.quote() のデフォルトでは /: などの一部の文字はエンコードされません。クエリパラメータの値として使用する場合は、safe='' を指定してすべての特殊文字をエンコードすることを推奨します。

まとめ

List-Unsubscribeヘッダーは、わずか1行のヘッダー設定ですが、メール配信の成功率と送信者レピュテーションに大きな影響を与えます。

  1. List-Unsubscribeヘッダーの重要性
    • Gmailなど主要メールクライアントで自動的に「配信停止」リンクが表示される
    • ユーザーが「迷惑メール報告」ではなく「配信停止」を選ぶため、送信者レピュテーションが保護される
    • スパムフィルターの評価が向上し、メール到達率が改善される
  2. 実装の基本
    • RFC 8058に準拠した mailto:https: の併用が推奨される
    • Gmailユーザー向けには List-Unsubscribe-Post ヘッダーが必須
    • URLエンコードを適切に行い、特殊文字や日本語を正しく処理する
  3. Blastengine SDKの利点
    • unsubscribe() メソッドで簡単にList-Unsubscribeヘッダーを追加できる
    • DKIM署名が自動的に適用され、ヘッダーの改ざん検知が可能
    • UTF-8エンコードに対応し、日本語メールの送信が容易
    • REST APIとPython SDKの両方でサポートされ、開発が柔軟

メールマガジンやトランザクションメールを送信する際、List-Unsubscribeヘッダーの設定は必須と考えるべきです。この1行の設定により、ユーザーエクスペリエンスが向上し、送信者レピュテーションが維持され、最終的にメール配信の成功率が大幅に改善されます。

Blastengine APIを使用することで、この重要なヘッダーを簡単に設定でき、DKIM署名による改ざん検知も自動的に行われます。ぜひ、この記事で紹介したコード例を参考に、List-Unsubscribeヘッダーを実装してみてください。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?