diff --git a/content/plan.md b/content/plan.md
index fb8bc9b..64ecf62 100755
--- a/content/plan.md
+++ b/content/plan.md
@@ -192,8 +192,8 @@ disableComments = true
-
-
+
+
diff --git a/forms/forms_helper.php b/forms/forms_helper.php
index e3ccc1a..54e86e3 100644
--- a/forms/forms_helper.php
+++ b/forms/forms_helper.php
@@ -59,22 +59,32 @@ function get_forms_settings() {
/**
* Простое шифрование данных для безопасного хранения
+ * Совместимо с Python Crypto.Cipher.AES + unpad
*/
function encrypt_data($data, $key) {
$json = json_encode($data, JSON_UNESCAPED_UNICODE);
$iv = random_bytes(16);
- $encrypted = openssl_encrypt($json, 'AES-256-CBC', hash('sha256', $key), 0, $iv);
- return base64_encode($iv . $encrypted);
+
+ // openssl_encrypt с параметром 0 сам добавляет PKCS7 padding и возвращает base64
+ $encrypted_b64 = openssl_encrypt($json, 'AES-256-CBC', hash('sha256', $key), 0, $iv);
+ // Декодируем base64 чтобы получить бинарные данные
+ $encrypted_raw = base64_decode($encrypted_b64);
+ // Добавляем IV в начало и кодируем все вместе
+ return base64_encode($iv . $encrypted_raw);
}
/**
* Расшифровка данных
+ * Совместимо с Python Crypto.Cipher.AES + unpad
*/
function decrypt_data($encrypted_data, $key) {
$data = base64_decode($encrypted_data);
$iv = substr($data, 0, 16);
- $encrypted = substr($data, 16);
- $decrypted = openssl_decrypt($encrypted, 'AES-256-CBC', hash('sha256', $key), 0, $iv);
+ $encrypted_raw = substr($data, 16);
+ // Кодируем обратно в base64 для openssl_decrypt
+ $encrypted_b64 = base64_encode($encrypted_raw);
+ // openssl_decrypt с параметром 0 сам убирает PKCS7 padding
+ $decrypted = openssl_decrypt($encrypted_b64, 'AES-256-CBC', hash('sha256', $key), 0, $iv);
return json_decode($decrypted, true);
}
@@ -208,6 +218,126 @@ function send_telegram_notification($form_data, $form_type) {
}
}
+/**
+ * Отправка уведомления на Email через msmtp с поддержкой файлов
+ */
+function send_email_notification($form_data, $form_type) {
+ $settings = get_forms_settings();
+
+ if (!$settings['send_email']) {
+ return true; // Отправка email отключена
+ }
+
+ // Получаем admin email из .env
+ $admin_email = getenv('ADMIN_EMAIL') ?: 'admin@example.com';
+ $from_email = getenv('SMTP_FROM_EMAIL') ?: getenv('SMTP_USERNAME') ?: 'noreply@yourdomain.com';
+ $from_name = getenv('SMTP_FROM_NAME') ?: 'PTP Robot';
+
+ // Формируем тему письма
+ $subject = ($form_type === 'plan')
+ ? '🎫 Новая заявка на поездку - ' . $form_data['name']
+ : '❓ Новый вопрос - ' . ($form_data['subject'] ?? 'Без темы');
+
+ // Формируем тело письма
+ $message = "Новая заявка с сайта\n\n";
+ $message .= "Тип: " . ($form_type === 'plan' ? 'Заявка на поездку' : 'Вопрос') . "\n";
+ $message .= "Время: " . date('Y-m-d H:i:s') . "\n\n";
+
+ $message .= "=== ДАННЫЕ ЗАЯВИТЕЛЯ ===\n";
+ $message .= "Имя: " . $form_data['name'] . "\n";
+ $message .= "Email: " . $form_data['email'] . "\n";
+
+ if ($form_type === 'plan') {
+ $message .= "Телефон: " . ($form_data['phone'] ?: 'не указан') . "\n";
+ $message .= "Telegram: " . ($form_data['telegram'] ?: 'не указан') . "\n";
+ $message .= "Поездка: " . ($form_data['trip_period'] ?: 'не выбрана') . "\n";
+ $message .= "БВС/Направление: " . ($form_data['bvs_number'] ?: 'не указано') . "\n";
+ } else {
+ if (!empty($form_data['telegram'])) {
+ $message .= "Telegram: " . $form_data['telegram'] . "\n";
+ }
+ if (!empty($form_data['phone'])) {
+ $message .= "Телефон: " . $form_data['phone'] . "\n";
+ }
+ $message .= "Тема: " . $form_data['subject'] . "\n";
+ $message .= "\n=== СООБЩЕНИЕ ===\n";
+ $message .= $form_data['message'] . "\n";
+ }
+
+ // Проверяем наличие файла для отправки
+ $attachment_file = $form_data['bvs_file_path'] ?? null;
+ $has_attachment = $attachment_file && file_exists($attachment_file);
+
+ // Создаем boundary для multipart письма если есть файл
+ $boundary = "----=_Part_" . md5(time() . rand());
+
+ if ($has_attachment) {
+ // Заголовки письма с файлом (multipart)
+ $headers = "From: $from_name <$from_email>\r\n";
+ $headers .= "Reply-To: " . $form_data['email'] . "\r\n";
+ $headers .= "MIME-Version: 1.0\r\n";
+ $headers .= "Content-Type: multipart/mixed; boundary=\"$boundary\"\r\n";
+ $headers .= "X-Mailer: PHP/" . phpversion();
+
+ // Формируем multipart тело письма
+ $multipart_message = "--$boundary\r\n";
+ $multipart_message .= "Content-Type: text/plain; charset=UTF-8\r\n";
+ $multipart_message .= "Content-Transfer-Encoding: 8bit\r\n\r\n";
+ $multipart_message .= $message . "\r\n";
+
+ // Добавляем файл
+ $file_content = file_get_contents($attachment_file);
+ $file_name = basename($attachment_file);
+ // Извлекаем оригинальное имя файла (после bvs_)
+ if (preg_match('/bvs_\w+_(.+)$/', $file_name, $matches)) {
+ $file_name = $matches[1];
+ }
+
+ $multipart_message .= "--$boundary\r\n";
+ $multipart_message .= "Content-Type: application/pdf; name=\"$file_name\"\r\n";
+ $multipart_message .= "Content-Transfer-Encoding: base64\r\n";
+ $multipart_message .= "Content-Disposition: attachment; filename=\"$file_name\"\r\n\r\n";
+ $multipart_message .= chunk_split(base64_encode($file_content)) . "\r\n";
+
+ $multipart_message .= "--$boundary--\r\n";
+
+ $email_message = $multipart_message;
+ } else {
+ // Заголовки письма без файла
+ $headers = "From: $from_name <$from_email>\r\n";
+ $headers .= "Reply-To: " . $form_data['email'] . "\r\n";
+ $headers .= "Content-Type: text/plain; charset=UTF-8\r\n";
+ $headers .= "X-Mailer: PHP/" . phpversion();
+ $email_message = $message;
+ }
+
+ // Отправка письма
+ try {
+ error_log("=== Attempting mail() ===");
+ error_log("To: $admin_email | From: $from_email | Subject: $subject | Has attachment: " . ($has_attachment ? 'YES' : 'NO'));
+ $result = mail($admin_email, $subject, $email_message, $headers);
+ error_log("mail() returned: " . ($result ? 'TRUE' : 'FALSE'));
+
+ if ($result) {
+ error_log("Email отправлен успешно на: $admin_email");
+
+ // Удаляем временный файл после отправки
+ if ($has_attachment && file_exists($attachment_file)) {
+ unlink($attachment_file);
+ error_log("Временный файл удален: $attachment_file");
+ }
+
+ return true;
+ } else {
+ error_log("Ошибка отправки email на: $admin_email");
+ return false;
+ }
+ } catch (Exception $e) {
+ error_log("Исключение при отправке email: " . $e->getMessage());
+ return false;
+ }
+}
+
/**
* Получение списка всех заявок (для Telegram бота)
*/
diff --git a/forms/send_plan.php b/forms/send_plan.php
index 88b967c..38b3837 100644
--- a/forms/send_plan.php
+++ b/forms/send_plan.php
@@ -16,8 +16,8 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$bvs_file = $_FILES['bvs_file'] ?? null;
// Валидация
- if (empty($name) || empty($consent)) {
- $error = "Обязательные поля: Фамилия, имя, Согласие на обработку данных.";
+ if (empty($name) || empty($consent) || empty($bvs_number)) {
+ $error = "Обязательные поля: Фамилия, имя, Учётный номер дрона, Согласие на обработку данных.";
} elseif (empty($phone)) {
$error = "Обязательное поле: Телефон.";
} elseif (empty($email) && empty($telegram)) {
@@ -38,6 +38,17 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
}
if (!isset($error)) {
+ // Сохраняем загруженный файл во временную папку
+ $uploaded_file_path = null;
+ if ($bvs_file && $bvs_file['error'] === UPLOAD_ERR_OK) {
+ $upload_dir = sys_get_temp_dir() . '/ptp_forms_uploads/';
+ if (!is_dir($upload_dir)) {
+ mkdir($upload_dir, 0700, true);
+ }
+ $uploaded_file_path = $upload_dir . uniqid('bvs_') . '_' . basename($bvs_file['name']);
+ move_uploaded_file($bvs_file['tmp_name'], $uploaded_file_path);
+ }
+
// Подготавливаем данные заявки
$form_data = [
'name' => $name,
@@ -47,7 +58,8 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
'bvs_number' => $bvs_number,
'trip_period' => $trip_period,
'consent' => $consent,
- 'bvs_file' => $bvs_file ? $bvs_file['name'] : ''
+ 'bvs_file' => $bvs_file ? $bvs_file['name'] : '',
+ 'bvs_file_path' => $uploaded_file_path
];
$success_messages = [];