【问题标题】:Send to e-mail with special characters using Exchange Web Services使用 Exchange Web 服务发送到带有特殊字符的电子邮件
【发布时间】:2014-06-13 21:02:03
【问题描述】:

当尝试使用 Exchange Web Services Managed API 针对 Exchange Server 2010 SP1 发送电子邮件时,会抛出 ServiceException 错误代码 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 中向这样的地址创建电子邮件会给出以下消息:

【问题讨论】:

  • 你能显示请求/响应 http 转储吗?我们支持丹麦语,没有这个问题
  • 您是否将 @ 的左侧部分编码为 UTF8?域也是非ASCII字符串吗?如果是这样,请不要忘记第二部分的 punycode。
  • 您使用的是哪个版本的 Exchange?我似乎记得 Exchange 2010 的一些服务包和更新汇总包含 EWS 处理特殊字符的修复程序。
  • @BateTech 2010 SP1。更新了问题。那么升级到 SP2 可能会解决问题吗?
  • @Jportelas 我应该如何编码?我正在使用托管 API:email.ToRecipients.Add("æøå@domain.com")。域名不是非ASCII。

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


【解决方案1】:

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

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

http://technet.microsoft.com/en-us/library/bb430743(v=exchg.141).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

【讨论】:

  • 嗯,在这种情况下它不会抱怨,但电子邮件没有到达(我正在使用@mailinator.com 地址进行测试)。我尝试在 Outlook 中向同一地址创建一条消息,但在这里它也失败了。查看添加到问题中的屏幕转储(底部)...
  • @mbjdev 我根据我能找到的一些 RFC 使用地址编码的代码示例更新了答案。您可以尝试使用该方法中的编码地址并查看它是否有效?在我们的测试环境中,我没有符合此标准的有效电子邮件地址。
  • 干得好,我会尽快测试并回复您。我非常感谢您的努力。
猜你喜欢
  • 2011-04-18
  • 1970-01-01
  • 1970-01-01
  • 2012-12-12
  • 1970-01-01
  • 1970-01-01
  • 2010-12-15
  • 2013-08-10
  • 1970-01-01
相关资源
最近更新 更多