Отправить по электронной почте со специальными символами с помощью веб-служб Exchange

При попытке отправить электронное письмо с помощью Exchange Web Services Managed API в сравнении с Exchange Server 2010 SP1 возникает ServiceException с кодом ошибки ErrorInvalidRecipients, когда адрес электронной почты получателя (слева от @) содержит, в данном случае, датские буквы æøå.

Эти символы просто не разрешены в локальной части адресов электронной почты, или я должен как-то закодировать адрес?

Обновление. Вот исходный код теста и данные трассировки:

var service = new ExchangeService(ExchangeVersion.Exchange2010_SP1);
service.AutodiscoverUrl("[email protected]");
EmailMessage email = new EmailMessage(service);
email.Body = "Test";
email.Subject = "Test";
email.ToRecipients.Add("æøå@domain.com");
email.Send();

Данные трассировки из EWS показывают следующее:

Заголовки запроса:

POST /EWS/Exchange.asmx HTTP/1.1
Content-Type: text/xml; charset=utf-8
Accept: text/xml
User-Agent: ExchangeServicesClient/14.03.0032.000
Accept-Encoding: gzip,deflate

Запрос:

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:m="http://schemas.microsoft.com/exchange/services/2006/messages" xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
  <soap:Header>
    <t:RequestServerVersion Version="Exchange2010_SP1" />
  </soap:Header>
  <soap:Body>
    <m:CreateItem MessageDisposition="SendOnly">
      <m:Items>
        <t:Message>
          <t:Subject>Test</t:Subject>
          <t:Body BodyType="HTML">Test</t:Body>
          <t:ToRecipients>
            <t:Mailbox>
              <t:EmailAddress>æøå@domain.com</t:EmailAddress>
            </t:Mailbox>
          </t:ToRecipients>
        </t:Message>
      </m:Items>
    </m:CreateItem>
  </soap:Body>
</soap:Envelope>

Ответ:

<?xml version="1.0" encoding="utf-8"?>
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
  <s:Header>
    <h:ServerVersionInfo MajorVersion="14" MinorVersion="1" MajorBuildNumber="438" MinorBuildNumber="0" Version="Exchange2010_SP1" xmlns:h="http://schemas.microsoft.com/exchange/services/2006/types" xmlns="http://schemas.microsoft.com/exchange/services/2006/types" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" />
  </s:Header>
  <s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <m:CreateItemResponse xmlns:m="http://schemas.microsoft.com/exchange/services/2006/messages" xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types">
      <m:ResponseMessages>
        <m:CreateItemResponseMessage ResponseClass="Error">
          <m:MessageText>One or more recipients are invalid.</m:MessageText>
          <m:ResponseCode>ErrorInvalidRecipients</m:ResponseCode>
          <m:DescriptiveLinkKey>0</m:DescriptiveLinkKey>
          <m:Items />
        </m:CreateItemResponseMessage>
      </m:ResponseMessages>
    </m:CreateItemResponse>
  </s:Body>
</s:Envelope>

Наконец, создание электронной почты в Outlook на такой адрес дает следующее сообщение:

Мы не сможем доставить это сообщение ___, поскольку адрес электронной почты больше недействителен


person bernhof    schedule 28.04.2014    source источник
comment
Вы можете показать http дамп запроса/ответа? Мы поддерживаем датский и у нас нет этой проблемы   -  person Ivan G.    schedule 28.04.2014
comment
Вы кодируете левую часть @ в UTF8? также является ли домен строкой, отличной от ASCII? если это так, не забудьте punycode для второй части.   -  person Jportelas    schedule 29.04.2014
comment
Какую версию Exchange вы используете? Кажется, я помню, что некоторые пакеты обновления и наборы обновлений для Exchange 2010 включали исправления для EWS, обрабатывающего специальные символы.   -  person BateTech    schedule 29.04.2014
comment
@BateTech 2010 SP1. Обновил вопрос. Значит, обновление до SP2 может решить проблему?   -  person bernhof    schedule 29.04.2014
comment
@Jportelas, как мне кодировать? Я использую управляемый API: email.ToRecipients.Add("æøå@domain.com"). Имя домена не является не-ASCII.   -  person bernhof    schedule 29.04.2014
comment
@aloneguid См. обновленный вопрос — также см. дамп экрана внизу. Вы поддерживаете датский язык, поэтому я полагаю, вы не получаете это сообщение в Outlook?   -  person bernhof    schedule 30.04.2014
comment
@mbjdev Я просмотрел пакеты обновления и обновления Exchange и не смог найти ничего, что конкретно касалось бы проблем со специальными символами в адресе получателя, поэтому, возможно, я неправильно запомнил свой комментарий выше. Я нашел одно упоминание в накопительном пакете обновления 4 для Exchange Server 2010 с пакетом обновления 1 (SP1), в котором говорится, что обновление включает символы диапазона 0x-0x1F в отображаемом имени учетной записи пользователя Exchange Server 2010, поэтому, возможно, это то, о чем я думал, но это не поможет вам, потому что упомянутые вами символы не входят в этот диапазон. support.microsoft.com/kb/2579150   -  person BateTech    schedule 30.04.2014
comment
Для доменной части, поскольку она не является ASCII, вам может потребоваться проверить метод System.Globalization.GetAscii для ее кодирования. msdn.microsoft.com/en-us/library/vstudio/3dcsw2h8   -  person BateTech    schedule 30.04.2014


Ответы (1)


Согласно этой статье, посвященной разрешению получателей Exchange, вам может потребоваться закодировать эти символы, используя этот метод:

Буквенно-цифровые символы, знак равенства (=) и дефис (-) не требуют кодирования. Для других символов используется следующий синтаксис кодирования: косая черта (/) заменяется знаком подчеркивания (_). Другие символы US-ASCII заменяются знаком плюс (+), а две цифры его значения ASCII записываются в шестнадцатеричном формате. Например, символ пробела имеет закодированное значение +20.

http://technet.microsoft.com/en-us/library/bb430743%28v=exchg.141%29.aspx

Таким образом, ваш пример «æøå@domain.com» станет «[email protected]».

ИЗМЕНИТЬ:

Также «доменная» часть адреса должна быть закодирована с использованием другого метода, если она использует специальные символы.

Вот вспомогательный метод GetExchangeEncodedRecipient, который я собрал для кодирования адреса электронной почты с использованием спецификаций RFC 5321 и RFC 3461.

    public static string GetExchangeEncodedRecipient(string recipient) {
        int atIdx = recipient.LastIndexOf('@');

        if (atIdx < 0) {
            throw new ArgumentException("Unable to parse domain portion of \"recipient\" email address.");
        }

        string namepart = recipient.Substring(0, atIdx);
        string domainPart = recipient.Substring(atIdx + 1);
        //need to encode any special characters in the domain name
        System.Globalization.IdnMapping punycode = new System.Globalization.IdnMapping();
        domainPart = "@" + punycode.GetAscii(domainPart);

        return String.Concat(namepart.Select(c => GetExchangeEncodedChar(c))) + domainPart;
    }
    private static string GetExchangeEncodedChar(char c) {
        string encodedChar = c.ToString();
        int charASCIICode = (int)c;
        //Encode according to RFC5321, https://tools.ietf.org/html/rfc5321#section-4.1.2
        //  which references rfc3461 "xtext" format. https://tools.ietf.org/html/rfc3461#section-4 
        if(charASCIICode >= 33 && charASCIICode <= 126 && c != '+' && c != '=')
        {
            //This is a character in the valid 33-126 ASCII range for email addresses, which does not need encoded.
            return c.ToString();
        }
        else if(c == '/'){
            //A forward slash (/) is replaced by an underscore (_).
            return "_";
        }
        else { 
            return "+" + ((int)c).ToString("x2").ToUpper();
        }
    }

Затем вы можете использовать GetExchangeEncodedRecipient для кодирования адреса. Вот пример:

string recipient = @"user1æøå@dømain.com";
string encodedAddress = GetExchangeEncodedRecipient(recipient);
Console.WriteLine("Original: {0}, Encoded: {1}", recipient, encodedAddress);

Что для приведенного выше примера получателя выведет:

Оригинал: user1æøå@dømain.com, закодированный: [email protected]

И если вы используете «обычный» адрес электронной почты, который не содержит символов из «нормального» диапазона ASCII, он возвращает ту же строку.

Оригинал: [email protected], закодированный: [email protected]

person BateTech    schedule 29.04.2014
comment
Хм, в этом случае он не жалуется, но письмо не приходит (я тестирую с адресом @mailinator.com). Пробовал создать сообщение в Outlook на тот же адрес, и тут тоже не получается. См. дамп экрана, добавленный к вопросу (внизу)... - person bernhof; 30.04.2014
comment
@mbjdev Я обновил ответ образцом кода для кодировки адреса на основе некоторых RFC, которые мне удалось найти. Можете ли вы попробовать использовать закодированный адрес из этого метода и посмотреть, работает ли он? У меня нет действительного адреса электронной почты, который соответствует этим критериям в нашей среде для тестирования. - person BateTech; 30.04.2014
comment
Отличная работа, я проверю это, как только смогу, и вернусь к вам. Я очень ценю ваши усилия. - person bernhof; 30.04.2014