Отправить на электронную почту со специальными символами, используя Exchange Web Services
При попытке отправить сообщение электронной почты с использованием управляемого API веб-служб Exchange против Exchange Server 2010 с пакетом обновления 1 (SP1) возникает исключение ServiceException с ErrorCode ErrorInvalidRecipients, если адрес электронной почты получателя (слева от @) содержит, в данном случае, датские буквы æøå.
Эти символы просто не разрешены в локальной части адресов электронной почты, или я должен как-то кодировать адрес?
Обновление: вот исходный код теста и данные трассировки:
var service = new ExchangeService(ExchangeVersion.Exchange2010_SP1);
service.AutodiscoverUrl("my@email.com");
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 на такой адрес дает следующее сообщение:
1 ответ
В соответствии с этой статьей, касающейся разрешения получателей Exchange, вам может понадобиться кодировать эти символы, используя этот метод:
Буквенно-цифровые символы, знак равенства (=) и дефис (-) не требуют кодировки. Другие символы используют следующий синтаксис кодировки: косая черта (/) заменяется подчеркиванием (_). Другие символы US-ASCII заменяются знаком плюс (+), а две цифры его значения ASCII записываются в шестнадцатеричном формате. Например, пробел имеет закодированное значение +20.
http://technet.microsoft.com/en-us/library/bb430743%28v=exchg.141%29.aspx
Таким образом, ваш пример "@øå@domain.com" станет "+e6+f8+e5@domain.com"
РЕДАКТИРОВАТЬ:
Также часть домена должна быть закодирована другим способом, если она использует специальные символы.
Вот 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, кодированный: user1+E6+F8+E5@xn--dmain-vua.com
И если вы используете "нормальный" адрес электронной почты, который не содержит символов вне "нормального" диапазона ASCII, он возвращает ту же строку.
Оригинал: jsmith01@gmail.com, кодированный: jsmith01@gmail.com