Тема: Exim php заголовки писем
Exim php заголовки писем
Сообщение от art
И еще один вопрос возник. (если он не по этой ветке, то перенесите, пожалуйста сообщение). По отправке сообщений из установленного пакета Exim 4.69:
Если сообщения отправляются через SMTP-сервер какой-либо учетной записи на сервере при помощи почтового клиента (например The Bat), то формируются нормальные заголовки писем.
А при отправки сообщений через ту же учетную запись, но непосредственно с сайта, расположенного на нашем сервере, либо просто при помощи php-функции mail() формируется лишний заголовок «Перенаправлено» от пользователя «www-data«. Т.е. получается вместо нормального:
Return-Path:
Received: from our-hosting.ru ([87.118.86.87]) by mx.google.com .
Received: from www-data by our-hosting.ru with local (Exim 4.69)
Sender: www-data
Подскажите, пожалуйста, как избавиться от этой строки? Какие настройки за это отвечают и где они находятся?
Хотелось бы чтобы и Return-Path не перезаписывался на www-data@our-hosting.ru, когда заменяем его на нужный (например, на return-mail@one-site.ru).
Если я правильно понимаю, то от пользователя www-data работает апач, но как эти настройки связаны с отправкой почты, не совсем ясно.
php в вашем случае запускает же апач. Вот от туда и вылезает. в php.ini есть параметр sendmail_path в котором через аргумент -f можно указать from и в самом скрипте можно генерировать заголовки return_path.
Или все равно перезаписываются?
Обработка входящей почты через PHP (debian, postfix, php)
Предполагается, что был установлен POSTFIX и включен SMTP (для входящей почты нужны только MX-запись, SMTP и TLS, остальное настраивать необязательно).
MX-запись ¶
Чтобы письма приходили на сервер, нужно чтобы на него ссылалась MX-запись. Проверяем, настроена ли MX-запись:
Если записи нет, нужно зайти в панель управления доменом и добавить её.
Настройки POSTFIX ¶
Все команды необходимо выполнять в консоли от суперпользователя.
Редактируем конфиги POSTFIX’а, чтобы принимать письма и передавать внешнему обработчику:
sed -i -E '/^#?smtp .*smtpd.*/' /etc/postfix/master.cf cat >> /etc/postfix/master.cf EOF ## Обработка входящей почты myhook unix - n n - - pipe flags=F user=www-data argv=/var/www/mail/save.php \$ \$ EOF cat >> /etc/postfix/main.cf EOF # Карты алиасов alias_maps = hash:/etc/aliases alias_database = hash:/etc/aliases # Разрешаем приём писем для всех local_recipient_maps = # Пересылаем все письма руту luser_relay = root@\$mydomain EOF newaliases service postfix restart
После этого все письма будут передаваться в стандартный поток скрипту /var/www/mail/save.php . Задача скрипта обработать письмо и ничего не вывести в стандартный поток, чтобы письмо дальше не пошло.
Скрипт для сохранения почты ¶
Хранить письма будем в базе данных mail , а загружать через PHP.
Устанавливаем необходимые пакеты:
# База данных MariaDB apt install mariadb-server # Пакеты PHP apt install php-cli php-mysql php-mbstring php-imap php-mailparse
Предполагается, что установится версия PHP не ниже 7.3 (стандартная версия для Debian 10).
База данных ¶
Создаём базу данных и пользователя:
mysql SQL -- База данных CREATE DATABASE IF NOT EXISTS mail; -- Пользователь test с паролем test для базы mail GRANT ALL PRIVILEGES ON mail.* TO test@localhost IDENTIFIED BY 'test'; SQL
mysql mail SQL -- Метаданные входящих писем CREATE TABLE IF NOT EXISTS mail_inbox ( id int(1) unsigned NOT NULL PRIMARY KEY AUTO_INCREMENT COMMENT 'Идентификатор записи', meta json NOT NULL COMMENT 'Метаданные входящих писем в формате JSON', creation_time timestamp NOT NULL DEFAULT current_timestamp() COMMENT 'Время создания записи' ) DEFAULT CHARSET=utf8mb4 COMMENT='Входящие письма (метаданные)'; -- Сами письма CREATE TABLE mail_inbox_data ( id int(1) unsigned NOT NULL PRIMARY KEY COMMENT 'Идентификатор записи', data mediumblob NOT NULL COMMENT 'Данные хранилища' ) DEFAULT CHARSET=utf8mb4 COMMENT='Входящие письма (данные)'; SQL
В таблице mail_inbox будут храниться общие данные о письме (кто, кому, когда и т.д.), а само письмо будет в таблице mail_inbox_data .
Скрипты PHP ¶
Создайте папку для хранения файлов-обработчиков:
Создайте в папке следующие файлы:
Файл .init.php
function Db( ) : PDO < static $db = null; if (is_null($db)) < $db = new PDO('mysql:dbname=mail;host=localhost', 'test', 'test', [ PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION ]); > return $db; > function Db_quote_name($name) : string < return '`' . $name . '`'; > function Db_quote_names($names) : array < return array_map('Db_quote_name', (array) $names); > function Db_save(string $table, array $fields) < $keys = array_keys($fields); $values = array_fill(0, count($keys), '?'); $sql = 'INSERT INTO ' . Db_quote_name($table) . ' ( ' . join(', ', Db_quote_names($keys)) .' ) VALUES (' . join(', ', $values) . ')'; Db()->prepare($sql)->execute(array_values($fields)); return Db()->lastInsertId(); > function Db_select_value(string $table, string $field, string $where) < $sql = 'SELECT ' . Db_quote_name($field) . ' FROM ' . Db_quote_name($table) .' WHERE ' . $where . ' LIMIT 1'; return Db()->query($sql)->fetch()[0] ?? null; >
Файл save.php
#!/usr/bin/env php ob_start(); include '.init.php'; $smtpSender = $argv[1] ?? null; // Отправитель, который был указан при передаче письма $smtpRecipient = $argv[2] ?? null; // Получатель, который был указан при передаче письма $headers = []; $mailBody = null; $prevLine = null; // Собираем заголовки while (($line = fgets(STDIN)) !== false) < if (trim($line) === '') < $mailBody = ltrim(stream_get_contents(STDIN)); break; > if (empty($prevLine)) < $prevLine = $line; continue; > if (preg_match('/^\s/', $line)) < $prevLine .= $line; continue; > $headers[] = $prevLine; $prevLine = $line; > if ($prevLine) < $headers[] = $prevLine; >if (empty($headers)) < return; > // Целое письмо $data = join('', $headers) . "\r\n" . $mailBody; // Парсим заголовки $rfc822Headers = imap_rfc822_parse_headers(join('', $headers)); // Состсавляем метаданные $meta = [ 'smtpSender' => $smtpSender, 'smtpRecipient' => $smtpRecipient, 'from' => mb_decode_mimeheader($rfc822Headers->fromaddress ?? ''), 'replyto' => mb_decode_mimeheader($rfc822Headers->reply_toaddress ?? ''), 'recipient' => mb_decode_mimeheader($rfc822Headers->toaddress ?? ''), 'subject' => mb_decode_mimeheader($rfc822Headers->subject ?? ''), 'size' => strlen($data), ]; // Сохраняем метаданные $id = Db_save('mail_inbox', [ 'meta' => json_encode($meta, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), ]); // Сохраняем письмо Db_save('mail_inbox_data', [ 'id' => $id, 'data' => $data, ]); ob_end_clean(); // Передаём информацию в лог fputs(STDERR, 'Saved to db with id #' . $id . PHP_EOL);
Файл view.php
#!/usr/bin/env php include '.init.php'; $mailId = $argv[1] ?? null; // Идентификатор письма $meta = Db_select_value('mail_inbox', 'meta', 'id = ' . intval($mailId)); if (!$meta) < die("Mail #$mailId not found\n"); > // Данные письма $meta = json_decode($meta, true); $itemData = Db_select_value('mail_inbox_data', 'data', 'id = ' . intval($mailId)); // Парсим письмо $msg = mailparse_msg_create(); mailparse_msg_parse($msg, $itemData); $text = null; $html = null; $images = []; $headers = mailparse_msg_get_part_data($msg)['headers']; $ids = []; foreach (mailparse_msg_get_structure($msg) as $section) < $part = mailparse_msg_get_part($msg, $section); $data = mailparse_msg_get_part_data($part); $contentType = $data['content-type'] ?? ''; $contentId = $data['content-id'] ?? null; if ($contentType == 'text/html') < $html = mailparse_msg_extract_part($part, $itemData, null); > elseif ($contentType == 'text/plain') < $text = mailparse_msg_extract_part($part, $itemData, null); > elseif (preg_match('~image~', $contentType)) < if ($contentId) < $images[$contentId] = [$section, $contentType]; $ids[] = preg_quote($contentId); >> > // Выводим метаданные print_r($meta); // Тело письма if ($html) < // Вставляем картинки $html = preg_replace_callback('~cid:(' . join('|', $ids) . ')~ui', function ($matches) use ($itemData, $images, $msg) < $id = $matches[1]; $part = mailparse_msg_get_part($msg, $images[$id][0]); $data = mailparse_msg_extract_part($part, $itemData, null); return 'data:' . $images[$id][1] . ';base64,' . base64_encode($data); >, $html); echo $html; > elseif ($text) < echo $text; > else < echo 'No data to view'; > echo PHP_EOL; mailparse_msg_free($msg);
Устанавливаем правильные права на файлы:
chmod -R a+r /var/www/mail chmod a+x /var/www/mail/*
$ /var/www/mail/save.php sender@test recipient@test EML From: "test" To: "test" Subject: Test SMTPS This is just a test mail EML Saved to db with id #1 $ /var/www/mail/view.php 1 Array ( [smtpSender] => sender@test [smtpRecipient] => recipient@test [from] => test test@example.org> [replyto] => test test@example.org> [recipient] => test test@example.com> [subject] => Test SMTPS [size] => 109 ) This is just a test mail
Теперь можно отправлять письма через обычную почту (если настроена MX-запись) и смотреть логи:
$ tail /var/log/mail.log -f | grep myhook Aug 7 18:39:12 test postfix/pipe[15894]: 63C373FECF: to=test@test.anton-pribora.ru>, relay=myhook, delay=0.78, delays=0.65/0.02/0/0.1, dsn=2.0.0, status=sent (delivered via myhook service (Saved to db with id #6)) Aug 7 18:40:12 test postfix/pipe[15894]: B30663FE5A: to=test@test.anton-pribora.ru>, relay=myhook, delay=438, delays=438/0.01/0/0.06, dsn=2.0.0, status=sent (delivered via myhook service (Saved to db with id #7))
Отправить JSON с одного сервера и получить на другом сервере
Здравствуйте. Я передаю массив JSON с одного сервера, например, www.example1.com, и хочу получить эти данные на другом сервере, например, www.example2.com/test.php. Я пробовал это с помощью cURL, но я не получаю эти данные при получении. Ниже мой код
Код отправителя
$send_data = json_encode($myarray); $request_url = 'www.example2.com/test.php'; $curl = curl_init(); curl_setopt($curl, CURLOPT_URL, $request_url); curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); curl_setopt($curl, CURLOPT_POST, true); curl_setopt($curl, CURLOPT_POSTFIELDS, 'send_data='.$send_data); $response = curl_exec($curl); $curl_error = curl_error($curl); curl_close($curl);
Код у получателя
Как мне получить данные в конце получателя.
Решение
$request_url = 'www.example2.com/test.php'; $curl = curl_init( $request_url ); # Setup request to send json via POST. $send_data = json_encode($myarray); curl_setopt( $curl, CURLOPT_POSTFIELDS, $send_data ); curl_setopt( $curl, CURLOPT_HTTPHEADER, array('Content-Type:application/json')); # Return response instead of printing. curl_setopt( $curl, CURLOPT_RETURNTRANSFER, true ); # Send request. $result = curl_exec($curl); curl_close($curl); # Print response. echo "
$result";
на вашей второй странице вы можете перехватить входящий запрос, используя file_get_contents («example1.com/sender.php»), который будет содержать POST-файл json. Чтобы просмотреть полученные данные в более удобочитаемом формате, попробуйте это:
echo '
'.print_r(json_decode(file_get_contents("example1.com/sender.php")),1).'';
Другие решения
'This is response1', 'response2' => 'This is response2', $_POST)); ?>
'postVar1'); $curl = curl_init(); curl_setopt($curl, CURLOPT_URL, $request_url); curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); curl_setopt($curl, CURLOPT_POST, true); curl_setopt($curl, CURLOPT_POSTFIELDS, 'sendData=' . http_build_query($sendData)); print_r($response = curl_exec($curl)); curl_close($curl); ?>
Вы получите объект JSON в качестве ответа cURL.