' . nl2br(get_settings('mail_signature')); } else { $signature = "\r\n\r\n" . get_settings('mail_signature'); } } else $signature = ''; // Составляем тело письма $body = stripslashes($body) . $signature; if ($type == 'text/html') { $body = str_replace(array("\t","\r","\n"),'',$body); $body = str_replace(array(' ','> <'),array(' ','><'),$body); } // ---------------------------------------------------- // БЛОК SYMFONY MAILER: Инициализация и настройка письма // ---------------------------------------------------- $message = new Email(); $message->getHeaders()->addTextHeader('X-Mailer', 'AVE.cms Symfony Mailer'); $message->subject($subject); // Отправитель $message->from(new Address($from_email, $from_name)); // Получатель (разбиваем строку $to на массив адресов) $to_addresses = array_map('trim', explode(',', $to)); $message->to(...$to_addresses); // Тело письма if ($type == 'text/html') { $message->html($body); $message->text(strip_tags($body)); // AltBody } else { $message->text($body); } // ---------------------------------------------------- // БЛОК SYMFONY MAILER: Прикрепление вложений // ---------------------------------------------------- if ($attach) { foreach ($attach as $attach_file) { $file_path = trim($attach_file); if ($file_path && file_exists($file_path)) { $message->attachFromPath($file_path); } } } // ---------------------------------------------------- // БЛОК SYMFONY MAILER: Формирование DSN // ---------------------------------------------------- $transport_dsn = ''; $mail_type = get_settings('mail_type'); switch ($mail_type) { // Резервный DSN (если выбрано что-то неизвестное) default: $transport_dsn = 'native://default'; break; // МЕТОД 'mail' (Самый простой и надежный) case 'mail': // DSN 'sendmail://default' использует внутреннюю, стабильную функцию PHP mail(). $transport_dsn = 'sendmail://default'; break; // 2. МЕТОД 'sendmail' (Использует путь из настроек, но только если он работает, проверяйте на VDS командой # systemctl status sendmail) case 'sendmail': $path = get_settings('mail_sendmail_path'); // Берем путь из настроек // DSN для прямого вызова исполняемого файла $transport_dsn = 'sendmail://default?command=' . urlencode($path); break; case 'smtp': $host = stripslashes(get_settings('mail_host')); $port = (int)get_settings('mail_port'); $user = stripslashes(get_settings('mail_smtp_login')); $pass = stripslashes(get_settings('mail_smtp_pass')); // Получаем значение шифрования, которое теперь может быть 'tls_insecure' или 'ssl_insecure' $encrypt_setting = strtolower(stripslashes(get_settings('mail_smtp_encrypt'))); $scheme = 'smtp'; $encryption = ''; $extra_params = ''; // 1. Определяем тип шифрования и необходимость отключения проверки if (str_contains($encrypt_setting, 'insecure')) { // Если выбрано *_insecure, отключаем проверку $extra_params = '&verify_peer=0'; // Извлекаем чистый тип шифрования (tls или ssl) $encryption = str_replace('_insecure', '', $encrypt_setting); } elseif ($encrypt_setting === 'tls' || $encrypt_setting === 'ssl') { // Если выбрано обычное шифрование, включаем его (проверка peer=1 по умолчанию) $encryption = $encrypt_setting; } // 2. Формируем DSN в зависимости от наличия шифрования if ($encryption) { // Если есть шифрование (tls или ssl), добавляем его и доп. параметры $transport_dsn = sprintf('%s://%s:%s@%s:%d?encryption=%s%s', $scheme, urlencode($user), urlencode($pass), $host, $port, $encryption, // 'tls' или 'ssl' $extra_params // '' или '&verify_peer=0' ); } else { // Без шифрования (когда выбрано "Нет") $transport_dsn = sprintf('smtp://%s:%s@%s:%d', urlencode($user), urlencode($pass), $host, $port ?: 25 // Порт 25 по умолчанию ); } break; } // Сохраняем вложения в ATTACH_DIR, если просили if ($attach && $saveattach) { $attach_dir = BASE_DIR . '/tmp/' . ATTACH_DIR . '/'; foreach ($attach as $file_path) { if ($file_path && file_exists($file_path)) { $file_name = basename($file_path); $file_name = str_replace(' ','',mb_strtolower(trim($file_name))); if (file_exists($attach_dir . $file_name)) { $file_name = rand(1000, 9999) . '_' . $file_name; } $file_path_new = $attach_dir . $file_name; if (!@move_uploaded_file($file_path,$file_path_new)) { copy($file_path,$file_path_new); } } } } // ---------------------------------------------------- // БЛОК SYMFONY MAILER: Отправка и обработка ошибок // ---------------------------------------------------- try { // 1. Создаем транспорт из DSN $transport = Transport::fromDsn($transport_dsn); // 2. Создаем почтальона (Mailer) $mailer = new Mailer($transport); // 3. Отправляем сообщение $mailer->send($message); return true; // Успех } catch (TransportExceptionInterface $e) { // Записываем специфические ошибки Symfony Mailer в лог reportLog('Не удалось отправить письма. Symfony Mailer Transport Error: ' . $e->getMessage()); return false; // Неудача } catch (\Exception $e) { // Общая ошибка (на всякий случай) reportLog('Не удалось отправить письма. Symfony Mailer Fatal Error: ' . $e->getMessage()); return false; } // ---------------------------------------------------- // КОНЕЦ БЛОКА SYMFONY MAILER // ---------------------------------------------------- } } if ( ! function_exists('safe_mailto')) { function safe_mailto($email, $title = '', $attributes = '') { $title = (string) $title; if ($title == "") { $title = $email; } for ($i = 0; $i < 16; $i++) { $x[] = substr(' $val) { $x[] = ' '.$key.'="'; for ($i = 0; $i < strlen($val); $i++) { $x[] = "|".ord(substr($val, $i, 1)); } $x[] = '"'; } } else { for ($i = 0; $i < strlen($attributes); $i++) { $x[] = substr($attributes, $i, 1); } } } $x[] = '>'; $temp = array(); for ($i = 0; $i < strlen($title); $i++) { $ordinal = ord($title[$i]); if ($ordinal < 128) { $x[] = "|".$ordinal; } else { if (count($temp) == 0) { $count = ($ordinal < 224) ? 2 : 3; } $temp[] = $ordinal; if (count($temp) == $count) { $number = ($count == 3) ? (($temp['0'] % 16) * 4096) + (($temp['1'] % 64) * 64) + ($temp['2'] % 64) : (($temp['0'] % 32) * 64) + ($temp['1'] % 64); $x[] = "|".$number; $count = 1; $temp = array(); } } } $x[] = '<'; $x[] = '/'; $x[] = 'a'; $x[] = '>'; $x = array_reverse($x); ob_start(); ?>