Показать сообщение отдельно
  #13 (permalink)  
Старый 10.11.2020, 08:05
Профессор
Отправить личное сообщение для laimas Посмотреть профиль Найти все сообщения от laimas
 
Регистрация: 14.01.2015
Сообщений: 12,990

На сервере:
<?php
//задержка для посмотерть как работает форма при отправке, удалить после
sleep(2); 

$check = [
    'sex'       => [
        'filter'    => FILTER_VALIDATE_INT, //пол, это вообще-то поле типа ENUM в базе со значениями: 1 - мужчина, 2 - женщина, это и надо проверять 
        'flags'     => FILTER_REQUIRE_SCALAR, 
        'options'   => ['min_range' => 1, 'max_range' => 2]
    ],
    'email'     => FILTER_VALIDATE_EMAIL,
    'worker'    => FILTER_VALIDATE_INT, //сотрудник Петя может быть таким только как текст опции, но никак не ее значение, значением должен быть уникальный идентфикатор сотрудника
    'subject'   => [
        'filter'    => FILTER_VALIDATE_REGEXP,  
        'options'   => ['regexp' =>'/^[а-яё\s]{10,60}$/ui']
    ],
    'message'   => FILTER_SANITIZE_SPECIAL_CHARS //нет смысла в strip_tags, если отправление в html формате, лучше преобразовать в html сущности
];

$error_message = [
    'sex'       => 'Некорректное значение поля «Пол»!',
    'email'     => 'Некорректное значение поля «Адрес почты»!',
    'worker'    => 'Некорректное значение поля «Сотрудник»!',
    'subject'   => 'Некорректное значение поля «Тема»!',
    'message'   => 'Некорректное значение поля «Сообощение»!',
    'file'      => 'Ошибка получения файла!'
];

$errors = [];

//убираем возможные крайние пробелы
$post = array_map('trim', $_POST);
//если не все на месте, нарушение формы, это не наш клиент, в этом случае можно прекратить работу и выйти
if(array_diff_key($post, $check)) exit;
//проверяем что прислали
$data = filter_var_array($post, $check);
//если есть ошибки получим их сообщения
$errors +=  array_intersect_key($error_message, array_filter($data, function($v) { return !$v; }));
//если прикреплен файл
if(!empty($_FILES)) {
    if(!$_FILES['error']) {
        //другие проверки файла - тип, размер и прочее что нужно        
    } else $errors += array_intersect_key($error_message, array_flip(array_keys($_FILES))); //если ошибка загрузки файла
}

//отправляем ошибки клиенту
if($errors) { 
    header('Content-Type: application/json');
    exit(json_encode(['result'=> 'error', 'data'=>  array_values($errors)]));
} else {
    //имитация базы
    $sex = [1 => 'мужчина', 'женщина'];
    $worker = [1 => 'Сергей', 'Иван', 'Николай', 'Антон', 'Виктор'];
    //получаем имя сотрудника запросом к базе по его ID, проверяя заодно есть ли такой
    //здесь проверка имитация, проверяется наличие ключа в $worker
    if(!$name = $worker[$data['worker']]) exit; //выход, нет такого сотрудника, форма левая
    
    //хороший тон, это отправление и текстовой версии, так как неизвестно в каком формате адресат принимает почту
    $text = 'Текстовый вариант';
    //html версия
    $html = "<p><b>Пол:</b> {$sex[$data[sex]]}</p>
    <p><b>E-mail:</b> {$data[email]}</p>
    <p><b>Сотрудник:</b> $name</p>
    <p><b>Сообщение:</b> {$data[message]}</p>";
    
    $to             = 'pochta@mail.ru';
    $subject        = '=?utf-8?b?' . base64_encode($data['subject']) . '?=';
    $headers        = 'From: =?utf-8?B?' . base64_encode($name) . '?= <' . $data['email'] . '>' . PHP_EOL;
    $headers       .= 'Reply-To: receiver@domain3.com' .  PHP_EOL;
    $headers       .= 'X-Mailer: PHP/' . phpversion() . PHP_EOL;
    $headers       .= 'Mime-Version: 1.0' . PHP_EOL;
    $headers       .= 'Content-Type: multipart/alternative; boundary="==boundary-2"' . PHP_EOL.PHP_EOL;
    $body          .= '--==boundary-2' . PHP_EOL.PHP_EOL;
    $body          .= 'Content-type: text/plain; charset="utf-8"' . PHP_EOL;
    $body          .= 'Content-Transfer-Encoding: 8bit' . PHP_EOL.PHP_EOL;
    $body          .= $text . PHP_EOL; //текстовая версия
    $body          .= '--==boundary-2' . PHP_EOL;
    $body          .= 'Content-Type: multipart/related; boundary="==boundary-1"; type="text/html"' . PHP_EOL.PHP_EOL;
    $body          .= '--==boundary-1' . PHP_EOL;
    $body          .= 'Content-type: text/html; charset="utf-8"' . PHP_EOL;
    $body          .= 'Content-Transfer-Encoding: base64' . PHP_EOL.PHP_EOL;
    $body          .= chunk_split(base64_encode($html)) . PHP_EOL.PHP_EOL; //html версия
    $body          .= !empty($_FILES) ? '--==boundary-1' . PHP_EOL : '--==boundary-1--' . PHP_EOL;
    
    if(!empty($_FILES)) {
        $f = fopen($_FILES['file']['tmp_name'], 'rb');
        $body      .= 'Content-Type: image/jpeg' . PHP_EOL; //заголовок произвольный, а вообще нужно проверять тип и его указывать, в случае изображения его можно встроить непосредственно в письмо
        $body      .= 'Content-Transfer-Encoding:base64' . PHP_EOL;
        $body      .= 'Content-Disposition: inline; filename="' . basename($_FILES['file']['name']) . '"' . PHP_EOL.PHP_EOL;
        $body      .= chunk_split(base64_encode(fread($f, filesize($_FILES['file']['tmp_name']))));
		$body      .= '--==boundary-1--' . PHP_EOL;
	}
    
    $body          .= '--==boundary-2--' . PHP_EOL;
    
    mail($to, $subject, $body, $headers);
    
    //функция mail не знает о том отправлено ли письмо или нет, она лишь сообщает о факте его принятия для отправления программой sendmail
    
    header('Content-Type: application/json');
    exit(json_encode(['result'=> 'done', 'data'=>  ['Письмо отправлено']]));
}

А вообще используйте готовые библиотеки, которые более серьезно к этому подходят, например phpmailer. Она отправляет и по SMTP, что не мало важно в нынешнее время, когда не редкость в отказе хостов к доступу функции mail из-за вала спама захлестнувшего почту, только SMTP.

Последний раз редактировалось laimas, 10.11.2020 в 15:37.
Ответить с цитированием