Php как отправить письмо на почту
Перейти к содержимому

Php как отправить письмо на почту

  • автор:

Отправка писем на PHP через SMTP

Отправлять письма через PHP намного проще, чем кажется. Всего-то надо сформировать правильный EML, подключиться к SMTP и отправить письмо. Ну ещё может быть, хотя и не факт, надо где-то как-то залогировать отправку, а то потом потеряют письмо, скажут, что и не было никаких писем. И виноватый опять ты, хотя ты бел и пушист. А ещё бы хорошо сделать хоть какую-то обработку ошибок, а то вдруг эксепшин, или серевер устал, или коннект не пошёл, а тут суперважный клиент. И уж совсем замечательно хранить где-то письма на случай «я потеряль», «мне не дошло», «а вышлите мне ещё раз». А ещё мы хотим отправлять письма на сайте, который видел расцвет динозавров. А ещё. мне кажется, что список ещё может расширяться не хуже нашей вселенной.

Для решения всех этих проблем я решил написать небольшой инструмент — ApMailer.

ApMailer

ApMailer — это небольшая библиотека, единственной целью которой является отправка почты. Я постарался сделать её максимально простой и удобной. Вы можете скачать всего один файл и отправлять письма и из консоли, и из web-скриптов!

Подключение ApMailer

Скачайте из репозитория файл mailer.phar или src/lib.php (если не нужна консольная версия). После этого подключите lib.php:

// Если скачали phar include 'phar:///path/to/mailer.phar/lib.php'; // Если скачали исходный код include '/path/to/lib.php';

После этого будет доступна функция Mailer() :

Mailer()->init(include 'config.php'); $message = Mailer()->newHtmlMessage(); $message->setSubject($messageSubject); $message->setSenderEmail($messageFrom); $message->addRecipient($messageTo); $message->addContent(file_get_contents('mail-header.html')); $message->addContent($messageText); $message->addContent(file_get_contents('mail-footer.html')); $message->addRelatedFile('signature.png'); if (isset($_FILES['attachment']['size']) && $_FILES['attachment']['size'] > 0) < $message->addAttachmentFile( $_FILES['attachment']['tmp_name'], $_FILES['attachment']['name'], $_FILES['attachment']['type'] ); > Mailer()->sendMessage($message);

Инициализация

Перед отправкой писем Mailer надо проинициализировать. Делается это так:

Mailer()->init($config);

Конфиг представляет из себя многомерный массив, в котором указываются адрес отправителя по умолчанию, хуки для обработки ошибок и ведения логов и транспортёры:

$config = [ 'defaultFrom' => 'mymail@example.org', 'onError' => function($error, $message, $transport) < echo $error; >, 'afterSend' => function($text, $message, $layer) < echo $text; >, 'transports' => [ // Сохранение всех писем в папке ['file', 'dir' => __DIR__ .'/mails'], // Отправка писем через Yandex, используя SSL и авторизацию ['smtp', 'host' => 'smtp.yandex.ru', 'ssl' => true, 'port' => '465', 'login' => '****@yandex.ru', 'password' => '******'], ], ];

В качестве транспортов можно использовать file и smtp . Тип транспорёта всегда должен передаваться первым элементом массива, дальше идут его настройки.

Транспортёр file сохраняет письмо в виде EML в папку. Доступны следующие настройки:

  • dir — папка, а которую будут сохраняться письма. Если предполагается много писем, лучше хранить их с разбивкой по дате ‘dir’ => strftime( ‘/path/to/mails/%Y/%m/%d’ )

Транспортёр smtp отправляет письмо через SMTP. Доступны следующие настройки:

  • host — адрес SMTP-сервера
  • ssl — использовать SSL при подключении (обязательно для google, yandex и других популярных сервисов)
  • port — порт подключения (обычно 25 для подключения без SSL и 465 для подклюения с SSL)
  • login — логин для авторизации (если логин не указан, то используется подключение без авторизации)
  • password — пароль для авторизации (не используется, если логин не указан)
  • onError — срабатывает на ошибку транспортёра (удобно делать лог ошибок отправки писем)
  • afterSend — срабатывает после отправки письма (удобно делать общий лог отправки писем)

Настройка defaultFrom нужна, чтобы не указывать каждый раз адрес отправителя. Если система не подразумевает работу нескольких человек, которые могут отсылать почту, то этот адрес обычно постоянный.

Рабочий пример

В качестве примера я сделал форму отправки письма:

Форма отправки письма

Пример письма

Отправка почты на старых версиях PHP

Поскольку библиотека умеет работать через консоль, то можно формировать команду, которая сможет отправлять письма. Единственное, что нужно, наличие скомпилированного бинарника PHP 5.6.

function sendMail($message) < $keys = array( 'subject' => '-s', 'from' => '-f', 'text' => '-t', 'reciient' => array('-r'), 'to' => array('-r'), 'related' => array('-i'), 'attachment' => array('-a'), 'config' => array('-c'), ); $args = array(); // Если отправляют HTML if (isset($message['html'])) < $args[] = '--html'; // Подключаем шаблон $textArray = array(); // Header $textArray[] = ''; if (isset($message['html'])) < $textArray[] = join((array) $message['html']); > // Footer $textArray[] = ''; $message['text'] = join($textArray); > foreach ($keys as $key => $argument) < if (!isset($message[$key])) < continue; > if (is_array($argument)) < $argument = array_shift($argument); foreach ((array) $message[$key] as $value) < $args[] = $argument .' '. escapeshellarg($value); > > else < $args[] = $argument .' '. escapeshellarg($message[$key]); > > $command = 'php5.6 /path/to/mailer.phar '. join(' ', $args); exec($command); >;

А дальше уже можно отправлять письма:

sendMail(array( 'to' => array('someone@exmaple.org', 'someoneelse@exmaple.org'), 'subject' => 'Привет, мир!', 'html' => '

Hello

'
, ));

Работа с PHP mail

Функция PHP mail предназначена для отправки электронной почты, и ее работа осуществляется на нашем хостинге через агент пересылки почтовых сообщений Exim, который установлен на каждом сервере виртуального хостинга.

  • Отправка сообщений
  • Недоступность PHP mail

Отправка сообщений

Чтобы отправить тестовое сообщение, необходимо создать php-скрипт, например, со следующим содержанием:

$message = "Line 1\nLine 2\nLine 3";
$message = wordwrap($message, 70);
var_dump(mail('mail@testdomain.ru', 'My Subject', $message));
?>

В данном примере переменная $message содержит текст письма, а вместо mail@testdomain.ru необходимо указать корректный адрес получателя письма.

Письма отправляются от user@server.timeweb.ru , где user — это ваш логин, а server — имя сервера, на котором расположен аккаунт. Доступ к данному электронному ящику невозможен. Также невозможна DKIM-подпись (цифровая подпись, подтверждающая что письмо отправлено именно с этого адреса) для данного вида писем.

Для того, чтобы в качестве адреса отправителя указывался определенный ящик, необходимо помимо заголовка From передавать почтовому серверу в функции mail аргумент -f :

mail("получатель", "тема", "текст", "заголовки", "-f адрес отправителя")

Дополнительную информацию по данному вопросу можно найти в документации PHP .

Недоступность PHP mail

Доступ к работе с PHP mail может быть заблокирован:

  • на тестовом аккаунте;
  • из-за открытого инцидента по вредоносному коду, фишингу и др.

Проверить, доступны ли почтовые функции для аккаунта, можно при подключении по SSH . Для этого введите команду:

user@server:~$ id
uid=4122(user) gid=600(customers) groups=600(customers)

Такой вывод команды id говорит о том, что почтовые функции доступны.

Подробная информация о данной функции доступна в официальной документации PHP .

Отправка почты средствами PHP

Работая над проектом, мне пришлось создать специфичную «анкету соискателя» в котором надо была отправлять всю анкету на указные за ране e-mail адрес, и я сразу же вспомнил про PHP функцию mail().

bool mail ( string to, string subject, string message [, string additional_headers [, string additional_parameters]]) 
  • E-mail получателя
  • Заголовок письма
  • Текст письма
  • Дополнительные заголовки письма
  • Дополнительные параметры командной строки
  • true, если письмо было принято к доставке
  • false, в противном случае.
Простейший пример
Перейдем к более сложному примеру
Текст письма


1-ая строчка
2-ая строчка
'; $headers = "Content-type: text/html; charset=windows-1251 \r\n"; $headers . ; $headers .= "Reply-To: reply-to@example.com\r\n"; mail($to, $subject, $message, $headers); ?>

В начале мы определяем кому адресовано письмо, за это отвечает переменная &to, если же получателей несколько человек, то записываем через запятую адреса эл. почты.

Переменные $subject и $message, не буду описывать, это и так понятно.

  • В первой строчке ми определяем ты отправляемого письма-HTML и кодировку windows-1251.
  • В 2-ом мы указываем от кого пришло письмо.
  • В 3-ем указываем e-mail адрес, для ответа на письмо.
А теперь самое интересное отправка письма c вложением (attachment)
$subject = "тема письма"; $message ="Текст сообщения"; // текст сообщения, здесь вы можете вставлять таблицы, рисунки, заголовки, оформление цветом и т.п. $filename = "file.doc"; // название файла $filepath = "files/file.doc"; // месторасположение файла //исьмо с вложением состоит из нескольких частей, которые разделяются разделителем $boundary = "--".md5(uniqid(time())); // генерируем разделитель $mailheaders = "MIME-Version: 1.0;\r\n"; $mailheaders .="Content-Type: multipart/mixed; boundary=\"$boundary\"\r\n"; // разделитель указывается в заголовке в параметре boundary $mailheaders . ; $mailheaders .= "Reply-To: $user_email\r\n"; $multipart = "--$boundary\r\n"; $multipart .= "Content-Type: text/html; charset=windows-1251\r\n"; $multipart .= "Content-Transfer-Encoding: base64\r\n"; $multipart .= \r\n; $multipart .= chunk_split(base64_encode(iconv("utf8", "windows-1251", $message))); // первая часть само сообщение // Закачиваем файл $fp = fopen($filepath,"r"); if (!$fp) < print "Не удается открыть файл22"; exit(); >$file = fread($fp, filesize($filepath)); fclose($fp); // чтение файла $message_part = "\r\n--$boundary\r\n"; $message_part .= "Content-Type: application/octet-stream; name=\"$filename\"\r\n"; $message_part .= "Content-Transfer-Encoding: base64\r\n"; $message_part .= "Content-Disposition: attachment; filename=\"$filename\"\r\n"; $message_part .= \r\n; $message_part .= chunk_split(base64_encode($file)); $message_part .= "\r\n--$boundary--\r\n"; // второй частью прикрепляем файл, можно прикрепить два и более файла $multipart .= $message_part; mail($to,$subject,$multipart,$mailheaders); // отправляем письмо //удаляем файлы через 60 сек. if (time_nanosleep(5, 0)) < unlink($filepath); >// удаление файла 

Функция mail() — самый простой способ отправить письмо с помощью PHP

Для связи с пользователями сайта (и некоем подобии контроля над ними) бывает полезно отправлять им письма с сайта. Например, при регистрации нового пользователя (чтобы они не плодились как кролики в урожайный год для моркови и капусты), можно просить указать их адрес электронной почты, выслать на этот адрес какой-то код и, пока этот код не будет введён на сайте, не считать пользователя зарегистрированным. В PHP есть удобная функция mail() для отправки сообщений на электронную почту. Простейший вариант отправки email с помощью этой функции рассмотрим в этой статье.

Работающий php-скрипт для отправки письма с помощью функции mail()

Как обычно, сперва приведу код программы на php, а потом объясню: как и что работает.

  








[email protected]' . "\r\n" . 'Reply-To: [email protected]' . "\r\n" . 'X-Mailer: PHP/' . phpversion(); if (isset($_POST['to']) && isset($_POST['subject']) && isset($_POST['message'])) if (mail($_POST['to'], $_POST['subject'], $_POST['message'], $headers)) < echo 'письмо было принято для передачи'; > else < echo 'что-то пошло не так. '; > ?>

Форма для получения данных, которые нужно отправить по электронной почте

Первые 10 строк кода, приведённого выше — это HTML-форма, в которую вводим email, куда будем отправлять письмо, тему письма и собственно сам текст письма. Это поля с именами to , subject и message .

Ниже идёт php-код, обрабатывающий полученные данные из этой формы и, если все поля заполнены, пытается отправить письмо на указанный адрес электронной почты.

PHP функция mail()

Перед тем, как рассматривать код, разберёмся вкратце с php-функций mail() , которая присутствует во всех версиях php и имеет следующий формат:

mail ( string $to , string $subject , string $message [, mixed $additional_headers [, string $additional_parameters ]] ) : bool
  • в первой строковой переменной $to должен содержаться получатель или список получателей письма в формате, описанном в RFC 2822, например,
    • [email protected]
    • [email protected], [email protected]
    • User <[email protected]>
    • User <[email protected]>, Another User <[email protected]>

    Это если вкратце.

    Стоит ещё обратить внимание на то, какие значения возвращает функция mail() : возвращает TRUE , если письмо было принято для передачи, иначе FALSE . Так можно отслеживать, что что-то пошло не так при попытке отправить сообщение на электронную почту.

    Дополнительные заголовки функции mail() для того, чтобы письмо сразу не попадало в спам

    Вернёмся к нашему коду. В строчках 13..14 в переменную $headers мы как раз записываем три заголовка:

    • From — адрес отправителя (можно подставить какое угодно мыло, но лучше своё) =)
    • Reply-To — адрес, который подставится почтовой программой при попытке получателя ответить на это сообщение.
    • X-Mailer — поможет для того, чтобы отследить, кто (какая программа) отправила письмо. Бывает полезно для отлова и отстрела спамеров.

    Отправка письма функцией mail() с предварительной проверкой полей перед отправкой

    В 16-й строке проверяем, что все поля заполнены. Более полную проверку на соответствие всем требованиям RFM всех заголовков пока писать лень. Кому интересно, могут почитать про валидацию электронной почты (email) из данных формы на стороне сервера с помощью php в → этой статье.

    В 17-й строке запускаем функцию mail() и. письмо полетело.

    • если полёт нормальный, в 18-й строке выводим зелёное сообщение о том, что всё хорошо;
    • если при попытке передать письмо возникли проблемы: функция mail() вернула значение FALSE , сообщаем об этом.

    Резюме

    Таким образом можно достаточно легко и быстро отправлять сообщения с помощью php-функции mail() , подписываясь Санта Клаусом, Кукусклановцем или Биллом Гейтсом. Но, надеюсь, что прочитав эту статью, никто не решил стать ещё одним рассыльным почтового спама. Для этого нужно знать немного больше. 😉

    Но этих сведений будет достаточно, чтобы отправить письмо с сайта пользователю со ссылкой подтверждения регистрации. Что и требовалось. =D

    Заберите ссылку на статью к себе, чтобы потом легко её найти!
    Раз уж досюда дочитали, то может может есть желание рассказать об этом месте своим друзьям, знакомым и просто мимо проходящим?
    Не надо себя сдерживать! 😉

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *