diff --git a/app/Console/Commands/FetchEmails.php b/app/Console/Commands/FetchEmails.php index c2ec6a20..a2f979aa 100644 --- a/app/Console/Commands/FetchEmails.php +++ b/app/Console/Commands/FetchEmails.php @@ -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); diff --git a/app/Misc/Mail.php b/app/Misc/Mail.php index d9a6885f..a68c0429 100644 --- a/app/Misc/Mail.php +++ b/app/Misc/Mail.php @@ -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 ''; + } } diff --git a/resources/views/emails/customer/auto_reply.blade.php b/resources/views/emails/customer/auto_reply.blade.php index 3206102c..0fe78096 100644 --- a/resources/views/emails/customer/auto_reply.blade.php +++ b/resources/views/emails/customer/auto_reply.blade.php @@ -13,6 +13,6 @@ @endif - {{--{#FS:123-123#}--}} + {{ \MailHelper::getMessageMarker($headers['Message-ID']) }} \ No newline at end of file diff --git a/resources/views/emails/customer/reply_fancy.blade.php b/resources/views/emails/customer/reply_fancy.blade.php index a27771d7..d51eefeb 100644 --- a/resources/views/emails/customer/reply_fancy.blade.php +++ b/resources/views/emails/customer/reply_fancy.blade.php @@ -68,14 +68,15 @@ @endif - @if (\App\Option::get('open_tracking')) - - + + + @if (\App\Option::get('open_tracking')) -
{#FS:123-123#}
- - - @endif + @endif + {{-- Addition to Message-ID header to detect relies --}} +
{{ \MailHelper::getMessageMarker($headers['Message-ID']) }}
+ + diff --git a/resources/views/emails/user/notification.blade.php b/resources/views/emails/user/notification.blade.php index 6867ed95..a515e86a 100644 --- a/resources/views/emails/user/notification.blade.php +++ b/resources/views/emails/user/notification.blade.php @@ -228,6 +228,12 @@ + + + {{-- Addition to Message-ID header to detect relies --}} +
{{ \MailHelper::getMessageMarker($headers['Message-ID']) }}
+ +