Published on

SendGrid のメールを Gmail 側でグループ化させずスレッドを分ける方法

Authors

運営サイトの問い合わせフォーム等から送られたメールを Gmail で受信すると、メールのスレッドが一つにまとめられてしまうことが多いと思います。この記事ではスレッドを分けて受信するための方法について書こうと思います。この記事では Nest.js x SendGrid を利用していますが、他のシステムでも基本的には同様だと思います。

Gmail のメールがグループ化される条件

まず、Gmail でメールがグループ化される条件について理解しておきましょう。Google の公式サイトによると、以下の条件を満たすとメールが自動的にグループ化されるようです。

  • 受信者、送信者、件名が以前のメールと同じである
  • 参照ヘッダーの ID が以前のメールと同じである
  • 以前のメールから 1 週間以内に送信されている

解決案

Gmail でグループ化される条件から、解決策として以下 2 つの方法が考えられます。

案 1:ヘッダーの In-Reply-To に値を設定する

この方法では、SendGrid のメール送信時にヘッダーの'In-Reply-To'に一意の値を設定します。これにより、Gmail はその値を元に新しいスレッドを作成します。

案 2:タイトルに一意の文字列を入れる

もう一つの方法としては、メールの件名に一意の文字列(例えば、タイムスタンプやランダムな文字列など)を追加する方法があります。これにより、Gmail はそれぞれのメールを異なるスレッドと認識し、分けて表示します。

案 1:SendGrid で In-Reply-To ヘッダーを追加する方法

ここでは、Nest.js で SendGrid を使用してメールを送信し、その際に'In-Reply-To'ヘッダーに一意の値を設定する方法をご紹介します。

//mailer.service.ts
import { InternalServerErrorException } from '@nestjs/common';
import { v4 as uuidv4 } from 'uuid';
import * as SendGrid from '@sendgrid/mail';

async send(mail: SendGrid.MailDataRequired) {
  try {
    await SendGrid.send(mail)
  } catch (error: any) {
    throw new InternalServerErrorException("SendGrid Error")
  }
}

async sendContact(dto: ContactDto) {
  const messageId = uuidv4()
  const msg = {
    to: "iwata@example.com",
    from: "noreply@example.com",
    subject: "お問合せがありました",
    text: "メール本文",
    headers: {
      "In-Reply-To": `<${messageId}@example.com>`,
    },
  }
  await this.send(msg)
}

ここでは、uuid ライブラリの uuidv4 関数を使用して一意のメッセージ ID を生成し、それを SendGrid 送信時に'In-Reply-To'ヘッダーとして設定しています。

uuidv4 については、こちらはほぼ確実に一意な値を生成するための関数です。UUID v4 は、乱数生成器を使用して生成されるバージョンで、他のバージョンの UUID よりも一意性が高くなっています。

案 2:タイトルに一意の文字列を入れる実装例

基本的に案 1 で良いと思いますが、一応こちらの方法についても書いておきます。 手順としては、一意の文字列として現在の日付と時間を分単位で取得し、それをメールの件名に付け加えるだけです。

yarn add date-fns
//mailer.service.ts
import { InternalServerErrorException } from '@nestjs/common';
import { v4 as uuidv4 } from 'uuid';
import * as SendGrid from '@sendgrid/mail';

async send(mail: SendGrid.MailDataRequired) {
  try {
    await SendGrid.send(mail)
  } catch (error: any) {
    throw new InternalServerErrorException("SendGrid Error")
  }
}

async sendContact(dto: ContactDto) {
  const messageId = uuidv4()
  const text = "Mail content"
  const uniqueString = format(new Date(), 'yyyyMMddHHmm')
  const msg = {
    to: 'iwata@example.com',
    from: 'noreply@example.com',
    subject: `お問い合わせがありました ${uniqueString}`, // 一意の文字列を件名に追加
    text: 'メール本文',
  }
  await this.send(msg)
}

uniqueStringは、2023 年 7 月 15 日 12 時 25 分にメールを送信した場合、生成される文字列は「202307151225」となります。1 分以内にメールが何通も届かないのであればこれで大丈夫でしょう。それ以上くるなら秒単位で分けることになります。

まとめ

このように SendGrid 等でメールを送信する際に、ヘッダーや件名を工夫することで、Gmail におけるメールのスレッド分けを制御することが可能になります。簡単なことではありますが日本語では情報がなかったので記事にしておきました。どなたかの参考になれば幸いです。