G.9. utl_smtp — отправка электронных писем по протоколу SMTP #
utl_smtp — это расширение Postgres Pro, предназначенное для отправки электронных писем по протоколу SMTP из PL/pgSQL. Функциональность, предоставляемая этим модулем, во многом пересекается с функциональностью пакета UTL_SMTP в Oracle.
G.9.1. Установка #
Расширение utl_smtp поставляется вместе с Postgres Pro Enterprise в отдельном пакете pgpro-orautl-ent-17 (подробные инструкции по установке приведены в Главе 17). Чтобы включить utl_smtp, создайте расширение с помощью следующего запроса:
CREATE EXTENSION utl_smtp;
G.9.2. Использование #
Чтобы отправить электронное письмо с помощью расширения utl_smtp, необходимо вызывать функции в определённом порядке:
Сначала откройте соединение, вызвав функцию
open_connection.Затем отправьте команду
HELO/EHLOSMTP-серверу, используя функцииhelo/ehloсоответственно.Отправьте адреса отправителя и получателя, используя функции
mailиrcpt.Вызовите функцию
opendata, чтобы начать процесс отправки данных посредством отправки командыDATASMTP-серверу.После этого можно многократно вызывать функции
write_dataиwrite_raw_dataдля отправки фактических данных.Процесс отправки данных завершается вызовом функции
close_data.После вызова
open_dataможно вызывать только следующие функции:write_data,write_raw_dataилиclose_data. Вызов других функций приведёт к возникновению ошибки.Кроме того, процесс отправки данных можно упростить, однократно вызвав функцию
data.После вызова
close_dataилиdataэлектронное письмо отправлено — вызовите функциюquit, чтобы завершить соединение.
G.9.3. Типы данных #
Расширение utl_smtp предоставляет следующие типы данных:
Тип
replyпредставляет собой строку ответа SMTP. Каждая строка ответа SMTP состоит из кода ответа, за которым следует текстовое сообщение. Для большинства команд SMTP ожидается одна строка ответа, для некоторых — несколько строк.Таблица G.97. Параметры
replyПараметр Описание code3-значный код ответа textТекстовое сообщение ответа Тип
connectionпредставляет собой соединение по протоколу SMTP.Таблица G.98. Параметры
connectionПараметр Описание hostИмя или IP-адрес удалённого узла при установке соединения. portНомер порта подключённого удалённого SMTP-сервера. tx_timeoutВремя ожидания расширением utl_smtp операций чтения или записи в этом соединении, в секундах. Таймаут соединения с сервером всегда составляет 60 секунд и не может быть настроен. private_socketЭтот параметр используется внутри Postgres Pro и не должен изменяться вручную.
G.9.4. Функции utl_smtp #
Расширение utl_smtp предоставляет функции для отправки электронных писем по протоколу SMTP. Обратите внимание, что функции, которые должны возвращать несколько строк ответа, возвращают массив типа reply.
-
auth(#cconnection,usernametext,passwordtext,schemestextdefault 'PLAIN') returnsreply Отправляет SMTP-серверу команду
AUTHдля аутентификации. В настоящее время поддерживается только схема аутентификацииPLAIN.-
close_all_connections() returns#void Закрывает все SMTP-соединения и освобождает все связанные с ними ресурсы.
-
close_connection(#cconnection) returnsvoid Закрывает указанное SMTP-соединение. Эту функцию можно вызвать при отправке данных на сервер перед вызовом
close_data. В этом случае следующий вызов функции с этим соединением выдаст исключение.-
close_data(#cconnection) returnsreply Завершает сообщение электронной почты отправкой последовательности
<CR><LF>.<CR><LF>(одна точка в начале строки).-
command(#cconnection,cmdtext,argtextdefault null) returnsreply Отправляет произвольную команду SMTP и может возвращать одну строку ответа.
-
command_replies(#cconnection,cmdtext,argtextdefault null) returnsreply[] Отправляет произвольную команду SMTP и может возвращать несколько строк ответа.
-
data(#cconnection,bodytext) returnsreply Указывает тело электронного письма. По сути, это последовательность вызовов следующих функций:
open_data,write_dataиclose_data.-
ehlo(#cconnection,domaintext) returnsreply Выполняет начальное согласование с SMTP-сервером с помощью команды
EHLO. Сервер возвращает часть своей конфигурации.-
helo(#cconnection,domaintext) returnsreply Выполняет начальное согласование с SMTP-сервером с помощью команды
HELO.-
help(#cconnection,commandtextdefault null) returnsreply Отправляет команду
HELP. Эта команда может быть реализована не на всех SMTP-серверах.-
last_reply(#cconnection) returnsreply Возвращает последний ответ SMTP-сервера.
-
mail(#cconnection,sendertext,parameterstextdefault null) returnsreply Инициирует транзакцию отправки электронного письма с сервером, отправляя команду
MAILс адресом отправителя.-
noop(#cconnection) returnsreply Выдаёт команду
NOOP. Эта функция в основном используется для проверки соединения.-
open_connection(#hosttext,portintdefault 25,tx_timeoutintdefault null,secure_connection_before_smtpbooldefault false,verify_peerbooldefault true) returnsconnection Открывает соединение с SMTP-сервером. Параметр
secure_connection_before_smtpуказывает, устанавливается ли подключение TLS до соединения SMTP (по сути, если этот параметр имеет значение true, соединение будет использовать SMTPS вместо SMTP). Параметрverify_peerуказывает, проверяются ли сертификаты при установке подключения TLS.-
open_data(#cconnection) returnsreply Отправляет команду
DATA, после которой можно использовать функцииwrite_dataиwrite_raw_data, чтобы написать часть электронного письма.-
quit(#cconnection) returnsreply Завершает сеанс SMTP и отключается от сервера.
-
rcpt(#cconnection,recipienttext,parameterstextdefault null) returnsreply Указывает получателя электронного письма. Транзакция отправки сообщения должна быть запущена предыдущим вызовом
MAIL, а соединение с почтовым сервером должно быть открыто и инициализировано предыдущими вызовамиopen_connectionиheloилиehloсоответственно.-
rset(#cconnection) returnsreply Завершает текущую транзакцию отправки письма. Клиент может вызвать
rsetв любое время после открытия соединения с SMTP-сервером с помощьюopen_connectionдо вызоваdataилиopen_data.-
set_reply_error_check(#cconnection,enablebool) returnsvoid Определяет поведение функции. Если для параметра
enableустановлено значение true (по умолчанию), любая ошибка на SMTP-сервере выдаёт исключение. Если установлено значение false, для определения ошибки пользователю следует самостоятельно анализировать результаты, возвращаемые функциями.-
starttls(#cconnection,verify_peerbooldefault true) returnsreply Отправляет команду
STARTTLSдля защиты SMTP-соединения с использованием TLS.-
vrfy(#cconnection,recipienttext) returnsreply Отправляет команду
VRFYдля проверки корректности адреса получателя электронного письма. Эта команда может быть реализована не на всех SMTP-серверах и может возвращать некорректную информацию, поэтому не рекомендуется её использовать.-
write_data(#cconnection,datatext) returnsvoid Отправляет часть текста сообщения, включая заголовки, SMTP-серверу. При повторном вызове
write_dataдобавляет данные к сообщению.-
write_raw_data(#cconnection,datatext) returnsvoid Отправляет часть текста сообщения, включая заголовки, SMTP-серверу. При повторном вызове
write_dataдобавляет данные к сообщению. Эта функция аналогична функцииwrite_data.
G.9.5. Примеры #
В следующем примере показана отправка электронного письма без вложения с помощью utl_smtp.
DO $$
DECLARE
conn utl_smtp.connection;
BEGIN
conn := utl_smtp.open_connection('smtp.mail.ru', 25, 10);
perform utl_smtp.ehlo(conn, 'localhost');
perform utl_smtp.starttls(conn);
perform utl_smtp.ehlo(conn, 'localhost');
perform utl_smtp.auth(conn, 'test_email@example.com', 'super-secret-password');
perform utl_smtp.mail(conn, 'sender@example.com');
perform utl_smtp.rcpt(conn, 'recipient@example.com');
perform utl_smtp.open_data(conn);
perform utl_smtp.write_data(conn, E'Content-Type: multipart/mixed; boundary=------------------------6f48b7d5ded0c5fc\n');
perform utl_smtp.write_data(conn, E'Mime-Version: 1.0\n');
perform utl_smtp.write_data(conn, E'From: Sender <sender@example.com>\n');
perform utl_smtp.write_data(conn, E'To: Recipient <recipient@example.com>\n');
perform utl_smtp.write_data(conn, E'Subject: mail from utl_smtp\n');
perform utl_smtp.write_data(conn, E'--------------------------6f48b7d5ded0c5fc\n');
perform utl_smtp.write_data(conn, E'Content-Type: text/plain; charset=\"UTF-8\"\n');
perform utl_smtp.write_data(conn, E'Content-Transfer-Encoding: 8bit\n\n');
perform utl_smtp.write_data(conn, E'This is body from inside Postgres Pro\n');
perform utl_smtp.write_data(conn, E'Sent using utl_smtp\n');
perform utl_smtp.write_data(conn, E'\n--------------------------6f48b7d5ded0c5fc--\n');
perform utl_smtp.close_data(conn);
perform utl_smtp.quit(conn);
END$$;В следующем примере показана обработка исключений с помощью utl_smtp.
DO $$
DECLARE
...
r utl_smtp.reply;
BEGIN
...
some utl_smtp funcion calls
...
exception
when others then
r = utl_smtp.last_reply(conn);
if r.code >= 500 then
raise notice 'caught permanent error';
elsif r.code >= 400 then
raise notice 'caught transient error';
else
raise notice 'some other error';
end if;
END$$;