diff --git a/app/Console/Commands/FetchEmails.php b/app/Console/Commands/FetchEmails.php index e3fac5f0e..1ee1d6f8a 100644 --- a/app/Console/Commands/FetchEmails.php +++ b/app/Console/Commands/FetchEmails.php @@ -943,7 +943,16 @@ public function saveCustomerThread($mailbox, $message_id, $prev_thread, $from, $ if ($new) { $thread->first = true; } - $thread->save(); + try { + $thread->save(); + } catch (\Exception $e) { + // Could not save thread. + // https://github.com/freescout-helpdesk/freescout/issues/3186 + if ($new) { + $conversation->deleteForever(); + } + throw $e; + } $saved_attachments = $this->saveAttachments($attachments, $thread->id); if ($saved_attachments) { diff --git a/app/Conversation.php b/app/Conversation.php index f65c7739e..2b4037a8f 100644 --- a/app/Conversation.php +++ b/app/Conversation.php @@ -1054,7 +1054,7 @@ public function getAssigneeName($ucfirst = false, $user = null) } else { return __('anyone'); } - } elseif (($user && $this->user_id == $user->id) || (!$user && $this->user_id == auth()->user()->id)) { + } elseif (($user && $this->user_id == $user->id) || (!$user && auth()->user() && $this->user_id == auth()->user()->id)) { if ($ucfirst) { return __('Me'); } else { diff --git a/app/Http/Controllers/SystemController.php b/app/Http/Controllers/SystemController.php index 973829846..1c519031f 100644 --- a/app/Http/Controllers/SystemController.php +++ b/app/Http/Controllers/SystemController.php @@ -55,6 +55,8 @@ public function status(Request $request) if (function_exists('shell_exec')) { $non_writable_cache_file = shell_exec('find '.base_path('storage/framework/cache/data/').' -type f | xargs -I {} sh -c \'[ ! -w "{}" ] && echo {}\' 2>&1 | head -n 1'); $non_writable_cache_file = trim($non_writable_cache_file ?? ''); + // Leave only one line (in case head -n 1 does not work) + $non_writable_cache_file = preg_replace("#[\r\n].+#m", '', $non_writable_cache_file); if (!strstr($non_writable_cache_file, base_path('storage/framework/cache/data/'))) { $non_writable_cache_file = ''; } diff --git a/app/Jobs/SendReplyToCustomer.php b/app/Jobs/SendReplyToCustomer.php index f255500b4..93bf40157 100644 --- a/app/Jobs/SendReplyToCustomer.php +++ b/app/Jobs/SendReplyToCustomer.php @@ -177,13 +177,32 @@ public function handle() \App\Misc\Mail::setMailDriver($mailbox, $this->last_thread->created_by_user, $this->conversation); // Get penultimate email Message-Id if reply + $references = ''; if (!$new && !empty($last_customer_thread) && $last_customer_thread->message_id) { $headers['In-Reply-To'] = '<'.$last_customer_thread->message_id.'>'; - $headers['References'] = '<'.$last_customer_thread->message_id.'>'; + //$headers['References'] = '<'.$last_customer_thread->message_id.'>'; + // https://github.com/freescout-helpdesk/freescout/issues/3175 + $i = 0; + $references_array = []; + foreach ($this->threads as $thread) { + if ($i > 0) { + $reference = $thread->getMessageId(); + if ($reference) { + $references_array[] = $reference; + } + } + $i++; + } + if ($references_array) { + $references = '<'.implode('> <', array_reverse($references_array)).'>'; + } + if ($references) { + $headers['References'] = $references; + } } - $this->message_id = \App\Misc\Mail::MESSAGE_ID_PREFIX_REPLY_TO_CUSTOMER.'-'.$this->last_thread->id.'-'.\MailHelper::getMessageIdHash($this->last_thread->id).'@'.$mailbox->getEmailDomain(); + $this->message_id = $this->last_thread->getMessageId($mailbox); $headers['Message-ID'] = $this->message_id; $this->customer_email = $this->conversation->customer_email; @@ -303,7 +322,7 @@ public function handle() if (!$new && !empty($last_customer_thread) && $last_customer_thread->message_id) { $envelope['custom_headers'] = [ 'In-Reply-To: <'.$last_customer_thread->message_id.'>', - 'References: <'.$last_customer_thread->message_id.'>' + 'References: '.$references, ]; } // Remove new lines to avoid "imap_mail_compose(): header injection attempt in subject". diff --git a/app/Misc/Mail.php b/app/Misc/Mail.php index 6ef09e730..7c94cb0e2 100644 --- a/app/Misc/Mail.php +++ b/app/Misc/Mail.php @@ -885,40 +885,14 @@ public static function getImapFolder($client, $folder_name) } } - // $subjects = [ - // '=?utf-8?Q?Gesch=C3=A4ftskonto?= erstellen =?utf-8?Q?f=C3=BCr?= - // 249143' => 'Geschäftskonto erstellen für 249143', - // '=?ISO-8859-1?Q?Vorgang 538336029: M=F6chten Sie Ihre E-Mail-Adresse =E4ndern??=' => 'Vorgang 538336029: Möchten Sie Ihre E-Mail-Adresse ändern?', - // '=?iso-2022-jp?B?IBskQiFaSEcyPDpuQ?= =?iso-2022-jp?B?C4wTU1qIVs3Mkp2JSIlLyU3JSItahsoQg==?=' => ' 【版下作成依頼】群峰アクシア(株)', - // '=?iso-2022-jp?B?IBskQiFaSEcyPDpuQC4wTU1qIVs3Mkp2JSIlLyU3JSItahsoQg==?=' => ' 【版下作成依頼】群峰アクシア(株)', - // '=?iso-2022-jp?B?GyRCIXlCaBsoQjEzMhskQjlmISEhViUsITwlRyVzGyhCJhskQiUoJS8lOSVGJWolIiFXQGxMZ0U5JE4kPyRhJE4jURsoQiYbJEIjQSU1JW0lcyEhIVo3bjQpJSglLyU5JUYlaiUiISYlbyE8JS8hWxsoQg==?=' => '☆第132号 「ガーデン&エクステリア」専門店のためのQ&Aサロン 【月刊エクステリア・ワーク】', - // '=?UTF-8?Q?Schadensmeldung_F=C3=9C230414439?=' => 'Schadensmeldung FÜ230414439', - // '=?utf-8?B?0JLRi9C/0LjRgdC60LAg0LfQsCDQv9GA0L7RiNC10LTRiNC4?= =?utf-8?B?0Lkg0LzQtdGB0Y/RhiDQv9C+INCe0J7QniAi0JjQmtCh0KTQkNCZ0JLQ?= =?utf-8?B?mNCa0KEi?=' => 'Выписка за прошедший месяц по ООО "ИКСФАЙВИКС"', - // '=?UTF-8?B?0JLRi9C/0LjRgdC60LAg0LfQsCDQv9GA0L7RiNC10LTRiNC40Lkg0LzQtdGB0Y/RhiDQvw==?= - // =?UTF-8?B?0L4g0J7QntCeICLQmNCa0KHQpNCQ0JnQktCY0JrQoSI=?=' => 'Выписка за прошедший месяц по ООО "ИКСФАЙВИКС"', - // '=?iso-2022-jp?B?IBskQiFaSEcyPDpuQC4wTU1qIVs3Mkp2JSIlLyU3JSItahsoQg==?=' => ' 【版下作成依頼】群峰アクシア(株)', - // '=?iso-2022-jp?B?IBskQiFaSEcyPDpuQC4wTU1qIVs3Mkp2JSIlLyU3JSItahsoQg==?= - // =?iso-2022-jp?B?GyRCQGlNVTtZRTkhIT4uTlMbKEI=?=' => ' 【版下作成依頼】群峰アクシア(株)千葉支店 小林', - // '=?UTF-8?B?44CQ44Os44Kk44Ki44Km44OI44O76KaL56mN5L2c5oiQ5L6d6aC844CR?= - // =?UTF-8?B?57eR5Yy644CA5Yqg6Jek6YK444CA54m55rOo5qGI5YaF44OX44Os44O8?= - // =?UTF-8?B?44OILnBkZg==?=' => '【レイアウト・見積作成依頼】緑区 加藤邸 特注案内プレート.pdf', - // ]; - // $i = 1; - // foreach ($subjects as $subject => $subject_valid) { - // $subject_decoded = \MailHelper::decodeSubject($subject); - // echo ($i). ") "; - // if ($subject_decoded != $subject_valid) { - // echo '[INVALID] '; - // } - // echo \MailHelper::decodeSubject($subject)."\n"; - // $i++; - // } public static function decodeSubject($subject) { // Remove new lines as iconv_mime_decode() may loose a part separated by new line: // =?utf-8?Q?Gesch=C3=A4ftskonto?= erstellen =?utf-8?Q?f=C3=BCr?= // 249143 $subject = preg_replace("/[\r\n]/", '', $subject); + // https://github.com/freescout-helpdesk/freescout/issues/3185 + $subject = str_replace('=?iso-2022-jp?', '=?iso-2022-jp-ms?', $subject); // Sometimes imap_utf8() can't decode the subject, for example: // =?iso-2022-jp?B?GyRCIXlCaBsoQjEzMhskQjlmISEhViUsITwlRyVzGyhCJhskQiUoJS8lOSVGJWolIiFXQGxMZ0U5JE4kPyRhJE4jURsoQiYbJEIjQSU1JW0lcyEhIVo3bjQpJSglLyU5JUYlaiUiISYlbyE8JS8hWxsoQg==?= @@ -950,6 +924,7 @@ public static function decodeSubject($subject) if ($subject_decoded && trim($subject_decoded) != trim($joined_parts) && trim($subject_decoded) != trim(rtrim($joined_parts, '=')) + && mb_check_encoding($subject_decoded, 'UTF-8') ) { return $subject_decoded; } @@ -961,6 +936,7 @@ public static function decodeSubject($subject) if ($subject_decoded && trim($subject_decoded) != trim($joined_parts) && trim($subject_decoded) != trim(rtrim($joined_parts, '=')) + && mb_check_encoding($subject_decoded, 'UTF-8') ) { return $subject_decoded; } @@ -983,7 +959,9 @@ public static function decodeSubject($subject) // mb_decode_mimeheader() properly decodes umlauts into one unice symbol. // But we use mb_decode_mimeheader() as a last resort as it may garble some symbols. // Example: =?ISO-8859-1?Q?Vorgang 538336029: M=F6chten Sie Ihre E-Mail-Adresse =E4ndern??= - if (preg_match_all("/=\?[^\?]+\?[BQ]\?/i", $subject_decoded) && $subject == $subject_decoded) { + if ((preg_match_all("/=\?[^\?]+\?[BQ]\?/i", $subject_decoded) && $subject == $subject_decoded) + || !mb_check_encoding($subject_decoded, 'UTF-8') + ) { $subject_decoded = mb_decode_mimeheader($subject); } diff --git a/app/Observers/FollowerObserver.php b/app/Observers/FollowerObserver.php index 4eb0c1843..7b2ad05ae 100644 --- a/app/Observers/FollowerObserver.php +++ b/app/Observers/FollowerObserver.php @@ -8,7 +8,7 @@ class FollowerObserver { public function created(Follower $follower) { - \Eventy::action('follower.created', $attachment); + \Eventy::action('follower.created', $follower); } public function deleted(Follower $follower) diff --git a/app/Thread.php b/app/Thread.php index 36811d1c4..48727bfaf 100644 --- a/app/Thread.php +++ b/app/Thread.php @@ -1473,4 +1473,19 @@ function ($match) { return $body; } + + public function getMessageId($mailbox = null) + { + if ($this->isCustomerMessage() && $this->message_id) { + return $this->message_id; + } + if ($this->isUserMessage()) { + if (!$mailbox) { + $mailbox = $this->conversation->mailbox; + } + return \MailHelper::MESSAGE_ID_PREFIX_REPLY_TO_CUSTOMER.'-'.$this->id.'-'.\MailHelper::getMessageIdHash($this->id).'@'.$mailbox->getEmailDomain(); + } + + return ''; + } } diff --git a/config/app.php b/config/app.php index 03d6ea210..e3c561829 100644 --- a/config/app.php +++ b/config/app.php @@ -18,7 +18,7 @@ | or any other location as required by the application or its packages. */ - 'version' => '1.8.84', + 'version' => '1.8.85', /* |-------------------------------------------------------------------------- diff --git a/resources/lang/ru.json b/resources/lang/ru.json index 50ef3c05f..e7284eddf 100644 --- a/resources/lang/ru.json +++ b/resources/lang/ru.json @@ -301,8 +301,8 @@ "First Page": "Первая страница", "First name": "Имя", "Folder not found": "Папка не найдена", - "Follow": "Следить", - "Following": "Следующий", + "Follow": "Отслеживать", + "Following": "Отслеживаемый", "Forgot Your Password?": "Забыли пароль?", "Forward": "Переслать", "Free open source help desk & shared mailbox": "Бесплатный хелпдеск с открытым кодом и общий почтовый ящик",