Make drone serial number field mandatory in trip form
- Added required validation for bvs_number field in send_plan.php - Updated form label to show asterisk (*) indicating required field - Implemented file attachment support in email notifications (multipart MIME) - Files are now temporarily saved and automatically deleted after email is sent
This commit is contained in:
+134
-4
@@ -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 бота)
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user