В современных корпоративных средах службы безопасности часто блокируют стандартные протоколы передачи почты, такие как POP3 и SMTP, из-за их потенциальной уязвимости. В таких случаях основным инструментом взаимодействия с сервером Microsoft Exchange становится протокол Exchange Web Services (EWS). Это API, основанное на SOAP и работающее через HTTP(S), что позволяет обходить ограничения и интегрироваться с почтовым сервером напрямую. Разберем подробно, как реализовать получение почты через EWS в среде 1С:Предприятие.
Часто разработчики пытаются использовать MSXML2.XMLHTTP через COM-соединение. Однако, как показывает практика, это часто приводит к ошибкам в системных библиотеках, таких как msxml3.dll, особенно при работе с современными протоколами шифрования TLS. Проанализируем, почему лучше отказаться от этого метода в пользу встроенных средств платформы 1С.
При использовании COMОбъект("MSXML2.XMLHTTP") вы зависите от настроек операционной системы и версии установленных библиотек. Вместо этого рассмотрим использование объекта HTTPСоединение, который является кроссплатформенным и более стабильным.
Поскольку работа с EWS практически всегда идет через HTTPS, первым шагом нам необходимо настроить защищенное соединение. Проигнорировав этот этап, мы получим ошибку при попытке установить связь с сервером.
ЗащищенноеСоединение = Новый ЗащищенноеСоединениеOpenSSL();
СерверExchange = "your-exchange-server.com";
Пользователь = "domain\user";
Пароль = "password";
Соединение = Новый HTTPСоединение(СерверExchange, , Пользователь, Пароль, , 30, ЗащищенноеСоединение);
Для получения списка писем используется метод FindItem. Важно понимать структуру XML-пакета, который ожидает сервер. Выясним причину, по которой многие запросы возвращают ошибку: часто это отсутствие пространства имен или некорректная версия схемы. Проанализируем структуру запроса на поиск непрочитанных сообщений в папке "Входящие".
Обратите внимание на заголовок RequestServerVersion. Без указания версии сервера Exchange может не понять структуру запроса.
ТекстЗапроса =
"<?xml version=""1.0"" encoding=""utf-8""?>
|<soap:Envelope xmlns:soap=""http://schemas.xmlsoap.org/soap/envelope/""
| xmlns:t=""http://schemas.microsoft.com/exchange/services/2006/types""
| xmlns:m=""http://schemas.microsoft.com/exchange/services/2006/messages"">
| <soap:Header>
| <t:RequestServerVersion Version=""Exchange2013"" />
| </soap:Header>
| <soap:Body>
| <m:FindItem Traversal=""Shallow"">
| <m:ItemShape>
| <t:BaseShape>IdOnly</t:BaseShape>
| <t:AdditionalProperties>
| <t:FieldURI FieldURI=""item:Subject""/>
| <t:FieldURI FieldURI=""item:DateTimeReceived""/>
| </t:AdditionalProperties>
| </m:ItemShape>
| <m:ParentFolderIds>
| <t:DistinguishedFolderId Id=""inbox""/>
| </m:ParentFolderIds>
| </m:FindItem>
| </soap:Body>
|</soap:Envelope>";
Рассмотрим процесс отправки сформированного XML на сервер. Для работы с EWS адрес ресурса обычно выглядит как /ews/exchange.asmx. Посмотрим на пример настройки заголовков и отправки POST-запроса.
Заголовки = Новый Соответствие();
Заголовки.Вставить("Content-Type", "text/xml; charset=utf-8");
Запрос = Новый HTTPЗапрос("/ews/exchange.asmx", Заголовки);
Запрос.УстановитьТелоИзСтроки(ТекстЗапроса, КодировкаТекста.UTF8);
Попытка
Ответ = Соединение.ОтправитьДляОбработки(Запрос);
Если Ответ.КодСостояния = 200 Тогда
ТекстОтвета = Ответ.ПолучитьТелоКакСтроку();
// Здесь мы приступаем к разбору XML
Иначе
Сообщить("Ошибка сервера: " + Ответ.КодСостояния);
КонецЕсли;
Исключение
Сообщить("Ошибка связи: " + ОписаниеОшибки());
КонецПопытки;
Метод FindItem возвращает только идентификаторы (ItemId). Чтобы прочитать текст письма или скачать вложения, нам необходимо выполнить второй шаг — запрос GetItem. Разберем по шагам, как это сделать, используя полученный ранее Id и ChangeKey.
ТекстЗапросаПолучения =
"<?xml version=""1.0"" encoding=""utf-8""?>
|<soap:Envelope xmlns:soap=""http://schemas.xmlsoap.org/soap/envelope/""
| xmlns:t=""http://schemas.microsoft.com/exchange/services/2006/types"">
| <soap:Body>
| <GetItem xmlns=""http://schemas.microsoft.com/exchange/services/2006/messages"">
| <ItemShape>
| <t:BaseShape>Default</t:BaseShape>
| <t:IncludeMimeContent>true</t:IncludeMimeContent>
| </ItemShape>
| <ItemIds>
| <t:ItemId Id=""ИДЕНТИФИКАТОР_ПИСЬМА"" ChangeKey=""КЛЮЧ_ИЗМЕНЕНИЙ""/>
| </ItemIds>
| </GetItem>
| </soap:Body>
|</soap:Envelope>";
Важный момент: использование свойства IncludeMimeContent позволяет получить письмо целиком в формате EML, что удобно для последующего разбора библиотеками 1С или сохранения в файл.
Рассмотрим альтернативный вариант — использование объекта WSОпределения. Этот метод кажется более "правильным" для 1С, так как он позволяет работать с объектами XDTO. Однако выясним, с какими сложностями вы можете столкнуться:
Services.wsdl) весит несколько мегабайт и ссылается на множество схем.WSПрокси на основе такого WSDL может занимать значительное время и требовать до нескольких гигабайт оперативной памяти в момент разбора.WSПрокси иногда возникают трудности с пробросом NTLM-авторизации в некоторых версиях платформы.Поэтому для простых задач получения почты ручное формирование XML через HTTPСоединение часто оказывается более быстрым и надежным решением.
Проанализируем современную ситуацию: Microsoft постепенно отключает базовую аутентификацию (логин/пароль) в Exchange Online (Office 365). Если ваша почта находится в облаке, вам потребуется:
AccessToken через отдельный HTTP-запрос.Authorization: Bearer [Ваш_Токен] во все запросы к EWS.Для разбора ответа от сервера рекомендуем использовать объект ЧтениеXML или ПостроительDOM. Поскольку XML от Exchange очень многословен, ПостроительDOM позволит вам быстро находить нужные узлы с помощью XPath-запросов, не перебирая все дерево вручную. Например, вы можете быстро извлечь все t:ItemId из ответа FindItem, чтобы затем в цикле запросить содержимое каждого письма.
Таким образом, мы проанализировали основные подходы к работе с MS Exchange через EWS. Несмотря на кажущуюся сложность по сравнению с POP3, данный метод предоставляет гораздо более широкие возможности по управлению почтовыми ящиками, календарями и задачами напрямую из 1С.