Итак, ситуация: на предприятии активно используются уведомления e-mail. Конфигурация УТ11, учетная запись 1С подключена к SMTP, письма отправляются регламентным заданием. Если в каком-то из писем указан неверный по формату адрес получателя (например, скопированный из Word и заканчивающийся "переводом строки") - SMTP возвращает ошибку, но 1С её обрабатывать на стадии отправки не умеет (ИнтернетПочта.Послать()). Соответсвенно в журнале регистрации ничего не зафиксировано, регламентное задание успешно работает, но письма перестают отправляться.
Проблема проверки адреса конечно не нова, но обычно предлагается решения с проверкой адреса через регулярные выражения, используя VBScript (RegExp) или Java. Но погрузившись немного в тему, я пришел к выводу что более правильный способ предлагается в http://www.lexpr.ru/node/382.
В кратце - алгоритм проверяет адрес на соответствие RFC 1035 “Domain Implementation and Specification”, RFC 2234 “ABNF for Syntax Specifications”, RFC 2821 “Simple Mail Transfer Protocol”, RFC 2822 “Internet Message Format”. Правда, выяснилось что "жизнь шире наших схем" и домен 1C, например, им не соответсвует :)
Ну и собственно реализовал некий неполный аналог (алгоритма предложенного автором статьи по ссылке) в виде функции в общем модуле в 1С.
Применительно к УТ11 данная проверка дополнительно к штатным исользуется перед записью контактной информации в
УправлениеКонтактнойИнформацией.ЗаполнитьРеквизитыТабличнойЧастиДляАдресаЭлектроннойПочты()
и перед отправкой письма в функции
ЭлектроннаяПочта.ОтправитьСообщение()
при формировании адреса получателя. После работы типового кода каждый идентифицированный адрес проверяется указанной функцией и удаляется если не проходит проверку; если в результате не остается ни одного получателя - вызывается исключение.
Соответсвенно происходит переход к отправке следующего письма и запись об ошибке в журнале регистрации.
Код проверочной функции:
Функция EmailValid(Адрес) Экспорт
//Адрес = "test@me@gmail.narod.am";
ЛатинскиеБуквы = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
Цифры = "0123456789";
//ищем крайний справа символ @ для правильного выделения локальной и доменной части
ИндексСобаки = Найти(Адрес,"@");
//1. строка адреса вообще не содержит разделителя
Если ИндексСобаки = 0 Тогда
Возврат ЛОЖЬ;
КонецЕсли;
УрезаемаяСтрока = Сред(Адрес, ИндексСобаки+1);
Пока Найти(УрезаемаяСтрока,"@") > 0 Цикл
ИндексСобаки = ИндексСобаки + Найти(УрезаемаяСтрока,"@");
УрезаемаяСтрока = Сред(УрезаемаяСтрока, ИндексСобаки+1);
КонецЦикла;
ДоменнаяЧасть = Сред(Адрес, ИндексСобаки+1);
ЛокальнаяЧасть = Лев(Адрес, ИндексСобаки-1);
//2. Проверяем длину локальной части
Если СтрДлина(ЛокальнаяЧасть) < 1 ИЛИ СтрДлина(ЛокальнаяЧасть) > 64 Тогда
Возврат ЛОЖЬ;
КонецЕсли;
//3. Проверяем длину доменной части
Если СтрДлина(ДоменнаяЧасть) < 1 ИЛИ СтрДлина(ДоменнаяЧасть) > 255 Тогда
Возврат ЛОЖЬ;
КонецЕсли;
//4. Проверяем что локальная части не начинается и не заканчивается на "."
Если Лев(ЛокальнаяЧасть, 1) = "." ИЛИ Прав(ЛокальнаяЧасть, 1) = "." Тогда
Возврат ЛОЖЬ;
КонецЕсли;
//5. Локальная части не содержит 2 или более "." подряд
Если Найти(ЛокальнаяЧасть, "..") > 0 Тогда
Возврат ЛОЖЬ;
КонецЕсли;
//Проверка доменной части
//6. Доменная часть не начинается с точки
Если Лев(ДоменнаяЧасть, 1) = "." Тогда
Возврат ЛОЖЬ;
КонецЕсли;
//7. Доменная часть не содержит 2 или более "." подряд
Если Найти(ДоменнаяЧасть, "..") > 0 Тогда
Возврат ЛОЖЬ;
КонецЕсли;
//8. Проверка частей доменной части
//каждая часть начинается с буквы и заканчивается буквой или цифрой
//каждая часть длиной не более 63 символов
ИдентификаторыДоменнойЧасти = СтроковыеФункцииКлиентСервер.РазложитьСтрокуВМассивПодстрок(ДоменнаяЧасть, ".");
Для Каждого ИдентификаторДомена ИЗ ИдентификаторыДоменнойЧасти Цикл
Если СтрДлина(ИдентификаторДомена) > 63 Тогда
Возврат ЛОЖЬ;
КонецЕсли;
Если Найти(ЛатинскиеБуквы, Лев(ИдентификаторДомена,1)) = 0
//для доменов, нарушающих RFC 1035 п.2.3.1, например @1c.ru :)
И Найти(Цифры, Лев(ИдентификаторДомена,1)) = 0
Тогда
Возврат ЛОЖЬ;
КонецЕсли;
Если Найти(ЛатинскиеБуквы, Прав(ИдентификаторДомена,1)) = 0 И Найти(Цифры, Прав(ИдентификаторДомена,1)) = 0 Тогда
Возврат ЛОЖЬ;
КонецЕсли;
КонецЦикла;
//Все проверки пройдены - радуемся
Возврат ИСТИНА;
КонецФункции