Исправление кодировки в письмах Opencart 3

Проблема: при переключении в режим отправки писем по SMTP текст писем может приходить поврежденным — например, с неизвестными символами либо с лишними пробелами посреди слов. Проблема замечена на связке шаблон Prostore + SMTP-сервер Beget.

Причина в механизме нарезки тела письма на строки в \system\library\mail\smtp.php, send() : устанавливается лимит для каждой строки исходя из ее кодировки, затем html нарезается по нему с помощью str_split(); граница может пройти прямо посередине слова

$length = (mb_detect_encoding($message, mb_detect_order(), true) == 'ASCII') ? 998 : 249;

$lines = explode("\n", $message);

foreach ($lines as $line) {
	$results = str_split($line, $length); // <-- проблемная строка

	foreach ($results as $result) {
		if (substr(PHP_OS, 0, 3) != 'WIN') {
			fputs($handle, $result . "\r\n");
		} else {
			fputs($handle, str_replace("\n", "\r\n", $result) . "\r\n");
		}
	}
}

Для исправления можно использовать готовый модификатор (в конце статьи) либо поправить вручную – добавить в класс Smtp() метод str_split_word_aware() отсюда, и модифицировать код выше следующим образом:

$length = (mb_detect_encoding($message, mb_detect_order(), true) == 'ASCII') ? 998 : 249;

$lines = explode("\n", $message);

foreach ($lines as $line) {

	$line = trim($line);
	$results = [];

	if (method_exists($this, 'str_split_word_aware')){
		$results = $this->str_split_word_aware($line, $length);
		foreach ($results as &$r_val) {
			$r_val = trim($r_val);
		}
	} else {
		$results = str_split($line, $length);
	}

	foreach ($results as $result) {
		if (substr(PHP_OS, 0, 3) != 'WIN') {
			fputs($handle, $result . "\r\n");
		} else {
			fputs($handle, str_replace("\n", "\r\n", $result) . "\r\n");
		}
	}
}

Как итог, теперь строки будут нарезаться по границе слов

Модификатор для Opencart

По данному рецепту собрал модификатор, тестировался на ocStore 3.0.3.7, ссылка

Оставьте комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Прокрутить вверх