Как в 1С отправить почту так, чтобы при ошибке одного адресата письмо уходило остальным?

Программист 1С v8.3 (Обычные формы) IT и автоматизация бизнеса
← На главную

В процессе разработки почтовых рассылок в среде 1С программисты часто сталкиваются с ситуацией, когда при указании нескольких получателей в одном объекте ИнтернетПочтовоеСообщение, почтовый сервер возвращает ошибку на один некорректный адрес (например, ящик не существует) и прекращает отправку для всех остальных участников списка. Это критично для бизнес-процессов, где уведомления должны дойти до всех корректных адресатов, несмотря на "битые" контакты в базе.

В данной статье мы подробно разберем, как изменить логику работы почтового клиента, проанализируем возможные подходы и выясним, какие настройки системы 1С помогут сделать рассылку максимально надежной.

Способ 1. Использование цикла и блока Попытка...Исключение

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

Разберем пример кода:


Профиль = Новый ИнтернетПочтовыйПрофиль;
// Настройка параметров подключения
Профиль.АдресСервераSMTP = "smtp.mail.ru";
Профиль.ПортSMTP = 465;
Профиль.ИспользоватьSSLSMTP = Истина;
Профиль.Пользователь = "sender@mail.ru";
Профиль.Пароль = "ваш_пароль_приложения";

Почта = Новый ИнтернетПочта;
Попытка
    Почта.Подключиться(Профиль);
Исключение
    Сообщить("Не удалось подключиться к серверу: " + ОписаниеОшибки());
    Возврат;
КонецПопытки;

ТекстОшибок = "";

Для каждого СтрокаАдреса Из ТаблицаАдресатов Цикл
    
    Сообщение = Новый ИнтернетПочтовоеСообщение;
    Сообщение.Отправитель = "sender@mail.ru";
    Сообщение.ИмяОтправителя = "Робот 1С";
    Сообщение.Тема = "Тестовая рассылка";
    Сообщение.Тексты.Добавить("Текст вашего сообщения");
    
    // Добавляем только одного получателя
    ТекущийАдрес = СокрЛП(СтрокаАдреса.Email);
    Сообщение.Получатели.Добавить(ТекущийАдрес);
    
    // Добавление вложений (если требуется)
    Если ЗначениеЗаполнено(ПутьКФайлу) Тогда
        Сообщение.Вложения.Добавить(ПутьКФайлу);
    КонецЕсли;

    Попытка
        Почта.Послать(Сообщение);
    Исключение
        // Если один адрес недоступен, ошибка попадет сюда, но цикл не прервется
        ТекстОшибок = ТекстОшибок + "Ошибка отправки на адрес " + ТекущийАдрес + ": " + ОписаниеОшибки() + Символы.ПС;
    КонецПопытки;

КонецЦикла;

Почта.Отключиться();

Если ЗначениеЗаполнено(ТекстОшибок) Тогда
    Сообщить("Рассылка завершена с ошибками:" + Символы.ПС + ТекстОшибок);
КонецЕсли;

Важный нюанс: Обратите внимание, что объект ИнтернетПочта создается и подключается один раз до начала цикла. Если вы будете подключаться и отключаться внутри цикла для каждого письма, это создаст огромную нагрузку на почтовый сервер и вашу систему, что может привести к временной блокировке вашего IP-адреса сервером за подозрительную активность.

Способ 2. Использование параметров метода Послать()

Мало кто из разработчиков обращает внимание на второй параметр метода Послать() объекта ИнтернетПочта. Рассмотрим синтаксис этого метода:

Послать(Сообщение, ОстановитьПриОшибке)

По умолчанию параметр ОстановитьПриОшибке имеет значение Истина. Если вы передадите в него значение Ложь, система попытается отправить письмо всем получателям, указанным в объекте сообщения, даже если при передаче данных одному из них возникнет сбой.


// Пример использования параметра
Почта.Послать(Сообщение, Ложь);

Однако стоит учитывать, что этот метод не всегда спасает, если почтовый сервер жестко настроен на отклонение всей транзакции при обнаружении первого же неверного адреса (ошибка SMTP 550).

Способ 3. Анализ результата через "Соответствие"

Метод Послать() возвращает результат в виде объекта Соответствие. Если отправка прошла полностью успешно, результат будет пустым. Если возникли ошибки с конкретными адресатами, в ключах этого соответствия будут находиться адреса получателей, а в значениях — описания ошибок. Проанализируем, как это можно использовать для логирования:


НепринятыеАдресаты = Почта.Послать(Сообщение, Ложь);

Если НепринятыеАдресаты.Количество() > 0 Тогда
    Для каждого Ошибка Из НепринятыеАдресаты Цикл
        Сообщить("Адрес: " + Ошибка.Ключ + " не принят сервером. Причина: " + Ошибка.Значение);
    КонецЦикла;
КонецЕсли;

Типичные ошибки при реализации рассылок

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

  1. Неверный путь к файлам вложений. Программист часто забывает проверять существование файла перед добавлением. Если метод Сообщение.Вложения.Добавить(Путь) получает некорректный путь, объект ИнтернетПочтовоеСообщение может стать "невалидным" еще до момента вызова Послать(). Всегда используйте Файл.Существует().
  2. Очистка вложений. Если вы используете один и тот же объект сообщения в цикле (что не рекомендуется), не забывайте вызывать Сообщение.Вложения.Очистить(), иначе каждый последующий получатель будет получать вложения всех предыдущих писем.
  3. Лимиты SMTP-сервера. Современные сервисы (Mail.ru, Gmail, Яндекс) имеют жесткие лимиты на количество писем в минуту и количество получателей в одном письме. Если ваша рассылка содержит сотни адресов, рекомендуется вставлять небольшую паузу в цикле, используя Приостановить(1).
  4. Современная аутентификация. Сейчас большинство серверов требуют использования "Паролей приложений". Если вы используете обычный пароль от ящика, сервер может обрывать соединение с ошибкой аутентификации, которую 1С может интерпретировать как общую ошибку отправки.

Рекомендации по стабильной работе

Для создания действительно профессионального почтового клиента в 1С мы рекомендуем придерживаться следующего алгоритма:

Во-первых, выполняйте предварительную проверку (валидацию) email-адреса на наличие символа "@" и отсутствие пробелов перед отправкой. Используйте СокрЛП() для всех строковых данных из базы.

Во-вторых, записывайте все ошибки в отдельный лог (регистр сведений или текстовый файл). Это позволит вам через неделю увидеть, какие адреса клиентов стали неактуальными, и исключить их из рассылки вручную или программно.

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

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

← На главную