1. Главная
  2. Форумы
  3. Техподдержка Drupal
  4. Решение проблем

Программно отправить html-почту. Как?

Главные вкладки

Лучший ответ

Комментарии

Аватар пользователя ignatev ignatev 25 января в 1:22

Базовый подход (рекомендуется)
1. Реализовать hook_mail()
В любом кастомном модуле (например, my_module.module):

<?php
use 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 (без модулей)

<?php
use 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

Аватар пользователя ignatev ignatev 25 января в 22:32

это значит

drupal 10 send html message programmatically

так формулируется запрос в поисковике
можно также убедиться в формулировке на https://www.learndrupalway.com/blog/how-send-email-drupal-10-programmati... к примеру

Аватар пользователя kosskren kosskren 26 января в 17:47

Для 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);

Аватар пользователя kosskren kosskren 26 января в 20:54

Это код с сайта одного из моих клиентов, в том году писал этот код. Проверен много раз.

Обратите внимание на эту строку:
$cnf = unserialize(\Drupal::state()->get('site_settings', ''));

Это идет получение настроек SMTP. У вас эта строка работать не будет, вам нужно в переменную $dsn заполнить своими данным о SMTP.

Аватар пользователя kompospec kompospec 26 января в 21:16

Спасибо. Как проверю - обязательно отпишусь. Спасибо.
Дело в том, что начальство снизошло до разрешения mail() на сервере - А с mail() проблем вообще - Ноль.
Но ваше решение - если оно рабочее - изменит подход. Что принесёт пользу Великой России.
Спасибо.

Аватар пользователя kompospec kompospec 1 февраля в 22:30

Посмотрел внимательно этот код. Но он ведь требует от меня данные стороннего почтового сервера. Так?

Если отправлять с стороннего почтового сервера(Яндекс например) - то зачем Симфони и Друпал?

Аватар пользователя kosskren kosskren 2 февраля в 8:15

Да, верно. Вам нужны данные от стороннего сервиса для отправки через протокол SMTP. В качестве SMTP можно использовать любой сервис, яндекс, гугл, маил.ру или свой собственный, если такой имеется. Это бесплатно.

Зачем тогда нужен друпал? Он дает команду удаленному почтовому серверу отправить письмо и передает ему это письмо. Вот этим и занимается представленный код.

Зачем нужен Симфони? Используем готовый код симфони, который берет на себя все заботы по подготовке письма(заголовки, кодировка и много чего еще) перед отправкой на SMTP сервер. Симфони описывает в коде серию стандартов RFC xxxx по работе с почтой.

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

Если немного углубится в работу почты, то глобально на сайтах используются 2 метода отправки писем:

1 метод, это php функция mail(). Друпал ее по умолчанию использует.
Не надежный способ, письма в большинстве своем уходят в спам или не покидают сервера. Отказался от этого способа около 5 лет назад.

2 метод использовать протокол SMTP.
100% доставляемость писем, если только ваш почтовый домен не в черном списке. Хотел бы отметить, что нужно оформить DKIM и DMARC записи для почтового домен. Так же SPF запись, для защиты почтового домена.

Аватар пользователя kompospec kompospec 3 февраля в 1:59

///2 метод использовать протокол SMTP.///

Вся, практически вся почта отправляется по SMTP

///Если у вас есть возможность, вы можете поднять свой собственный почтовый сервер и///
Чтоб отправить почту программно с стороннего почтового сервера - не нужно ничего. 40 размашистых строк кода и ни одной библиотеки.
Почему так перегружены коды отправки - мне не ведомо.

Аватар пользователя kosskren kosskren 3 февраля в 8:29

Вам написали 2 варианта решения проблемы в рамках системы друпал. Через hook_mail() и через классы симфони. Можете выбрать один из двух или написать свое решение. Все же просто, не понимаю в чем проблема Smile

Аватар пользователя kosskren kosskren 3 февраля в 21:56

Правда не понимаю, по этому и спрашиваю)

Как вижу пути решения:

1. Используем стандартную php функцию mail(). Ее работа сводится к тому, что она отдает команду на отправку письма локальному агенту, как правило sendmail в юникс системах. Локальный агент уже через протокол smpt отправляет задачу на почтовый сервер.

Про использование функции mail() я писал, что это не надежно.

2. Через соккеты на php. Сам такое не делал, но код изучал ради интереса. Как то мне это показалось слишком замысловатым.

3. Используем готовые библиотеки/классы. В моем примере это симфони. Ну это же максимально просто выходит, разве нет? Сама функция отправки буквально 5-7 строк. Всю низкоуровневую реализацию smtp протокола на себя берт симфони.

Я не могу все знать, могу ошибаться. По этому интересно в чем проблема и если проблема есть, то как бы вы решили?

Аватар пользователя kompospec kompospec 4 февраля в 11:52

почему?
Я почти уверен, что если посмотреть код тех Друпало-Симфони библиотек - там именно сокетами всё и закончится.
Потому как ничего другого то и нет, как вы справедливо написали в двух первых пунктах выше.

Аватар пользователя kosskren kosskren 4 февраля в 15:27

Да, в этих библиотеках и многих других используются сокеты. Тут же дело в другом.

Причина No 1 - надежность.
Что такое симфони или друпал ? Это продукты, которые существуют и развиваются много лет. За годы их существования было исправлено куча багов, в том числе и с отправкой почты. Сейчас мы имеем возможность пользоваться состоявшимися продуктами, которые превосходно решают задачи.

Причина No2 - деньги и время.
Что нужно, что бы отправлять почту через сокеты? Нужно реализовать хотя бы в базовой основе протокол SMTP. Вот условно вам приходит заказ, реализовать отправку почты за условные 5 т.р.. Перед вами стоит выбор. Сделать быстро через компоненты симфони/друпала или реализовать через сокеты с учетом стандартов RFC xxxx, их там не один используется для работы протокола smtp и оформления почты. Так же сколько уйдет времени на отладку почты, отправляемой через сокеты.
Достаточно посмотреть в исходный код симофни/друпала, становится сразу понятно, что это задача с кучей подводных камне.

Причина No 3 - зачем изобретать велосипед.

Повторюсь. Для спортивного интереса можно поиграть с сокетами, но в коммерческий продукт выбираю отлаженные решения.

Аватар пользователя kosskren kosskren 7 февраля в 8:22

6. Еще можно через Почту России
7. Через СДЭК
Шучу конечно Smile

Если у вас сайт на друпал или на симфони сделан, почему нельзя использовать уже готовые компоненты данных систем? Они же вот у вас в папке с сайтом уже находятся :).

Аватар пользователя OldWarrior OldWarrior 4 февраля в 21:53
1

Мне вот чем нравится космоспец - своей несгибаемостью. Он с железобетонным упрямством остаётся преданным процедурной парадигме и философии Drupal 7 и во всех бедах винит "плохой новый" Друпал в ветках ^8.x. А не массу очевидных явлений/свойств своей личности - ведь так поступают только слабаки.

Так держать! Даёшь культ ретроградства! Нет - излишествам и новшествам, выходящим за рамки усвоенного процесса кодинга! Напридумали всякой дребедени, геи-буржуи.

Аватар пользователя OldWarrior OldWarrior 7 февраля в 22:16

Что вы ноете всё? Вам дали самое простое решение (пп.1 + 2) в самом первом ответе. Готовый каркас, только меняйте/подставляйте свой код. hook_mail + \Drupal::service('plugin.manager.mail') - это всегда рабочее решение.

К слову, я использую на некоторых сайтах примерно схожую конструкцию. Только я обычно расширяю \Drupal::service('plugin.manager.mail') в кастомном классе сервиса.

Про "говно" я промолчу. В некоторых (削除) известных (削除ここまで) случаях процедурный код напоминает именно эту субстанцию Wink

Аватар пользователя Bafur Bafur 6 февраля в 15:10

Друпал, считаю, не нужен. Если кому то хочется отправлять почту, отправляйте в удобном почтовом сервисе. Все бесполезные формы, вроде "Перезвоните мне", "Обратный звонок", "Оставить заявку" нужно удалить. Вместо этого, показать клиенту почту или телефон. Пусть сам пишет и звонит, нечего лениться.

Аватар пользователя kosskren kosskren 9 февраля в 11:22

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

В будущем, вы же на сайте данный код обернете в функцию, что бы его переиспользовать в разных частях сайта. В дальнейшем добавите поддержку вложений, добавите обработку ошибок и многое многое еще чего, чтобы код был надежен и функционален. В итоге у вас получится своя собственная библиотека по отправке почты. Так и вопрос, зачем городить велосипед? Я правда не понимаю вашей логики, в чем смысл такого подхода в работе? Smile

Разработка это баланс между тремя ценностями - цена, время и качество. Представьте, это как треугольник, где на каждой вершине по одной ценности. Так вот баланс в разработке, это быть в центре треугольника.
Я видел на форуме, вы работаете за 200 р. час, это не большая цена по рынку. Так же вы готовы вкладывать временя в написание кода, который уже есть в друпале. Это прямой путь к ухудшению качества в работе. Баланс нарушается.

Если мои слова вас обижают, то я извиняюсь. У меня нет цели обидеть или оскорбить вас или кого либо.

Аватар пользователя kompospec kompospec 9 февраля в 15:07

///Так же вы готовы вкладывать временя в написание кода, который уже есть в друпале. Это прямой путь к ухудшению качества в работе. Баланс нарушается.///

Я не увидел здесь ни одного готового к работе кода - кроме моего.
В конце концов я наверное всё таки сам попытаюсь их запустить и сравнить.

/// В дальнейшем добавите поддержку вложений,///
По моему задача чётко поставлена в заголовке. Никаких Вложений там даже близко нет

Аватар пользователя kosskren kosskren 9 февраля в 16:20

Я не увидел здесь ни одного готового к работе кода - кроме моего.

Забавно Smile

В конце концов я наверное всё таки сам попытаюсь их запустить и сравнить.

По каким параметрам хотите сравнить? Правда интересно.

По моему задача чётко поставлена в заголовке. Никаких Вложений там даже близко нет

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

Аватар пользователя kompospec kompospec 9 февраля в 17:25

///По каким параметрам хотите сравнить? Правда интересно.///

Для меня важна - Простота использования и чтоб работало везде где не закрыты порты.
Простота использования - это отсутствие сторонних библиотек, в том числе.

=============

У меня на хостинге прекрасно работает mail(), но полностью закрыты порты для почты.
Как запускать ваши программы - пока не придумал.

Аватар пользователя OldWarrior OldWarrior 9 февраля в 23:33
1

Ээээ, космоспец таки знатный тролль! Вброс на три рубля, а сколько в ответ поводов для беспредметного спора, брюзжания и нытья. Smile

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

Ну что, отвёл душу? По существу: займись уже делом, ёмана. Почитай мануалы и документацию, там много интересного.

Аватар пользователя kompospec kompospec 15 февраля в 0:36

По curl отправить письмо не удалось - ни локально, ни с сервера. Локально - требует сертификаты. А с сервера - просто не дошло. Почему - не понятно.
В коде - те-же 50 строк что и в Сокетах, а заморочек - гораздо больше.

Аватар пользователя kompospec kompospec 15 февраля в 1:45

6. Способ отправки - PHPMailer. Это работает где открыт порт и установлен PHPMailer. Установлен не везде. - Это обидно, так-как там всё до боли просто и укладывается в 40 строк.

Логотип drupal.ru

Содержимое сайта публикуется на условиях CreativeCommons Attribution-ShareAlike 3.0 или более поздней версии. Программные коды в тексте статей — на условиях GNU GPL v2 или более поздней версии.

Документация по совместной работе с репозиторием drupal.ru – https://docs.drupal.ru/code

Drupal – торговая марка Дриса Бёйтарта

12+

AltStyle によって変換されたページ (->オリジナル) /