1
0
mirror of https://github.com/freescout-helpdesk/freescout.git synced 2024-11-25 03:43:33 +01:00

Use marker in body in addition to Message ID to track replies

This commit is contained in:
FreeScout 2018-11-15 05:03:53 -08:00
parent 556660e6c1
commit 060d24c95e
5 changed files with 84 additions and 25 deletions

View File

@ -193,11 +193,42 @@ class FetchEmails extends Command
$in_reply_to = $message->getInReplyTo();
$references = $message->getReferences();
$attachments = $message->getAttachments();
$html_body = '';
// Is it a bounce message
$is_bounce = false;
$bounce_attachment = null;
// Determine previous Message-ID
$prev_message_id = '';
if ($in_reply_to) {
$prev_message_id = $in_reply_to;
} elseif ($references) {
if (!is_array($references)) {
$references = array_filter(preg_split('/[, <>]/', $references));
}
// Maybe we need to check all references
$prev_message_id = $references[0];
}
// Some mail service providers change Message-ID of the outgoing email,
// so we are passing Message-ID in marker in body.
$reply_prefixes = [
\MailHelper::MESSAGE_ID_PREFIX_NOTIFICATION,
\MailHelper::MESSAGE_ID_PREFIX_REPLY_TO_CUSTOMER,
\MailHelper::MESSAGE_ID_PREFIX_AUTO_REPLY,
];
if (!$prev_message_id || !preg_match('/^('.implode('|', $reply_prefixes).')\-(\d+)\-/', $prev_message_id)) {
// Try to get previous message ID from marker in body.
$html_body = $message->getHTMLBody(false);
$marker_message_id = \MailHelper::fetchMessageMarkerValue($html_body);
if ($marker_message_id) {
$prev_message_id = $marker_message_id;
}
}
// Determine bounce by attachment
if ($message->hasAttachments()) {
foreach ($attachments as $attachment) {
@ -212,7 +243,7 @@ class FetchEmails extends Command
}
// Is it a message from Customer or User replied to the notification
preg_match('/^'.\App\Misc\Mail::MESSAGE_ID_PREFIX_NOTIFICATION."\-(\d+)\-(\d+)\-/", $in_reply_to, $m);
preg_match('/^'.\MailHelper::MESSAGE_ID_PREFIX_NOTIFICATION."\-(\d+)\-(\d+)\-/", $prev_message_id, $m);
if (!$is_bounce && !empty($m[1]) && !empty($m[2])) {
// Reply from User to the notification
@ -228,7 +259,7 @@ class FetchEmails extends Command
continue;
}
$this->line('['.date('Y-m-d H:i:s').'] Message from: User');
} elseif (!$is_bounce && ($user = User::where('email', $from)->first()) && $in_reply_to && ($prev_thread = Thread::where('message_id', $in_reply_to)->first()) && $prev_thread->created_by_user_id == $user->id) {
} elseif (!$is_bounce && ($user = User::where('email', $from)->first()) && $prev_message_id && ($prev_thread = Thread::where('message_id', $prev_message_id)->first()) && $prev_thread->created_by_user_id == $user->id) {
// Reply from customer to his reply to the notification
$user_id = $user->id;
$message_from_customer = false;
@ -237,29 +268,20 @@ class FetchEmails extends Command
// Message from Customer
$this->line('['.date('Y-m-d H:i:s').'] Message from: Customer');
$prev_message_id = '';
if (!$is_bounce) {
if ($in_reply_to) {
$prev_message_id = $in_reply_to;
} elseif ($references) {
if (!is_array($references)) {
$references = array_filter(preg_split('/[, <>]/', $references));
}
// Maybe we need to check all references
$prev_message_id = $references[0];
}
if ($prev_message_id) {
$prev_thread_id = '';
// Customer replied to the email from user
preg_match('/^'.\App\Misc\Mail::MESSAGE_ID_PREFIX_REPLY_TO_CUSTOMER."\-(\d+)\-/", $prev_message_id, $m);
preg_match('/^'.\MailHelper::MESSAGE_ID_PREFIX_REPLY_TO_CUSTOMER."\-(\d+)\-/", $prev_message_id, $m);
if (!empty($m[1])) {
$prev_thread_id = $m[1];
}
// Customer replied to the auto reply
if (!$prev_thread_id) {
preg_match('/^'.\App\Misc\Mail::MESSAGE_ID_PREFIX_AUTO_REPLY."\-(\d+)\-/", $prev_message_id, $m);
preg_match('/^'.\MailHelper::MESSAGE_ID_PREFIX_AUTO_REPLY."\-(\d+)\-/", $prev_message_id, $m);
if (!empty($m[1])) {
$prev_thread_id = $m[1];
}
@ -278,10 +300,13 @@ class FetchEmails extends Command
}
}
if ($message->hasHTMLBody()) {
// Get body
if (!$html_body) {
// Get body and do not replace :cid with images base64
$body = $message->getHTMLBody(false);
$body = $this->separateReply($body, true, $is_reply);
$html_body = $message->getHTMLBody(false);
}
if ($html_body) {
$body = $this->separateReply($html_body, true, $is_reply);
} else {
$body = $message->getTextBody();
$body = $this->separateReply($body, false, $is_reply);

View File

@ -318,4 +318,31 @@ class Mail
return true;
}
}
/**
* Get email marker for the outgoing email to track replies
* in case Message-ID header is removed by mail service provider.
* @param [type] $message_id [description]
* @return [type] [description]
*/
public static function getMessageMarker($message_id)
{
// It has to be BASE64, as Gmail converts it into link.
return '{#FS:'.base64_encode($message_id).'#}';
}
/**
* Fetch Message-ID from incoming email body.
* @param [type] $message_id [description]
* @return [type] [description]
*/
public static function fetchMessageMarkerValue($body)
{
preg_match("/{#FS:([^#]+)#}/", $body, $matches);
if (!empty($matches[1]) && base64_decode($matches[1])) {
// Return first found marker.
return base64_decode($matches[1]);
}
return '';
}
}

View File

@ -13,6 +13,6 @@
</div>
@endif
</div>
{{--<span height="0" style="font-size: 0px; height:0px; line-height: 0px; color:#ffffff;">{#FS:123-123#}</span>--}}
<span height="0" style="font-size: 0px; height:0px; line-height: 0px; color:#ffffff;">{{ \MailHelper::getMessageMarker($headers['Message-ID']) }}</span>
</body>
</html>

View File

@ -68,14 +68,15 @@
</td>
</tr>
@endif
@if (\App\Option::get('open_tracking'))
<tr>
<td height="0" style="font-size: 0px; line-height: 0px; color:#ffffff;">
<tr>
<td height="0" style="font-size: 0px; line-height: 0px; color:#ffffff;">
@if (\App\Option::get('open_tracking'))
<img src="{{ route('open_tracking.set_read', ['conversation_id' => $threads->first()->conversation_id, 'thread_id' => $threads->first()->id]) }}/" alt="" />
<div style="font-size: 0px; line-height: 0px; color:#ffffff !important; display:none;">{#FS:123-123#}</div>
</td>
</tr>
@endif
@endif
{{-- Addition to Message-ID header to detect relies --}}
<div style="font-size: 0px; line-height: 0px; color:#ffffff !important; display:none;">{{ \MailHelper::getMessageMarker($headers['Message-ID']) }}</div>
</td>
</tr>
</table>
</td>
</tr>

View File

@ -228,6 +228,12 @@
</table>
</td>
</tr>
<tr>
<td height="0" style="font-size: 0px; line-height: 0px; color:#ffffff;">
{{-- Addition to Message-ID header to detect relies --}}
<div style="font-size: 0px; line-height: 0px; color:#ffffff !important; display:none;">{{ \MailHelper::getMessageMarker($headers['Message-ID']) }}</div>
</td>
</tr>
</table>
<div itemscope itemtype="http://schema.org/EmailMessage">
<div itemprop="potentialAction" itemscope itemtype="http://schema.org/ViewAction">