Laravel 5.6:如何发送电子邮件,客户会将它们显示为线程/对话?
Laravel 5.6: How-to send emails, that clients will show them as threads / conversations?
我的 Laravel 应用程序包含一个票务系统,它正在发送电子邮件通知。
所有电子邮件都像这样构建和发送:
public function build()
{
$email_from_name = "Support - " . config('app.name');
$subject = "[" . $this->ticket->id . "] " . $this->ticket->subject . " - " . config('app.name');
return $this->from('support@example.com', $email_from_name)
->subject($subject)
->markdown('emails.customer.ticket.comment_added')
->with([
'nickname' => $this->user->nickname,
'ticket_id' => $this->ticket->id,
'ticket_subject' => $this->ticket->subject,
'ticket_text' => $this->ticket_comments->text,
]);
}
不幸的是,当我收到多封此类电子邮件时,没有电子邮件客户端(Outlook、Thunderbird、Roundcube 等)将这些电子邮件显示为线程/对话。所有客户端都将每封电子邮件显示为 "new email" 线程/对话。
什么规定,有些电子邮件是一个线程/会话,有些不是?我如何告诉我的 Laravel 应用程序,这些电子邮件是一个线程/会话?
我想,它只需要是相同的电子邮件主题,但它不起作用。
主题由电子邮件客户端自动创建。
你什么也做不了
感谢@Yeeooow 提供有关 RFC 2822
标准的信息:The References and In-Reply-To headers must be set in compliance with the RFC 2822 standard.
根据这些信息,我检查了一些其他的电子邮件主题/对话。所有这些都以相同的方式使用了提到的 References
和 In-Reply-To
headers。有了这些信息,我开始开发以存档相同的结果。
由于我们需要参考旧邮件,我们需要一个 table,我们可以在其中存储每封已发送电子邮件的 Message-ID
。我在我的案例中创建了这个 table:
// Table: ticket_message_ids
public function up()
{
Schema::create('ticket_message_ids', function (Blueprint $table) {
$table->increments('id');
$table->integer('ticket_id')->unsigned();
$table->integer('reference_id')->unsigned(); // Optional; You may remove it or make it ->nullable()
$table->string('message_id');
$table->timestamps();
});
}
有了这个 table,我们可以存储每封已发送电子邮件的 Message-ID
,并可以参考它属于哪个工单。这将有助于我们稍后也仅获取与此工单相关的 Message-ID
s - 否则,我们将在同一电子邮件线程中混淆不同的工单历史记录。
在reference_id
字段中,您可以选择存储任务的关联ID:
- 已添加工单文本
- 已执行票证操作(例如支持者、优先级、头衔或状态已更改)
在您的可邮寄邮件中(例如 app\Mail\TicketTextAdded.php
),您现在可以将代码部分 $this->withSwiftMessage() {}
添加到您的 build()
函数中以捕获此新邮件的当前 Message-ID
之前的电子邮件和对所有其他电子邮件的引用以及存储新的 Message-ID`:
public function build()
{
$email_from_name = "Support - " . config('app.name');
$subject = "[" . $this->ticket->id . "] " . $this->ticket->subject . " - " . config('app.name');
$email = $this->from('support@example.com', $email_from_name)
->subject($subject)
->markdown('emails.customer.ticket.comment_added')
->with([
'nickname' => $this->user->nickname,
'ticket_id' => $this->ticket->id,
'ticket_subject' => $this->ticket->subject,
'ticket_text' => $this->ticket_comments->text,
]);
// Access underlaying Swift message
$this->withSwiftMessage(function ($swiftmessage) {
// Get all Message-IDs associated to this specific ticket
$message_ids = TicketMessageIds::where('ticket_id', '=', $this->ticket->id)->get();
// Build RFC2822 conform 'References' header
// Example: 'References: <4bcf5a806f795b86fb2ba7238c78983c@swift.generated> <ab7898365c4aa91bfe010d4e1e8da377@swift.generated>'
$header_references = "";
foreach($message_ids as $message_id) {
if(empty($header_references)) {
$header_references = $message_id->message_id;
} else {
$header_references = $header_references . " " . $message_id->message_id;
}
}
// Build RFC2822 conform 'In-Reply-To' header
// Example: 'In-Reply-To: <ab7898365c4aa91bfe010d4e1e8da377@swift.generated>'
$header_in_reply_to = TicketMessageIds::where('ticket_id', '=', $this->ticket->id)->orderBy('id', 'DESC')->get(['message_id'])->first()->message_id;
// Add required custom headers with above values
$headers = $swiftmessage->getHeaders();
// 'X-Mailer' header is not required for this purpose
// This header sets only a name for the client, which sent this message (typical values: Outlook 2016, PHPMailer v6.0.5,...)
$headers->addTextHeader('X-Mailer', config('app.name') . ' (' . config('app.url') . ')');
if(!empty($header_references)) {
$headers->addTextHeader('References', $header_references);
}
$headers->addTextHeader('In-Reply-To', $header_in_reply_to);
TicketMessageIds::create([
'ticket_id' => $this->ticket->id,
'message_id' => '<'.$swiftmessage->getId().'>'
]);
});
return $email;
}
仅供参考:您也可以在此处更改 Message-ID
,我们已在其中设置了自定义 headers,但这需要遵守相关的 RFC 文档:
$msgId = $swiftmessage->getHeaders()->get('Message-ID');
$msgId->setId(time() . '.' . uniqid('thing') . '@example.org');
更多信息:https://swiftmailer.symfony.com/docs/headers.html#id-headers
希望我可以用这些信息帮助其他人。 :)
我的 Laravel 应用程序包含一个票务系统,它正在发送电子邮件通知。
所有电子邮件都像这样构建和发送:
public function build()
{
$email_from_name = "Support - " . config('app.name');
$subject = "[" . $this->ticket->id . "] " . $this->ticket->subject . " - " . config('app.name');
return $this->from('support@example.com', $email_from_name)
->subject($subject)
->markdown('emails.customer.ticket.comment_added')
->with([
'nickname' => $this->user->nickname,
'ticket_id' => $this->ticket->id,
'ticket_subject' => $this->ticket->subject,
'ticket_text' => $this->ticket_comments->text,
]);
}
不幸的是,当我收到多封此类电子邮件时,没有电子邮件客户端(Outlook、Thunderbird、Roundcube 等)将这些电子邮件显示为线程/对话。所有客户端都将每封电子邮件显示为 "new email" 线程/对话。
什么规定,有些电子邮件是一个线程/会话,有些不是?我如何告诉我的 Laravel 应用程序,这些电子邮件是一个线程/会话?
我想,它只需要是相同的电子邮件主题,但它不起作用。
主题由电子邮件客户端自动创建。 你什么也做不了
感谢@Yeeooow 提供有关 RFC 2822
标准的信息:The References and In-Reply-To headers must be set in compliance with the RFC 2822 standard.
根据这些信息,我检查了一些其他的电子邮件主题/对话。所有这些都以相同的方式使用了提到的 References
和 In-Reply-To
headers。有了这些信息,我开始开发以存档相同的结果。
由于我们需要参考旧邮件,我们需要一个 table,我们可以在其中存储每封已发送电子邮件的 Message-ID
。我在我的案例中创建了这个 table:
// Table: ticket_message_ids
public function up()
{
Schema::create('ticket_message_ids', function (Blueprint $table) {
$table->increments('id');
$table->integer('ticket_id')->unsigned();
$table->integer('reference_id')->unsigned(); // Optional; You may remove it or make it ->nullable()
$table->string('message_id');
$table->timestamps();
});
}
有了这个 table,我们可以存储每封已发送电子邮件的 Message-ID
,并可以参考它属于哪个工单。这将有助于我们稍后也仅获取与此工单相关的 Message-ID
s - 否则,我们将在同一电子邮件线程中混淆不同的工单历史记录。
在reference_id
字段中,您可以选择存储任务的关联ID:
- 已添加工单文本
- 已执行票证操作(例如支持者、优先级、头衔或状态已更改)
在您的可邮寄邮件中(例如 app\Mail\TicketTextAdded.php
),您现在可以将代码部分 $this->withSwiftMessage() {}
添加到您的 build()
函数中以捕获此新邮件的当前 Message-ID
之前的电子邮件和对所有其他电子邮件的引用以及存储新的 Message-ID`:
public function build()
{
$email_from_name = "Support - " . config('app.name');
$subject = "[" . $this->ticket->id . "] " . $this->ticket->subject . " - " . config('app.name');
$email = $this->from('support@example.com', $email_from_name)
->subject($subject)
->markdown('emails.customer.ticket.comment_added')
->with([
'nickname' => $this->user->nickname,
'ticket_id' => $this->ticket->id,
'ticket_subject' => $this->ticket->subject,
'ticket_text' => $this->ticket_comments->text,
]);
// Access underlaying Swift message
$this->withSwiftMessage(function ($swiftmessage) {
// Get all Message-IDs associated to this specific ticket
$message_ids = TicketMessageIds::where('ticket_id', '=', $this->ticket->id)->get();
// Build RFC2822 conform 'References' header
// Example: 'References: <4bcf5a806f795b86fb2ba7238c78983c@swift.generated> <ab7898365c4aa91bfe010d4e1e8da377@swift.generated>'
$header_references = "";
foreach($message_ids as $message_id) {
if(empty($header_references)) {
$header_references = $message_id->message_id;
} else {
$header_references = $header_references . " " . $message_id->message_id;
}
}
// Build RFC2822 conform 'In-Reply-To' header
// Example: 'In-Reply-To: <ab7898365c4aa91bfe010d4e1e8da377@swift.generated>'
$header_in_reply_to = TicketMessageIds::where('ticket_id', '=', $this->ticket->id)->orderBy('id', 'DESC')->get(['message_id'])->first()->message_id;
// Add required custom headers with above values
$headers = $swiftmessage->getHeaders();
// 'X-Mailer' header is not required for this purpose
// This header sets only a name for the client, which sent this message (typical values: Outlook 2016, PHPMailer v6.0.5,...)
$headers->addTextHeader('X-Mailer', config('app.name') . ' (' . config('app.url') . ')');
if(!empty($header_references)) {
$headers->addTextHeader('References', $header_references);
}
$headers->addTextHeader('In-Reply-To', $header_in_reply_to);
TicketMessageIds::create([
'ticket_id' => $this->ticket->id,
'message_id' => '<'.$swiftmessage->getId().'>'
]);
});
return $email;
}
仅供参考:您也可以在此处更改 Message-ID
,我们已在其中设置了自定义 headers,但这需要遵守相关的 RFC 文档:
$msgId = $swiftmessage->getHeaders()->get('Message-ID');
$msgId->setId(time() . '.' . uniqid('thing') . '@example.org');
更多信息:https://swiftmailer.symfony.com/docs/headers.html#id-headers
希望我可以用这些信息帮助其他人。 :)