APEX + Яндекс Почта
02.03.2018

В одном из проектов в очередной раз встал вопрос: "Как отправлять уведомления о тех или иных событиях в системе на электронную почту?"

В предыдущих проектах в качестве агента использовались внутренние SMTP сервера. Подключение к ним настраивалось как правило без особых проблем. В одном из случаев возникли проблемы с Exchange, решил их путем установки локального SMTP сервера Personal SMTP Server. Но то был сервер Windows, в текущем же проекте сервер CentOS. Попробовал настроить Postfix. В принципе с его помощью получилось настроить отправку на smtp.yandex.ru, но письма попадали в спам. Как я понял, надо было настраивать такие понятия как MX-запись, подписи SPF и DKIM, но не хотелось со всем с этим разбираться, хотелось настроить прямое подключение к smtp.yandex.ru.

Что имеем в качестве исходно материала?

  1. Домен 1apex.ru
  2. Сайт http://1apex.ru/fzzp
  3. В панели управления доменом на сайте www.reggi.ru права на управление почтой делегированы Яндексу:
    Пример настроек на www.reggi.ru для делегирования управления почтой серверам Яндекса.
  4. Права на управление почтой домена 1apex.ru подтверждены по инструкции Яндекса. При этом сам домен Яндексу я не делегировал, только почту.
  5. В почте Яндекс заведен почтовый адрес fzzp@1apex.ru
  6. В настройках инстанса APEX указаны необходимые настройки для подключения к smtp.yandex.ru
    Пример настроек инстанса APEX для отправки почты через smtp.yandex.ru

Обратите внимание, в настройках указан путь к бумажнику (wallet) с сертификатами для установления защищенного соединения с smtp.yandex.ru. С осени 2015г. Яндекс почта разрешает только защищенные соединения.
Собственно именно с SSL и возникли некоторые проблемы. Тот сертификат, что был приведен на сайте Яндекса не подошел. При отправке почты выдавалась ошибка ORA-29024: Certificate validation failure. Начались поиски корректной цепочки сертификатов. Поиск привел на сайт https://mikepargeter.wordpress.com/2013/11/28/ora-29024-certificate-validation-failure. Командой

openssl s_client -connect smtp.yandex.ru:25 -starttls smtp

получаем список сертификатов необходимых для корректного соединения:
Пример вывода команды openssl
Сами сертификаты нашел в своем браузере Mozilla Firefoх:

"Настройка" > Дополнительно > Сертификаты > Просмотр сертификатов
В списке нужно найти цепочку сертификатов "Unizeto Sp. z o.o." и экспортировать всю цепочку кроме последнего:

Пример экспорта цепочки сертификатов
Полученный файл нужно закинуть на сервер Oracle и прописать его в бумажнике wallet.
  1. Создаем каталог для хранения бумажника (путь может быть любым, главное что бы у пользователя под которым работает БД Oracle был туда доступ на чтение/запись):
    /u01/app/oracle/wallet
  2. Закидываем туда файл с цепочкой (не обязательно туда же, можно в любое другое место, я так сделал просто для удобства написания команды импорта сертификатов)
  3. Создаем бумажник командной:
    orapki wallet create -wallet /u01/app/oracle/wallet -auto_login
  4. Два раза вводим пароль для доступа к бумажнику, его же потом вводим в настройках инстанса APEX в поле "Wallet Password"
  5. Импортируем цепочку сертификатов:
    orapki wallet add -wallet /u01/app/oracle/wallet -trusted_cert -cert /u01/app/oracle/wallet/CertumLevelIVCA.p7c -pwd <ваш пароль к бумажнику>

После этого соединение по защищенному каналу должно устанавливаться успешно. Но при отправке письма выдается ошибка:
ORA-29279: SMTP permanent error: 535 5.7.8 Error: authentication failed:Invalid format.
Проблема в utl_smtp.auth(..., schemes  => utl_smtp.all_schemes), если значение utl_smtp.all_schemes заменить на "LOGIN", все работает, почта уходит через smtp.yandex.ru.
Если вы для отправки почты используете пакет UTL_SMTP, то задача решена.

В случае же с APEX - это ни как не настраивается, т.к. вызов utl_smtp.auth(..., schemes  => utl_smtp.all_schemes) прошит в заврапленном пакете wwv_flow_mail. Нужно, либо создавать свой обработчик очереди сообщений и заменять штатный джоб ORACLE_APEX_MAIL_QUEUE повторяя всю ту логику которая заложена в процедуре WWV_FLOW_MAIL.PUSH_QUEUE_IMMEDIATE, либо искать другой SMTP сервер, либо, как я уже писал выше, настраивать свой собственный SMTP сервер.

Еще один пример (другой источник сертификатов)

release 1.0