使用Exchange Web服务发送包含特殊字符的电子邮件

时间:2014-04-28 10:44:36

标签: .net email exchangewebservices exchange-server-2010 ews-managed-api

尝试使用Exchange Web Services Managed API针对 Exchange Server 2010 SP1 发送电子邮件时,将使用ErrorCode {{3}引发 ServiceException 当收件人的电子邮件地址(@的左侧)包含,在这种情况下,丹麦字母æøå。

这些字符是否仅在电子邮件地址的本地部分中被允许,或者我应该以某种方式对地址进行编码?

更新:以下是测试源代码和跟踪数据:

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中创建一个这样的地址的电子邮件会显示以下消息:

We wont be able to deliver this message to ___ because the email address is no longer valid

1 个答案:

答案 0 :(得分:1)

根据处理Exchange收件人解析的这篇文章,您可能需要使用以下方法对这些字符进行编码:

  

字母数字字符,等号(=)和连字符( - )不   需要编码。其他字符使用以下编码语法:   正斜杠(/)由下划线(_)替换。其他US-ASCII   字符由加号(+)及其两位数字代替   ASCII值以十六进制写入。例如,空间   character的编码值为+20。

http://technet.microsoft.com/en-us/library/bb430743(v=exchg.141).aspx

所以你的“æøå@domain.com”的例子将成为“+ e6 +f8 + e5@domain.com”

修改

如果使用特殊字符,地址的“域”部分也需要使用不同的方法进行编码。

以下是我使用RFC 5321和RFC 3461规范对电子邮件地址进行编码的GetExchangeEncodedRecipient辅助方法。

    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