EWS访问其他用户的Exchange邮箱时出现ErrorMissingEmailAddress错误

时间:2016-10-13 17:00:56

标签: c# .net exchangewebservices ews-managed-api

我使用EWS托管API从收件箱和子文件夹中读取电子邮件。当我作为邮箱所有者使用用户名&密码验证它一切正常,但当我使用Windows身份验证连接作为服务帐户时,访问子文件夹时出错。该服务帐户已被授予对其连接的邮箱的完全访问权限。服务帐户没有自己的邮箱。错误是:

Problem encountered while retrieving the email from exchange. Microsoft.Exchange.WebServices.Data.ServiceResponseException: When making a request as an account that does not have a mailbox, you must specify the mailbox primary SMTP address for any distinguished folder Ids.
   at Microsoft.Exchange.WebServices.Data.ServiceResponse.InternalThrowIfNecessary()
   at Microsoft.Exchange.WebServices.Data.MultiResponseServiceRequest`1.Execute()
   at MyMethod_That_Calls_ExchangeServer_FindItems(folderId, view)

当您使用对邮箱的委派访问权(即未连接到您拥有的邮箱)并且未指定邮箱所有者时连接到已知邮箱时,这是一个非常常见的错误。可以轻松解决此问题:使用FolderId对象创建Mailbox对象,其中包含要连接到的邮箱的主要smtp地址,例如:

var theMailboxEmailAddress = "johnsmith@example.com";
var folderId = new FolderId(WellKnownFolderName.Inbox,
                      new Mailbox(theMailboxEmailAddress);
var items = myExchangeService.FindItems(folderId, anItemView);

然而,我的情况并非那么容易。我正在指定邮箱,但是当我在子文件夹上调用FindItems时,我收到错误。访问子文件夹时无法指定邮箱,因为没有它就可以工作。

根据this article('明确访问和EWS')建议的方法是:

  • 首先使用&{39; explicit access':使用FindFolder()(又名DistinguishedFolderId)致电WellKnownFolderName,传递MailBox参数识别邮箱所有者。
    • 这对我来说很好,我能够获取收件箱下方的文件夹列表并获取文件夹ItemId
  • 然后使用' implicit access':调用service.FindItems(folderId, view)传递从上一步检索到的folderId。这对我来说是失败的,这是令人惊讶的。

当我查看EWS跟踪时,我可以看到在我的FindItems()请求中没有发送DistinguishedFolderIds。这是失败的电话:

Trace type: EwsRequest
Trace message: <Trace Tag="EwsRequest" Tid="13" Time="2016-10-13 12:50:05Z" Version="15.00.0913.015">
  <?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_SP2" />
    </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:FieldURI FieldURI="message:IsRead" />
            <t:FieldURI FieldURI="message:From" />
            <t:ExtendedFieldURI DistinguishedPropertySetId="InternetHeaders" PropertyName="X-MyApp-MailId" PropertyType="String" />
          </t:AdditionalProperties>
        </m:ItemShape>
        <m:IndexedPageItemView MaxEntriesReturned="6" Offset="0" BasePoint="Beginning" />
        <m:SortOrder>
          <t:FieldOrder Order="Ascending">
            <t:FieldURI FieldURI="item:DateTimeReceived" />
          </t:FieldOrder>
        </m:SortOrder>

<!-- Note below there's no DistinguishedFolderId, so nowhere to specify the mailbox -->

        <m:ParentFolderIds>
          <t:FolderId Id="AAMkAGU2NWRkNjYxLTI3YjktNDFkMi04ZmNlLWI0M2FmMGVmYzBhYwAuAAAAAAD/Z9M6ia69S5l65fo6tjEaAQAoQBtCK9L9S4ux7hB0Qcw/AAAIZFKVAAA=" />
        </m:ParentFolderIds>


      </m:FindItem>
    </soap:Body>
  </soap:Envelope>
</Trace>

这是失败的回应:

Trace type: EwsResponse
Trace message: <Trace Tag="EwsResponse" Tid="13" Time="2016-10-13 12:50:05Z" Version="15.00.0913.015">
  <?xml version="1.0" encoding="utf-8"?>
  <s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
    <s:Header>
      <h:ServerVersionInfo MajorVersion="15" MinorVersion="0" MajorBuildNumber="847" MinorBuildNumber="31" Version="V2_8" xmlns:h="http://schemas.microsoft.com/exchange/services/2006/types" xmlns="http://schemas.microsoft.com/exchange/services/2006/types" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" />
    </s:Header>
    <s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
      <m:FindItemResponse xmlns:m="http://schemas.microsoft.com/exchange/services/2006/messages" xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types">
        <m:ResponseMessages>
          <m:FindItemResponseMessage ResponseClass="Error">
            <m:MessageText>When making a request as an account that does not have a mailbox, you must specify the mailbox primary SMTP address for any distinguished folder Ids.</m:MessageText>
            <m:ResponseCode>ErrorMissingEmailAddress</m:ResponseCode>
            <m:DescriptiveLinkKey>0</m:DescriptiveLinkKey>
          </m:FindItemResponseMessage>
        </m:ResponseMessages>
      </m:FindItemResponse>
    </s:Body>
  </s:Envelope>
</Trace>

在上面的示例中,我指定了ExchangeServerVersion Exchange2010_SP2,但我也尝试过使用Exchange2013。我正在连接到Exchange 2013服务器。

一位同事使用EWSEditor尝试了同样的事情并得到了同样的错误。我还没有仔细检查过,但是如果是这样的话,那就表明在使用API​​时会出现EWS问题或容易犯的错误。

也发布在MSDN论坛here上。

更新13-Oct-16:

根据这篇Handling delegation-related errors in EWS in Exchange文章,我现在想知道这是否是一个&#39;设计&#39;交易所的限制。即,如果你想查看收件箱中的非知名文件夹,你必须有一个邮箱,否则它无法管理权限或类似的东西。在该文章中,它表示当{&#34}使用没有邮箱的代理帐户发出请求时会发生ErrorMissingEmailAddress。&#34;并通过&#34;将邮箱添加到代理人的帐户来处理它。&#34;

我明天会检查是否向服务帐户添加邮箱(否则根本不使用)可以解决问题。

1 个答案:

答案 0 :(得分:0)

检查(Microsoft.Exchange.WebServices.Data)FolderId类,它显示在为请求编写Xml时,我认为它应该包含Mailbox条目。它还显示如果你使用ToString()它,它应该返回文件夹ID和邮箱ID。我建议您确认使用的邮箱&#34;新邮箱(theMailboxEmailAddress)&#34;不是null,值是您所期望的。我还注意到,当FolderId中的FolderName有一个值时,GetXmlElementName只返回DistinguishedFolderId - 从目前为止我看到的只有当使用uniqueId字符串而不是WellKnownFolderName创建FolderId时才会出现。

    internal override string GetXmlElementName()
    {
        if (!this.FolderName.HasValue)
        {
            return "FolderId";
        }
        return "DistinguishedFolderId";
    }

    public FolderId(WellKnownFolderName folderName, Mailbox mailbox) : this(folderName)
    {
        this.mailbox = mailbox;
    }

    internal override void WriteAttributesToXml(EwsServiceXmlWriter writer)
    {
        if (this.FolderName.HasValue)
        {
            writer.WriteAttributeValue("Id", this.FolderName.Value.ToString().ToLowerInvariant());
            if (this.Mailbox != null)
            {
                this.Mailbox.WriteToXml(writer, "Mailbox");
                return;
            }
        }
        else
        {
            base.WriteAttributesToXml(writer);
        }
    }

    public override string ToString()
    {
        if (!this.IsValid)
        {
            return string.Empty;
        }
        if (!this.FolderName.HasValue)
        {
            return base.ToString();
        }
        if (this.Mailbox != null && this.mailbox.IsValid)
        {
            return string.Format("{0} ({1})", this.folderName.Value, this.Mailbox.ToString());
        }
        return this.FolderName.Value.ToString();
    }

更新1: 我仍然能够快速追踪。这些是我的一些快速测试代码的结果:

folder = New FolderId(WellKnownFolderName.Inbox)
Dim v As New ItemView(10, 0, OffsetBasePoint.Beginning)
Dim f As FindItemsResults(Of Item) = oService.FindItems(folder, v)

    <m:ParentFolderIds>
      <t:DistinguishedFolderId Id="inbox" />
    </m:ParentFolderIds>



Dim box As New Mailbox(mailboxAddress)
folder = New FolderId(WellKnownFolderName.Inbox, box)
Dim v As New ItemView(10, 0, OffsetBasePoint.Beginning)
Dim f As FindItemsResults(Of Item) = oService.FindItems(folder, v)

  <m:ParentFolderIds>
      <t:DistinguishedFolderId Id="inbox">
        <t:Mailbox>
          <t:EmailAddress>****mailboxAddress****</t:EmailAddress>
        </t:Mailbox>
      </t:DistinguishedFolderId>
    </m:ParentFolderIds>

更新2:

确认使用使用uniqueId字符串创建的FolderId时,跟踪为:

    <m:ParentFolderIds>
      <t:FolderId Id="AQMkADY5YmEzNGJmLTljN2QtNDIwNS1hMWU2LTg4ADM4NDAzMDcxMGEALgAAA83F9dM/SH5Lnnw/6ftMMB0BANfWBWp5+bpGsBoSfk3Km5IAAAINKgAAAA==" ChangeKey="AQAAABYAAADX1gVqefm6RrAaEn5NypuSAAC8Vr7C" />
    </m:ParentFolderIds>