Разработчики в 1С часто сталкиваются со следующей проблемой: при отправке писем через объект ИнтернетПочта на заведомо некорректный или несуществующий адрес электронный ящик не получает письмо, однако встроенный метод Послать() отрабатывает без ошибок и возвращает пустое соответствие. Согласно синтакс-помощнику, метод Послать() должен возвращать соответствие недоставленных адресов и ошибок, но на практике этого не происходит.
В этой статье мы подробно разберем, почему стандартный механизм 1С ведет себя именно так, проанализируем особенности работы почтовых серверов и рассмотрим практические варианты решения этой проблемы: от синтаксической валидации до автоматической обработки писем-отчетов о недоставке (Bounce Messages).
Чтобы понять, почему платформа 1С не сообщает об ошибке в момент отправки письма, нам необходимо погрузиться в устройство почтового протокола SMTP. Процесс отправки письма состоит из нескольких этапов взаимодействия вашего клиента (1С) и почтового сервера-отправителя.
Когда вы вызываете метод Почта.Послать(Сообщение), происходит следующее:
RCPT TO.250 OK.Для платформы 1С транзакция завершилась успешно: локальный SMTP-сервер принял письмо для дальнейшей отправки. Именно поэтому метод Послать() возвращает пустое соответствие, а блок Попытка...Исключение не фиксирует никаких ошибок.
Возвращаемое значение метода Послать() (объект Соответствие) будет заполнено только в том случае, если SMTP-сервер отклонит адрес непосредственно во время SMTP-сессии. Обычно это происходит при отправке писем внутри закрытой корпоративной сети (например, через локальный MS Exchange), когда сервер сразу "знает", существует ли данный внутренний ящик или нет.
Что же делать, если рассылка идет на внешние адреса? Давайте разберем по шагам три эффективных решения.
Самый простой шаг, который убережет базу от отправки писем на адреса с опечатками (без символа "@", с запрещенными знаками, пробелами и т.д.) — это проверка формата адреса перед формированием сообщения. Для этого нет необходимости писать сложные регулярные выражения самостоятельно. Если ваша конфигурация построена на базе БСП (Библиотека стандартных подсистем), мы можем использовать готовые функции.
Рассмотрим пример кода, в котором перед отправкой выполняется разбор строки получателей и их валидация:
// Предположим, у нас есть строка с адресатами, введенная пользователем
СтрокаАдресатов = "user1@mail.ru, incorrect_address, user2@yandex.ru";
// Шаг 1. Разбираем строку на структуру почтовых адресов
МассивАдресов = ОбщегоНазначенияКлиентСервер.РазобратьСтрокуСПочтовымиАдресами(СтрокаАдресатов);
Сообщение = Новый ИнтернетПочтовоеСообщение;
Сообщение.Тема = "Тема тестовой рассылки";
Сообщение.Тексты.Добавить("Текст нашего сообщения");
// Шаг 2. Проверяем каждый адрес на соответствие формату RFC
Для Каждого СтрАдрес Из МассивАдресов Цикл
ТекущийАдрес = СокрЛП(СтрАдрес.Адрес);
Если ОбщегоНазначенияКлиентСервер.АдресЭлектроннойПочтыСоответствуетФормату(ТекущийАдрес) Тогда
Сообщение.Получатели.Добавить(ТекущийАдрес);
Иначе
// Обрабатываем ошибку валидации
ЗаписьЖурналаРегистрации("ОтправкаПочты",
УровеньЖурналаРегистрации.Предупреждение,
,
,
"Некорректный формат почтового адреса: " + ТекущийАдрес);
КонецЕсли;
КонецЦикла;
// Шаг 3. Отправляем письмо только если есть валидные получатели
Если Сообщение.Получатели.Количество() > 0 Тогда
Почта = Новый ИнтернетПочта;
Попытка
Почта.Подключиться(Профиль);
Почта.Послать(Сообщение);
Почта.Отключиться();
Исключение
Сообщить("Ошибка при отправке почты: " + ОписаниеОшибки());
КонецПопытки;
КонецЕсли;
Этот способ позволяет отсеять явные ошибки ввода, однако он не спасет от ситуации, когда адрес написан без ошибок (например, exist@domain.com), но самого ящика физически не существует на удаленном сервере.
Когда удаленный почтовый сервер отклоняет доставку письма (ящик заблокирован, переполнен или не существует), он отправляет на адрес отправителя служебное сообщение — отчет о недоставке (Non-Delivery Report, NDR или Bounce Message). Обычно отправителем таких писем выступает системный робот с адресом вида mailer-daemon@... или postmaster@....
Мы можем автоматизировать сбор таких писем в 1С с помощью регламентного задания. Настроим систему так, чтобы она периодически подключалась к нашему почтовому ящику по протоколу IMAP или POP3, находила служебные письма о недоставке, парсила их содержимое, извлекала плохой e-mail адрес и помечала его в базе 1С как невалидный.
Проанализируем пример реализации такого алгоритма:
Процедура ОбработатьОтчетыОНедоставке() Экспорт
Профиль = Новый ИнтернетПочтовыйПрофиль;
Профиль.АдресСервераPOP3 = "pop.yandex.ru";
Профиль.ПортPOP3 = 995;
Профиль.ИспользоватьSSLPOP3 = Истина;
Профиль.Пользователь = "our_robot@yandex.ru";
Профиль.Пароль = "strong_password";
Почта = Новый ИнтернетПочта;
Попытка
Почта.Подключиться(Профиль, ПротоколИнтернетПочты.POP3);
Исключение
ЗаписьЖурналаРегистрации("ОбработкаПочты", УровеньЖурналаРегистрации.Ошибка,,, ОписаниеОшибки());
Возврат;
КонецПопытки;
// Получаем заголовки писем, чтобы не скачивать тяжелые вложения сразу
МассивЗаголовков = Почта.ПолучитьЗаголовки();
Если МассивЗаголовков.Количество() = 0 Тогда
Почта.Отключиться();
Возврат;
КонецЕсли;
// Загружаем только интересующие нас письма (от MAILER-DAEMON)
МассивИндексов = Новый Массив;
Для Индекс = 0 По МассивЗаголовков.Количество() - 1 Цикл
Отправитель = ВРег(МассивЗаголовков[Индекс].Отправитель);
Если Найти(Отправитель, "MAILER-DAEMON") > 0 Или Найти(Отправитель, "POSTMASTER") > 0 Тогда
МассивИндексов.Добавить(Индекс);
КонецЕсли;
КонецЦикла;
Если МассивИндексов.Количество() > 0 Тогда
МассивПисем = Почта.Выбрать(Ложь, МассивИндексов);
Для Каждого Письмо Из МассивПисем Цикл
ТекстПисьма = "";
Для Каждого ТекстСообщения Из Письмо.Тексты Цикл
Если ТекстСообщения.ТипТекста = ТипТекстаПочтовогоСообщения.ПростойТекст Тогда
ТекстПисьма = ТекстПисьма + Символы.ПС + ТекстСообщения.Текст;
КонецЕсли;
КонецЦикла;
// Ищем некорректный адрес в теле письма с помощью регулярных выражений
НедоставленныйАдрес = НайтиАдресВТекстеОшибки(ТекстПисьма);
Если ЗначениеЗаполнено(НедоставленныйАдрес) Тогда
// Фиксируем битый адрес в нашей базе данных
ЗаблокироватьАдресВБазе(НедоставленныйАдрес);
КонецЕсли;
// Помечаем письмо к удалению, чтобы не обрабатывать его повторно
Почта.УдалитьПисьма(Письмо);
КонецЦикла;
КонецЕсли;
Почта.Отключиться();
КонецПроцедуры
Функция НайтиАдресВТекстеОшибки(ТекстОшибки)
// Используем RegExp для поиска e-mail адреса, на который не удалось доставить письмо
RegExp = Новый COMОбъект("VBScript.RegExp");
RegExp.IgnoreCase = Истина;
RegExp.Global = Истина;
// Ищем паттерны вида "To: user@domain.com" или "failed: user@domain.com"
RegExp.Pattern = "To:\s*([a-zA-Z0-9_\-\.]+)@([a-zA-Z0-9_\-\.]+)\.([a-zA-Z]{2,5})";
Если RegExp.Test(ТекстОшибки) Тогда
Matches = RegExp.Execute(ТекстОшибки);
Если Matches.Count > 0 Тогда
// Возвращаем найденный e-mail
Возврат СокрЛП(Matches.Item(0).SubMatches.Item(0) + "@" + Matches.Item(0).SubMatches.Item(1) + "." + Matches.Item(0).SubMatches.Item(2));
КонецЕсли;
КонецЕсли;
Возврат "";
КонецФункции
Процедура ЗаблокироватьАдресВБазе(Email)
// Здесь мы пишем логику обновления контактной информации в базе 1С.
// Например, записываем признак "Некорректный" в регистр сведений или снимаем флаг согласия на рассылку.
ЗаписьЖурналаРегистрации("БлокировкаАдреса",
УровеньЖурналаРегистрации.Информация,
,
,
"Адрес " + Email + " исключен из рассылок из-за отчета о недоставке.");
КонецПроцедуры
Этот подход требует настройки регулярного выражения под особенности отчетов вашего конкретного почтового провайдера, так как формат писем-ошибок у Yandex, Mail.ru и Microsoft Exchange может незначительно отличаться.
Если ваша компания производит массовые рассылки клиентам (более 1000 писем в день), стандартные возможности встроенного SMTP-клиента 1С и обычные офисные почтовые ящики не подойдут. Почтовые провайдеры быстро заблокируют ваш домен за спам-активность при большом проценте недоставленных писем (так называемый "Bounce Rate").
В этом случае лучшим архитектурным решением будет интеграция 1С со специализированными сервисами рассылок (например, UniSender, SendPulse, Mailjet и др.) через HTTP API. Проанализируем преимущества такого подхода:
Интеграция выполняется с помощью стандартных HTTP-запросов 1С (объекты HTTPСоединение и HTTPЗапрос), что позволяет полностью автоматизировать контроль качества базы контрагентов.
Подводя итог: если вы столкнулись с проблемой "тихой" отправки писем на некорректные адреса, обязательно начните с внедрения синтаксической валидации через БСП. Если рассылки регулярные, настройте фоновое задание по сбору писем от mailer-daemon для автоматической очистки базы от несуществующих ящиков. Это сохранит высокую доставляемость ваших писем и убережет домен от попадания в черные списки.