+ /**
+ * Тестирует отправку email для проверки настроек на сервере
+ *
+ * Проверяет переменные окружения и отправляет тестовое письмо.
+ * Используется для диагностики проблем с отправкой почты на production.
+ *
+ * Команда:
+ * php yii marketplace/test-email
+ *
+ * @return int Код завершения (0 = успех, 1 = ошибка)
+ */
+ public function actionTestEmail(): int
+ {
+ $this->stdout("\n", BaseConsole::RESET);
+ $this->stdout("╔══════════════════════════════════════════════════════════════╗\n", BaseConsole::FG_CYAN);
+ $this->stdout("║ ТЕСТИРОВАНИЕ ОТПРАВКИ EMAIL ║\n", BaseConsole::FG_CYAN);
+ $this->stdout("╚══════════════════════════════════════════════════════════════╝\n", BaseConsole::FG_CYAN);
+ $this->stdout("\n", BaseConsole::RESET);
+
+ // 1. Определяем окружение
+ $isDevEnv = \yii_app\services\TelegramService::isDevEnv();
+ $envLabel = $isDevEnv ? 'DEVELOPMENT' : 'PRODUCTION';
+ $this->stdout("Окружение: ", BaseConsole::FG_YELLOW);
+ $this->stdout("{$envLabel}\n", $isDevEnv ? BaseConsole::FG_GREEN : BaseConsole::FG_RED);
+ $this->stdout("YII_ENV: " . YII_ENV . "\n", BaseConsole::FG_CYAN);
+ $this->stdout("\n", BaseConsole::RESET);
+
+ // 2. Показываем настройки SMTP
+ $this->stdout("─── Настройки SMTP ───\n", BaseConsole::FG_YELLOW);
+
+ $mailHost = getenv('MAIL_HOST') ?: '(не задан)';
+ $mailPort = getenv('MAIL_PORT') ?: '(не задан)';
+ $mailUsername = getenv('MAIL_USERNAME');
+ $mailPassword = getenv('MAIL_PASSWORD');
+ $mailEncryption = getenv('MAIL_ENCRYPTION') ?: '(не задан)';
+ $mailScheme = getenv('MAIL_SCHEME') ?: 'smtp';
+
+ $this->stdout(" MAIL_HOST: {$mailHost}\n", BaseConsole::FG_CYAN);
+ $this->stdout(" MAIL_PORT: {$mailPort}\n", BaseConsole::FG_CYAN);
+ $this->stdout(" MAIL_SCHEME: {$mailScheme}\n", BaseConsole::FG_CYAN);
+ $this->stdout(" MAIL_ENCRYPTION: {$mailEncryption}\n", BaseConsole::FG_CYAN);
+ $this->stdout(" MAIL_USERNAME: " . ($mailUsername ? $this->maskEmail($mailUsername) : '(не задан)') . "\n", BaseConsole::FG_CYAN);
+ $this->stdout(" MAIL_PASSWORD: " . ($mailPassword ? '***настроен***' : '(не задан)') . "\n", BaseConsole::FG_CYAN);
+ $this->stdout("\n", BaseConsole::RESET);
+
+ // 3. Показываем получателей
+ $this->stdout("─── Получатели ───\n", BaseConsole::FG_YELLOW);
+
+ $configKey = $isDevEnv ? 'email_recipients_test' : 'email_recipients';
+ $envKey = $isDevEnv ? 'ORDER_CONTROL_EMAIL_RECIPIENTS_TEST' : 'ORDER_CONTROL_EMAIL_RECIPIENTS';
+
+ $config = Yii::$app->params['MARKETPLACE_ORDER_CONTROL_REPORT'] ?? [];
+ $recipients = $config[$configKey] ?? [];
+
+ if (empty($recipients)) {
+ $envRecipients = getenv($envKey);
+ if ($envRecipients) {
+ $recipients = array_filter(array_map('trim', explode(',', $envRecipients)));
+ }
+ }
+
+ $this->stdout(" Источник: " . ($isDevEnv ? "email_recipients_test / {$envKey}" : "email_recipients / {$envKey}") . "\n", BaseConsole::FG_CYAN);
+
+ if (empty($recipients)) {
+ $this->stderr(" ❌ Получатели не настроены!\n", BaseConsole::FG_RED);
+ $this->stderr(" Установите переменную окружения {$envKey}\n", BaseConsole::FG_RED);
+ $this->stderr(" или добавьте в params['MARKETPLACE_ORDER_CONTROL_REPORT']['{$configKey}']\n", BaseConsole::FG_RED);
+ return ExitCode::UNSPECIFIED_ERROR;
+ }
+
+ // Валидация email-адресов
+ $validRecipients = [];
+ foreach ($recipients as $email) {
+ $email = trim($email);
+ if (filter_var($email, FILTER_VALIDATE_EMAIL)) {
+ $validRecipients[] = $email;
+ $this->stdout(" ✅ {$email}\n", BaseConsole::FG_GREEN);
+ } else {
+ $this->stdout(" ❌ {$email} (некорректный формат)\n", BaseConsole::FG_RED);
+ }
+ }
+
+ if (empty($validRecipients)) {
+ $this->stderr("\n❌ Нет валидных email-адресов!\n", BaseConsole::FG_RED);
+ return ExitCode::UNSPECIFIED_ERROR;
+ }
+
+ $this->stdout("\n", BaseConsole::RESET);
+
+ // 4. Проверяем критические настройки
+ $this->stdout("─── Проверка конфигурации ───\n", BaseConsole::FG_YELLOW);
+
+ $errors = [];
+ if (empty($mailHost) || $mailHost === '(не задан)') {
+ $errors[] = 'MAIL_HOST не настроен';
+ }
+ if (empty($mailUsername)) {
+ $errors[] = 'MAIL_USERNAME не настроен';
+ }
+ if (empty($mailPassword)) {
+ $errors[] = 'MAIL_PASSWORD не настроен';
+ }
+
+ if (!empty($errors)) {
+ foreach ($errors as $error) {
+ $this->stderr(" ❌ {$error}\n", BaseConsole::FG_RED);
+ }
+ $this->stderr("\n❌ Критические ошибки конфигурации. Отправка невозможна.\n", BaseConsole::FG_RED);
+ return ExitCode::UNSPECIFIED_ERROR;
+ }
+
+ $this->stdout(" ✅ Все критические настройки заданы\n", BaseConsole::FG_GREEN);
+ $this->stdout("\n", BaseConsole::RESET);
+
+ // 5. Показываем класс mailer
+ $this->stdout("─── Конфигурация Mailer ───\n", BaseConsole::FG_YELLOW);
+ $mailer = Yii::$app->mailer;
+ $this->stdout(" Класс: " . get_class($mailer) . "\n", BaseConsole::FG_CYAN);
+ $this->stdout(" useFileTransport: " . ($mailer->useFileTransport ? 'true (письма в файлы!)' : 'false') . "\n",
+ $mailer->useFileTransport ? BaseConsole::FG_RED : BaseConsole::FG_GREEN);
+
+ if (method_exists($mailer, 'getTransport')) {
+ try {
+ $transport = $mailer->getTransport();
+ $this->stdout(" Transport: " . get_class($transport) . "\n", BaseConsole::FG_CYAN);
+ } catch (\Exception $e) {
+ $this->stdout(" Transport: ошибка получения - " . $e->getMessage() . "\n", BaseConsole::FG_RED);
+ }
+ }
+ $this->stdout("\n", BaseConsole::RESET);
+
+ // 6. Отправка тестового письма
+ $this->stdout("─── Отправка тестового письма ───\n", BaseConsole::FG_YELLOW);
+ $this->stdout(" Получатели: " . implode(', ', $validRecipients) . "\n", BaseConsole::FG_CYAN);
+
+ $subject = '[ERP24 TEST] Тестовое письмо - ' . date('Y-m-d H:i:s');
+ $fromEmail = $mailUsername ?: 'noreply@localhost';
+
+ $this->stdout(" Тема: {$subject}\n", BaseConsole::FG_CYAN);
+ $this->stdout(" От: {$fromEmail}\n", BaseConsole::FG_CYAN);
+ $this->stdout("\n", BaseConsole::RESET);
+
+ $htmlBody = $this->generateTestEmailHtml($envLabel, $mailHost, $mailPort, $validRecipients);
+
+ $this->stdout(" Отправляю...\n", BaseConsole::FG_YELLOW);
+
+ try {
+ $message = Yii::$app->mailer->compose()
+ ->setTo($validRecipients)
+ ->setSubject($subject)
+ ->setFrom([$fromEmail => 'ERP24 Test'])
+ ->setHtmlBody($htmlBody);
+
+ $sent = $message->send();
+
+ if ($sent) {
+ $this->stdout("\n", BaseConsole::RESET);
+ $this->stdout("╔══════════════════════════════════════════════════════════════╗\n", BaseConsole::FG_GREEN);
+ $this->stdout("║ ✅ УСПЕХ! Письмо отправлено. ║\n", BaseConsole::FG_GREEN);
+ $this->stdout("║ Проверьте почтовые ящики получателей. ║\n", BaseConsole::FG_GREEN);
+ $this->stdout("╚══════════════════════════════════════════════════════════════╝\n", BaseConsole::FG_GREEN);
+ return ExitCode::OK;
+ } else {
+ $this->stderr("\n", BaseConsole::RESET);
+ $this->stderr("╔══════════════════════════════════════════════════════════════╗\n", BaseConsole::FG_RED);
+ $this->stderr("║ ❌ ОШИБКА! Метод send() вернул false. ║\n", BaseConsole::FG_RED);
+ $this->stderr("║ Письмо не было отправлено (без исключения). ║\n", BaseConsole::FG_RED);
+ $this->stderr("╚══════════════════════════════════════════════════════════════╝\n", BaseConsole::FG_RED);
+ return ExitCode::UNSPECIFIED_ERROR;
+ }
+ } catch (\Exception $e) {
+ $this->stderr("\n", BaseConsole::RESET);
+ $this->stderr("╔══════════════════════════════════════════════════════════════╗\n", BaseConsole::FG_RED);
+ $this->stderr("║ ❌ ОШИБКА при отправке письма! ║\n", BaseConsole::FG_RED);
+ $this->stderr("╚══════════════════════════════════════════════════════════════╝\n", BaseConsole::FG_RED);
+ $this->stderr("\n", BaseConsole::RESET);
+ $this->stderr("Сообщение: " . $e->getMessage() . "\n", BaseConsole::FG_RED);
+ $this->stderr("Код: " . $e->getCode() . "\n", BaseConsole::FG_RED);
+ $this->stderr("Файл: " . $e->getFile() . ":" . $e->getLine() . "\n", BaseConsole::FG_RED);
+ $this->stderr("\nStack trace:\n", BaseConsole::FG_YELLOW);
+ $this->stderr($e->getTraceAsString() . "\n", BaseConsole::FG_RED);
+
+ Yii::error("Test email error: " . $e->getMessage(), 'email-test');
+
+ return ExitCode::UNSPECIFIED_ERROR;
+ }
+ }
+
+ /**
+ * Маскирует email для вывода (показывает первые 3 символа)
+ *
+ * @param string $email
+ * @return string
+ */
+ private function maskEmail(string $email): string
+ {
+ $parts = explode('@', $email);
+ if (count($parts) !== 2) {
+ return '***';
+ }
+
+ $local = $parts[0];
+ $domain = $parts[1];
+
+ $maskedLocal = substr($local, 0, 3) . str_repeat('*', max(0, strlen($local) - 3));
+ return $maskedLocal . '@' . $domain;
+ }
+
+ /**
+ * Генерирует HTML тело тестового письма
+ *
+ * @param string $envLabel
+ * @param string $mailHost
+ * @param string $mailPort
+ * @param array $recipients
+ * @return string
+ */
+ private function generateTestEmailHtml(string $envLabel, string $mailHost, string $mailPort, array $recipients): string
+ {
+ $timestamp = date('Y-m-d H:i:s');
+ $hostname = gethostname() ?: 'unknown';
+ $phpVersion = PHP_VERSION;
+
+ $recipientsList = implode(', ', $recipients);
+
+ return <<<HTML
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset="UTF-8">
+ <style>
+ body { font-family: Arial, sans-serif; margin: 20px; }
+ .header { background: #4CAF50; color: white; padding: 20px; border-radius: 5px; }
+ .content { padding: 20px; border: 1px solid #ddd; margin-top: 10px; border-radius: 5px; }
+ .info-table { width: 100%; border-collapse: collapse; }
+ .info-table td { padding: 8px; border-bottom: 1px solid #eee; }
+ .info-table td:first-child { font-weight: bold; width: 200px; color: #666; }
+ .success { color: #4CAF50; }
+ .footer { margin-top: 20px; color: #999; font-size: 12px; }
+ </style>
+</head>
+<body>
+ <div class="header">
+ <h2>✅ Тестовое письмо ERP24</h2>
+ <p>Это тестовое письмо подтверждает, что настройки email работают корректно.</p>
+ </div>
+ <div class="content">
+ <h3>Информация об отправке</h3>
+ <table class="info-table">
+ <tr><td>Дата/время:</td><td>{$timestamp}</td></tr>
+ <tr><td>Окружение:</td><td>{$envLabel}</td></tr>
+ <tr><td>SMTP сервер:</td><td>{$mailHost}:{$mailPort}</td></tr>
+ <tr><td>Хост:</td><td>{$hostname}</td></tr>
+ <tr><td>PHP версия:</td><td>{$phpVersion}</td></tr>
+ <tr><td>Получатели:</td><td>{$recipientsList}</td></tr>
+ </table>
+ </div>
+ <div class="footer">
+ <p>Это автоматическое тестовое сообщение. Если вы получили его — настройки email работают.</p>
+ <p>Команда: <code>php yii marketplace/test-email</code></p>
+ </div>
+</body>
+</html>
+HTML;
+ }
+