Программно отправить html-почту. Как?
- Блог
- Войдите или зарегистрируйтесь, чтобы отправлять комментарии
Программно отправить html-почту. Как?
Содержимое сайта публикуется на условиях CreativeCommons Attribution-ShareAlike 3.0 или более поздней версии. Программные коды в тексте статей — на условиях GNU GPL v2 или более поздней версии.
Документация по совместной работе с репозиторием drupal.ru – https://docs.drupal.ru/code
Drupal – торговая марка Дриса Бёйтарта
Комментарии
Базовый подход (рекомендуется)
1. Реализовать hook_mail()
В любом кастомном модуле (например, my_module.module):
<?phpuse Drupal\Core\Mail\MailFormatHelper; /**
* Implements hook_mail().
*/
function my_module_mail($key, &$message, $params) {
switch ($key) {
case 'html_mail':
$message['subject'] = $params['subject']; // HTML-тело письма
$message['body'][] = $params['body']; // ВАЖНО: указываем HTML
$message['headers']['Content-Type'] = 'text/html; charset=UTF-8';
break;
?>}
}
2. Отправить письмо программно
<?php$mailManager = \Drupal::service('plugin.manager.mail'); $module = 'my_module';
$key = 'html_mail';
$to = 'user@example.com';
$langcode = \Drupal::currentUser()->getPreferredLangcode(); $params = [
'subject' => 'HTML письмо из Drupal 10',
'body' => '
<h1>Здравствуйте!</h1>
<p>Это <strong>HTML-письмо</strong>, отправленное программно.</p>
',
]; $send = TRUE; $result = $mailManager->mail($module, $key, $to, $langcode, $params, NULL, $send);
if (
$result['result'] !== TRUE) {\Drupal::logger('my_module')->error('Ошибка отправки письма.');
} ?>
1. HTML по умолчанию может быть «сломано»
Drupal по умолчанию экранирует HTML, если не используется HTML-mailer.
2. Для 100% корректной HTML-почты рекомендуется модуль
Swiftmailer больше не поддерживается. В Drupal 10 рекомендуется:
Symfony Mailer (Core ≥ 10.1)
Mime Mail
HTML Mail
На практике чаще всего используют HTML Mail + Symfony Mailer.
Вариант 2. Чистый Drupal (без модулей)
<?phpuse Drupal\Core\Mail\MailManagerInterface;
use Drupal\Core\Language\LanguageManagerInterface; $mailManager = \Drupal::service('plugin.manager.mail');
$langcode = \Drupal::languageManager()->getDefaultLanguage()->getId(); $params = [];
$params['subject'] = 'HTML письмо';
$params['message'] = '
<h1>Заголовок</h1>
<p>Это <strong>HTML-письмо</strong></p>
'; $result = $mailManager->mail(
'mymodule',
'html_mail',
'test@example.com',
$langcode,
$params,
NULL,
TRUE
); ?>
Реализация hook_mail()
<?php/**
* Implements hook_mail().
*/
function mymodule_mail($key, &$message, $params) {
switch ($key) {
case 'html_mail':
$message['subject'] = $params['subject'];
$message['body'][] = $params['message']; // ВАЖНО: HTML-заголовки
$message['headers']['Content-Type'] = 'text/html; charset=UTF-8';
break;
}
} ?>
Вариант 3 . HTML Mail + Symfony Mailer
Если что непонятно, надо сделать. Стучите в личку, накалякаем Mail 1
Вы это делали?
Что значит программно? Ну есть модули для отправки почты. Что нужно и чем не устраивают?
Вы правда не понимаете?
это значит
так формулируется запрос в поисковике
можно также убедиться в формулировке на https://www.learndrupalway.com/blog/how-send-email-drupal-10-programmati... к примеру
Для Drupal 10. Но думаю заработает на версии от 8 и выше. Просто не тестировал на остальных версиях.
Можно использовать компоненты симфони, которые уже имеются в друпале. Дополнительные модули не нужны. Ниже пример сервиса по отправке писем. Так же поддерживается отправка файлов по почте.
<?php
namespace Drupal\oc_settings\Service;
use
Symfony\Component\Mailer\Transport;use Symfony\Component\Mailer\Mailer;
use Symfony\Component\Mime\Email;
use Symfony\Component\Mime\Part\DataPart;
use Symfony\Component\Mime\Part\File;
class
Mail {private $mailer;
private $mailSettings;
public function
__construct(){
$cnf = unserialize(\Drupal::state()->get('site_settings', '')); $this->mailSettings = [
'smtp_user' => $cnf['smtp_user'],
'smtp_password' => $cnf['smtp_password'],
'smtp_server' => $cnf['smtp_server'],
'smtp_port' => $cnf['smtp_port'],
'common_email' => explode(',', $cnf['common_email'])
];
if(isset(
$this->mailSettings['smtp_user'])){$dsn = 'smtp://' . urlencode( $this->mailSettings['smtp_user'] );
$dsn .= ':' . urlencode( $this->mailSettings['smtp_password'] );
$dsn .= '@' . $this->mailSettings['smtp_server'];
$dsn .= ':' . $this->mailSettings['smtp_port']; $transport = Transport::fromDsn($dsn);
$this->mailer = new Mailer($transport);
}
} /**
* Пример массива для отправки письма
*
* $params = [
* 'to' => '<Кому отправляем>',
* 'subject' => '<Тема письма>',
* 'message' => '<HTML письмо>',
* 'files' => [
* <Абсолютный путь к файлы>,
* <Абсолютный путь к файлы>
* ]
* ];
*/
public function sendEmail($params)
{
$emails = isset($params['to']) ? [$params['to']] : $this->mailSettings['common_email'];
foreach($emails as $email){
if(empty(trim($email))){
continue;
} $email = (new Email())
->from( $this->mailSettings['smtp_user'] )
->to(trim($email))
->subject($params['subject'])
->html($params['message']);
if(isset(
$params['files'])){foreach($params['files'] as $absolutePath){
$email->addPart(new DataPart(new File( $absolutePath )));
}
} $this->mailer->send($email);
}
}
}
?>
Пример использования:
\Drupal::service('oc_settings.mail')->sendEmail($params);
Это же заготовка. Пусто. Рыба.
Вы точно это проверяли?
Это код с сайта одного из моих клиентов, в том году писал этот код. Проверен много раз.
Обратите внимание на эту строку:
$cnf = unserialize(\Drupal::state()->get('site_settings', ''));
Это идет получение настроек SMTP. У вас эта строка работать не будет, вам нужно в переменную $dsn заполнить своими данным о SMTP.
Спасибо. Как проверю - обязательно отпишусь. Спасибо.
Дело в том, что начальство снизошло до разрешения mail() на сервере - А с mail() проблем вообще - Ноль.
Но ваше решение - если оно рабочее - изменит подход. Что принесёт пользу Великой России.
Спасибо.
Посмотрел внимательно этот код. Но он ведь требует от меня данные стороннего почтового сервера. Так?
Если отправлять с стороннего почтового сервера(Яндекс например) - то зачем Симфони и Друпал?
Да, верно. Вам нужны данные от стороннего сервиса для отправки через протокол SMTP. В качестве SMTP можно использовать любой сервис, яндекс, гугл, маил.ру или свой собственный, если такой имеется. Это бесплатно.
Зачем тогда нужен друпал? Он дает команду удаленному почтовому серверу отправить письмо и передает ему это письмо. Вот этим и занимается представленный код.
Зачем нужен Симфони? Используем готовый код симфони, который берет на себя все заботы по подготовке письма(заголовки, кодировка и много чего еще) перед отправкой на SMTP сервер. Симфони описывает в коде серию стандартов RFC xxxx по работе с почтой.
Если у вас есть возможность, вы можете поднять свой собственный почтовый сервер и указать его SMTP данные. У меня такой возможности нет, это отдельная область знаний)
Если немного углубится в работу почты, то глобально на сайтах используются 2 метода отправки писем:
1 метод, это php функция mail(). Друпал ее по умолчанию использует.
Не надежный способ, письма в большинстве своем уходят в спам или не покидают сервера. Отказался от этого способа около 5 лет назад.
2 метод использовать протокол SMTP.
100% доставляемость писем, если только ваш почтовый домен не в черном списке. Хотел бы отметить, что нужно оформить DKIM и DMARC записи для почтового домен. Так же SPF запись, для защиты почтового домена.
///2 метод использовать протокол SMTP.///
Вся, практически вся почта отправляется по SMTP
///Если у вас есть возможность, вы можете поднять свой собственный почтовый сервер и///
Чтоб отправить почту программно с стороннего почтового сервера - не нужно ничего. 40 размашистых строк кода и ни одной библиотеки.
Почему так перегружены коды отправки - мне не ведомо.
Вам написали 2 варианта решения проблемы в рамках системы друпал. Через hook_mail() и через классы симфони. Можете выбрать один из двух или написать свое решение. Все же просто, не понимаю в чем проблема Smile
Вы правда - не понимаете?
Проблема в том, что при решении через сторонний почтовый сервер - никакой Друпал не нужен.
Правда не понимаю, по этому и спрашиваю)
Как вижу пути решения:
1. Используем стандартную php функцию mail(). Ее работа сводится к тому, что она отдает команду на отправку письма локальному агенту, как правило sendmail в юникс системах. Локальный агент уже через протокол smpt отправляет задачу на почтовый сервер.
Про использование функции mail() я писал, что это не надежно.
2. Через соккеты на php. Сам такое не делал, но код изучал ради интереса. Как то мне это показалось слишком замысловатым.
3. Используем готовые библиотеки/классы. В моем примере это симфони. Ну это же максимально просто выходит, разве нет? Сама функция отправки буквально 5-7 строк. Всю низкоуровневую реализацию smtp протокола на себя берт симфони.
Я не могу все знать, могу ошибаться. По этому интересно в чем проблема и если проблема есть, то как бы вы решили?
Через сокеты на php.
Если только ради опыта, почему бы нет Smile
Для коммерческого продукта я бы не стал.
почему?
Я почти уверен, что если посмотреть код тех Друпало-Симфони библиотек - там именно сокетами всё и закончится.
Потому как ничего другого то и нет, как вы справедливо написали в двух первых пунктах выше.
Да, в этих библиотеках и многих других используются сокеты. Тут же дело в другом.
Причина No 1 - надежность.
Что такое симфони или друпал ? Это продукты, которые существуют и развиваются много лет. За годы их существования было исправлено куча багов, в том числе и с отправкой почты. Сейчас мы имеем возможность пользоваться состоявшимися продуктами, которые превосходно решают задачи.
Причина No2 - деньги и время.
Что нужно, что бы отправлять почту через сокеты? Нужно реализовать хотя бы в базовой основе протокол SMTP. Вот условно вам приходит заказ, реализовать отправку почты за условные 5 т.р.. Перед вами стоит выбор. Сделать быстро через компоненты симфони/друпала или реализовать через сокеты с учетом стандартов RFC xxxx, их там не один используется для работы протокола smtp и оформления почты. Так же сколько уйдет времени на отладку почты, отправляемой через сокеты.
Достаточно посмотреть в исходный код симофни/друпала, становится сразу понятно, что это задача с кучей подводных камне.
Причина No 3 - зачем изобретать велосипед.
Повторюсь. Для спортивного интереса можно поиграть с сокетами, но в коммерческий продукт выбираю отлаженные решения.
к 3-му:
Там уже не велосипед. Там уже Ядрёный двигатель к велосипеду зачем то прикручен. А нужно просто почту отправить.
Нашёл ещё способы:
4. Через API специальных сайтов. Соединяешься с ними по curl - и всё.
5. Curl.
6. Еще можно через Почту России
7. Через СДЭК
Шучу конечно Smile
Если у вас сайт на друпал или на симфони сделан, почему нельзя использовать уже готовые компоненты данных систем? Они же вот у вас в папке с сайтом уже находятся :).
Мне вот чем нравится космоспец - своей несгибаемостью. Он с железобетонным упрямством остаётся преданным процедурной парадигме и философии Drupal 7 и во всех бедах винит "плохой новый" Друпал в ветках ^8.x. А не массу очевидных явлений/свойств своей личности - ведь так поступают только слабаки.
Так держать! Даёшь культ ретроградства! Нет - излишествам и новшествам, выходящим за рамки усвоенного процесса кодинга! Напридумали всякой дребедени, геи-буржуи.
если куча "геев-буржуев" хавает из чана гавно, не зная из-за необразованности, что рядом есть вкусная и простая хавка - инвиняйте, но я не буду хавать гавно.
Что вы ноете всё? Вам дали самое простое решение (пп.1 + 2) в самом первом ответе. Готовый каркас, только меняйте/подставляйте свой код.
hook_mail+\Drupal::service('plugin.manager.mail')- это всегда рабочее решение.К слову, я использую на некоторых сайтах примерно схожую конструкцию. Только я обычно расширяю
\Drupal::service('plugin.manager.mail')в кастомном классе сервиса.Про "говно" я промолчу. В некоторых
(削除) известных (削除ここまで)случаях процедурный код напоминает именно эту субстанцию WinkДрупал, считаю, не нужен. Если кому то хочется отправлять почту, отправляйте в удобном почтовом сервисе. Все бесполезные формы, вроде "Перезвоните мне", "Обратный звонок", "Оставить заявку" нужно удалить. Вместо этого, показать клиенту почту или телефон. Пусть сам пишет и звонит, нечего лениться.
Если бы все так было просто Smile
Давайте просто и сурово будем писать код и сравнивать. Я сейчас оптимизирую сокеты и скажу что там по чём.
50 строк - как я и говорил. Никаких проблем. Полное владение ситуацией отправки
Во Входящих - не в Спаме
HTML письмо.
Что сейчас вижу? Код в котором легко допустить ошибку, код который не учитывает разные состояния отправки писем, код который не обрабатывает ошибки, код который не дает гарантии отправки писем на разные почтовые службы, код без реализации отправки вложений. Код в такой стилистике я много вижу на WordPress, к сожалению приходится работать с этой системой в рамках моих трудовых обязанностей.
В будущем, вы же на сайте данный код обернете в функцию, что бы его переиспользовать в разных частях сайта. В дальнейшем добавите поддержку вложений, добавите обработку ошибок и многое многое еще чего, чтобы код был надежен и функционален. В итоге у вас получится своя собственная библиотека по отправке почты. Так и вопрос, зачем городить велосипед? Я правда не понимаю вашей логики, в чем смысл такого подхода в работе? Smile
Разработка это баланс между тремя ценностями - цена, время и качество. Представьте, это как треугольник, где на каждой вершине по одной ценности. Так вот баланс в разработке, это быть в центре треугольника.
Я видел на форуме, вы работаете за 200 р. час, это не большая цена по рынку. Так же вы готовы вкладывать временя в написание кода, который уже есть в друпале. Это прямой путь к ухудшению качества в работе. Баланс нарушается.
Если мои слова вас обижают, то я извиняюсь. У меня нет цели обидеть или оскорбить вас или кого либо.
///Так же вы готовы вкладывать временя в написание кода, который уже есть в друпале. Это прямой путь к ухудшению качества в работе. Баланс нарушается.///
Я не увидел здесь ни одного готового к работе кода - кроме моего.
В конце концов я наверное всё таки сам попытаюсь их запустить и сравнить.
/// В дальнейшем добавите поддержку вложений,///
По моему задача чётко поставлена в заголовке. Никаких Вложений там даже близко нет
Забавно Smile
По каким параметрам хотите сравнить? Правда интересно.
Про вложения это предположение. Живые проекты всегда развиваются и обрастают функционалом. По этому предположил, что в будущем понадобится возможность отправлять вложения.
///По каким параметрам хотите сравнить? Правда интересно.///
Для меня важна - Простота использования и чтоб работало везде где не закрыты порты.
Простота использования - это отсутствие сторонних библиотек, в том числе.
=============
У меня на хостинге прекрасно работает mail(), но полностью закрыты порты для почты.
Как запускать ваши программы - пока не придумал.
А Локально - есть только php/
Ээээ, космоспец таки знатный тролль! Вброс на три рубля, а сколько в ответ поводов для беспредметного спора, брюзжания и нытья. Smile
Тема создана для очередного развлечения автора. Весь конструктив закончился примерно после первых приведённых (и вполне соответствующих запросу) ответов, дальше покатили обычные проклятия, вызовы, жалобы и стенания космического специалиста. ) Типичный шаблон: я против этого, поэтому что этого не понимаю или не знаю, но если вы не разжуете мне всё или не дадите готовое и понятное мне решение, то Друпал - отстой. Причём, на ус-то он кое-что всё-таки мотает, только не признаётся. Это не подобает самодостаточному мужчине ))
Ну что, отвёл душу? По существу: займись уже делом, ёмана. Почитай мануалы и документацию, там много интересного.
По curl отправить письмо не удалось - ни локально, ни с сервера. Локально - требует сертификаты. А с сервера - просто не дошло. Почему - не понятно.
В коде - те-же 50 строк что и в Сокетах, а заморочек - гораздо больше.
6. Способ отправки - PHPMailer. Это работает где открыт порт и установлен PHPMailer. Установлен не везде. - Это обидно, так-как там всё до боли просто и укладывается в 40 строк.
Ура! У нас есть победитель. Это - конечно же я.
Вы проиграли во всем :). Я не буду объяснять свою точку зрения, просто примите это.
Хм. Эта штука работает возле Друпала - это точно. А в Друпале то она работает?
Какой же ты всё-таки наркоман.