Laravel 5.6:如何发送可被邮件客户端识别为会话/线程的邮件?
Laravel工单邮件:让邮件客户端识别为同一会话的解决方案
我之前也碰到过一模一样的问题——本来以为主题带固定工单ID就能让客户端把邮件归为同一会话,结果Outlook、Thunderbird这些全把每封评论邮件当成新会话展示。后来研究了邮件客户端的线程识别逻辑才发现,核心是几个关键邮件头字段,远不止主题这么简单。
邮件客户端识别会话/线程的关键因素
主流邮件客户端判断邮件是否属于同一会话,主要依赖以下几个核心邮件头,主题只是辅助判断项:
- Message-ID:每封邮件的唯一身份标识,相当于邮件的「身份证号」,每个邮件的这个ID都是唯一的
- In-Reply-To:明确当前邮件是回复哪一封邮件的,值就是目标邮件的
Message-ID - References:记录整个会话里所有关联邮件的
Message-ID,形成一条完整的对话链条 - 主题一致性:虽然不是必须条件,但主题里的固定标识(比如你的
[工单ID])会辅助客户端确认;很多客户端允许主题有轻微变化(比如自动加「Re:」前缀),只要核心标识不变就不会影响
调整Laravel邮件代码,实现会话识别
你当前的代码已经处理了主题,但缺少关键的会话头配置,按下面的步骤修改即可:
1. 存储初始工单邮件的Message-ID
首先,当用户提交工单发送第一封确认邮件时,需要把这封邮件的Message-ID存到tickets表里(先给tickets表新增一个message_id字符串类型字段)。
发送初始邮件时保存ID:
// 发送初始工单确认邮件后 $sentMessage = (new YourInitialTicketMail($ticket))->send(); $ticket->message_id = $sentMessage->getId(); $ticket->save();
2. 在评论邮件中添加会话头字段
修改你现有的build()方法,添加In-Reply-To和References头:
public function build() { $email_from_name = "Support - " . config('app.name'); $subject = "[" . $this->ticket->id . "] " . $this->ticket->subject . " - " . config('app.name'); // 先构建基础邮件实例 $mail = $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, ]); // 如果工单有初始邮件的Message-ID,添加会话头 if (!empty($this->ticket->message_id)) { // 指向原始工单邮件的ID $mail->getHeaders()->addTextHeader('In-Reply-To', $this->ticket->message_id); // 引用原始邮件ID,形成会话链条 $mail->getHeaders()->addTextHeader('References', $this->ticket->message_id); // 进阶优化:如果你的评论表也存了对应邮件的Message-ID,可以把所有关联ID都加入References // 比如:$references = $this->ticket->message_id . ' ' . $this->ticket_comments->message_id; // $mail->getHeaders()->addTextHeader('References', $references); } return $mail; }
3. 可选:保存评论邮件的Message-ID(进阶)
如果想让会话链条更完整,可以给ticket_comments表也新增一个message_id字段,发送评论邮件后保存ID:
$sentCommentMail = (new YourTicketCommentMail($ticket, $comment))->send(); $comment->message_id = $sentCommentMail->getId(); $comment->save();
这样后续的评论邮件就能把所有历史Message-ID都加入References,让客户端更精准地识别完整会话。
验证方法
修改后发送测试邮件,然后在邮件客户端里查看邮件的「原始内容」(不同客户端叫法不同,比如Outlook里是「查看邮件头」),确认In-Reply-To和References字段是否正确指向初始邮件的Message-ID。
内容的提问来源于stack exchange,提问作者checker284
相关产品推荐
相关产品推荐

