EWS 报告 SendItem 成功但邮件仍在草稿文件夹中
EWS reports SendItem as succeeding but message is still in Drafts folder
我正在使用 EWS Managed API 通过交换发送电子邮件。发送带有附件的项目时,我首先执行 CreateItem
,然后执行 SendItem
。大多数情况下这工作正常,但有时项目会留在草稿文件夹中,即使 EWS 报告 SendItem
成功。我怎么知道这里发生了什么?
我从跟踪中看到的 EWS 消息是第一个 CreateItem
:
<?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="Exchange2013" />
</soap:Header>
<soap:Body>
<m:CreateItem MessageDisposition="SaveOnly">
<m:SavedItemFolderId>
<t:DistinguishedFolderId Id="drafts">
<t:Mailbox>
<t:EmailAddress>amailbox@thedomain.com</t:EmailAddress>
</t:Mailbox>
</t:DistinguishedFolderId>
</m:SavedItemFolderId>
...
</m:CreateItem>
</soap:Body>
</soap:Envelope>
</Trace>
我收到成功响应:
<?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="1104" MinorBuildNumber="3" Version="V2_22" 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: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="Success">
<m:ResponseCode>NoError</m:ResponseCode>
<m:Items>
<t:Message>
<t:ItemId Id="AAMkADExMmY0MTgzLWJmZmUtNDcxNi1iOTk0LWMzZTU3M2I3NjBkMwBGAAAAAABL/dBAdDByRbztYn12Cy/4BwCJZGY3HQ5zQpbF9WoRXD0sAAAAAAEPAACJZGY3HQ5zQpbF9WoRXD0sAAA6HNVuAAA=" ChangeKey="CQAAABYAAACJZGY3HQ5zQpbF9WoRXD0sAAA6JC4z" />
<t:Attachments>
<t:FileAttachment>
<t:AttachmentId Id="AAMkADExMmY0MTgzLWJmZmUtNDcxNi1iOTk0LWMzZTU3M2I3NjBkMwBGAAAAAABL/dBAdDByRbztYn12Cy/4BwCJZGY3HQ5zQpbF9WoRXD0sAAAAAAEPAACJZGY3HQ5zQpbF9WoRXD0sAAA6HNVuAAABEgAQAGiKX5lgtuFLgfIBgyg4IwM=" />
</t:FileAttachment>
<t:FileAttachment>
<t:AttachmentId Id="AAMkADExMmY0MTgzLWJmZmUtNDcxNi1iOTk0LWMzZTU3M2I3NjBkMwBGAAAAAABL/dBAdDByRbztYn12Cy/4BwCJZGY3HQ5zQpbF9WoRXD0sAAAAAAEPAACJZGY3HQ5zQpbF9WoRXD0sAAA6HNVuAAABEgAQADkNd4D6H0NAgxCM7uH6MGo=" />
</t:FileAttachment>
<t:FileAttachment>
<t:AttachmentId Id="AAMkADExMmY0MTgzLWJmZmUtNDcxNi1iOTk0LWMzZTU3M2I3NjBkMwBGAAAAAABL/dBAdDByRbztYn12Cy/4BwCJZGY3HQ5zQpbF9WoRXD0sAAAAAAEPAACJZGY3HQ5zQpbF9WoRXD0sAAA6HNVuAAABEgAQAKu2RdYFlBVIiLyPxshNCZQ=" />
</t:FileAttachment>
<t:FileAttachment>
<t:AttachmentId Id="AAMkADExMmY0MTgzLWJmZmUtNDcxNi1iOTk0LWMzZTU3M2I3NjBkMwBGAAAAAABL/dBAdDByRbztYn12Cy/4BwCJZGY3HQ5zQpbF9WoRXD0sAAAAAAEPAACJZGY3HQ5zQpbF9WoRXD0sAAA6HNVuAAABEgAQAJ2C2tyz2iJHm8XC9LmSkcA=" />
</t:FileAttachment>
</t:Attachments>
</t:Message>
</m:Items>
</m:CreateItemResponseMessage>
</m:ResponseMessages>
</m:CreateItemResponse>
</s:Body>
</s:Envelope>
</Trace>
然后我要求发送它并移动到 SentItems:
<?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="Exchange2013" />
</soap:Header>
<soap:Body>
<m:SendItem SaveItemToFolder="true">
<m:ItemIds>
<t:ItemId Id="AAMkADExMmY0MTgzLWJmZmUtNDcxNi1iOTk0LWMzZTU3M2I3NjBkMwBGAAAAAABL/dBAdDByRbztYn12Cy/4BwCJZGY3HQ5zQpbF9WoRXD0sAAAAAAEPAACJZGY3HQ5zQpbF9WoRXD0sAAA6HNVuAAA=" ChangeKey="CQAAABYAAACJZGY3HQ5zQpbF9WoRXD0sAAA6JC4z" />
</m:ItemIds>
<m:SavedItemFolderId>
<t:DistinguishedFolderId Id="sentitems">
<t:Mailbox>
<t:EmailAddress>amailbox@thedomain.com</t:EmailAddress>
</t:Mailbox>
</t:DistinguishedFolderId>
</m:SavedItemFolderId>
</m:SendItem>
</soap:Body>
</soap:Envelope>
</Trace>
然后我收到成功无错误响应:
<?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="1104" MinorBuildNumber="3" Version="V2_22" 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:SendItemResponse xmlns:m="http://schemas.microsoft.com/exchange/services/2006/messages" xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types">
<m:ResponseMessages>
<m:SendItemResponseMessage ResponseClass="Success">
<m:ResponseCode>NoError</m:ResponseCode>
</m:SendItemResponseMessage>
</m:ResponseMessages>
</m:SendItemResponse>
</s:Body>
</s:Envelope>
</Trace>
这些都是由同一个托管 ThreadId 跟踪的,所以我很确定它们都对应于同一个项目。
我没有使用交换模拟。我正在使用用户名和密码 auth 以及发送邮件的邮箱的凭据进行身份验证。
编辑(5 月 22 日):
我已将 X-AnchorMailbox header 添加到我的请求中并升级到 EWS Managed API 2.2(使用的是 2.1,尽管因为 SOAP 消息看起来正确,我认为这是一个问题)。问题仍然存在。
我在发送后向 re-retrieve 项目添加了代码,以检查它是否仍在“草稿”文件夹中。我通过 EmailMessage.Bind()
使用刚从草稿发送的项目的 ID 来执行此操作。当我 运行 针对 Office 365 上的 Exchange 时,总是会引发异常,因为该项目不再存在,这是预期的,因为项目移动文件夹时 ItemId 会发生变化。当我 运行 针对客户的 Exchange 服务器时,它通过该 ID 找到项目。然后我尝试重新发送它并获得 ServiceResponseException
消息 Access is denied. Check credentials and try again.
如果我尝试重新发送针对 Office 365 的消息,我会收到 SendItemResponse
消息 The specified object was not found in the store., The process failed to get the correct properties.
(SOAP 消息是SendItemResponse
响应代码 ErrorItemNotFound
.
我已经向 Microsoft 提出了支持请求(奇怪的是,超过 48 小时都没有得到回应......也许提出支持请求有一些技巧)。
编辑(5 月 24 日)
在重复测试时,我有时会看到保留在草稿中的项目,但收件人也收到了!通过 outlook 检查他们的属性 > Internet Headers 时,他们都具有相同的 Message-ID。更多迹象表明在 Exchange 方面出现问题?
编辑(5 月 30 日)
我从 Microsoft 支持人员那里听说,他们解释了一些关于发送交换的工作原理以及他们认为正在发生的事情:
a No error response from EWS means that the message was
successfully flagged for submissions (PR_MESSAGE_FLAGS >
MSGFLAG_SUBMIT). When the submission flag is set, the Mail Submission
service on Exchange notifies the Transport Service that there are
messages awaiting to be picked up in the Drafts (Outbox if Outlook).
If any client reads the message after it’s been flagged for submission
but before it’s picked up by the Transport service, the MSGFLAG_SUBMIT
flag is removed which leads to the message being stuck in the Drafts
folder.
In order to determine if this is the case, you can sign up for notifications using Streaming Notifications (and a tool the likes of
EWSEditor or EwsStreaming) and check for any item Modified events and
check for any PR_MESSAGE_FLAGS changes.
As discussed, the message could have been accessed by any client or API before the transport service went to pick it up, such as OWA,
Outlook, EWS Managed API, Outlook add-ins or any mobile apps.
所以下一个任务是双重的:
在消息标记为要发送后立即确定是否有任何内容正在阅读我的消息,并重置 MSGFLAG_SUBMIT 标记。如果有,请他们停止。
为 re-send 我认为已发送但后来在草稿中找到的项目添加流程。
我没有得到任何关于为什么我在尝试重新发送时会收到 Access Denied
的信息,但也许这与修改项目的其他内容一致。
他们认为这不可能是 EWS 中的问题,EWS 错误地报告了成功,而实际上邮件还没有被标记为要发送。让人安心。
编辑(6 月 20 日):
为 re-send 卡在草稿中的项目引入流程效果不佳。事实证明,有时当项目留在草稿中时,它们实际上已经被收件人发送和接收,所以 re-send 发送它们意味着收件人得到了电子邮件的副本。或者多次,如果同样的问题再次发生。有时,该项目未发送但仍从草稿中删除并移至已发送项目 - 同样,发件人无法确定它是否已发送。完全奇怪。我在这里问了另一个问题,具体是 Exchange message sending is expected to be atomic and reliable。
也发布在 Exchange forums
将 'MessageFlags' MAPI 扩展 属性 设置为 'Read',这样项目就不会被标记为 'Draft'。
这里是扩展的 属性 定义:
/// <summary>
/// Definitions of Microsoft's Mail API (MAPI) extended properties that you can get/set on mailbox items via EWS interface
/// </summary>
public static class MapiSchema
{
/// <summary>
/// Definition of MAPI property unique identifiers
/// </summary>
public static class Tags
{
/// <summary>
/// Message flags (like 'read', 'unsent'; see PR_MESSAGE_FLAGS online)
/// </summary>
public const int MessageFlags = 0x0E07;
}
/// <summary>
/// Message flags (like 'read', 'unsent'; see PR_MESSAGE_FLAGS online)
/// </summary>
public static readonly ExtendedPropertyDefinition MessageFlags = new ExtendedPropertyDefinition(Tags.MessageFlags, MapiPropertyType.Integer);
}
以下是此 属性 的可能值(标志):
/// <summary>
/// Values for the PR_MESSAGE_FLAGS message property (Microsoft's Message API)
/// </summary>
[Flags]
public enum MessageFlags
{
/// <summary>
/// No flags set
/// </summary>
None = 0,
/// <summary>
/// [MSGFLAG_READ] The message is marked as having been read. This can occur as the result of a call at any time to IMessage::SetReadFlag or IMAPIFolder::SetReadFlags. Clients can also set this flag by calling a message's IMAPIProp::SetProps method before the message has been saved for the first time. This flag is ignored if the MSGFLAG_ASSOCIATED flag is set.
/// </summary>
Read = 1,
/// <summary>
/// [MSGFLAG_UNMODIFIED] The outgoing message has not been modified since the first time that it was saved; the incoming message has not been modified since it was delivered.
/// </summary>
Unmodified = 2,
/// <summary>
/// [MSGFLAG_SUBMIT] The message is marked for sending as a result of a call to IMessage::SubmitMessage. Message store providers set this flag; the client has read-only access.
/// </summary>
Submit = 4,
/// <summary>
/// [MSGFLAG_UNSENT] The message is still being composed. It is saved, but has not been sent. The client or provider has read/write access to this flag until the first IMAPIProp::SaveChanges call and read-only thereafter. If a client doesn't set this flag by the time the message is sent, the message store provider sets it when IMessage::SubmitMessage is called. Typically, this flag is cleared after the message is sent.
/// </summary>
Unsent = 8,
/// <summary>
/// [MSGFLAG_HASATTACH] The message has at least one attachment. This flag corresponds to the message's PR_HASATTACH (PidTagHasAttachments) property. The client has read-only access to this flag.
/// </summary>
HasAttachment = 16,
/// <summary>
/// [MSGFLAG_FROMME] The messaging user sending was the messaging user receiving the message. The client or provider has read/write access to this flag until the first IMAPIProp::SaveChanges call and read-only thereafter. This flag is meant to be set by the transport provider.
/// </summary>
FromMe = 32,
/// <summary>
/// [MSGFLAG_ASSOCIATED] The message is an associated message of a folder. The client or provider has read-only access to this flag. The MSGFLAG_READ flag is ignored for associated messages, which do not retain a read/unread state.
/// </summary>
Associated = 64,
/// <summary>
/// [MSGFLAG_RESEND] The message includes a request for a resend operation with a nondelivery report. The client or provider has read/write access to this flag until the first IMAPIProp::SaveChanges call and read-only thereafter.
/// </summary>
Resend = 128,
/// <summary>
/// [MSGFLAG_RN_PENDING] A read report needs to be sent for the message. The client or provider has read-only access to this flag.
/// </summary>
ReadReportPending = 256,
/// <summary>
/// [MSGFLAG_NRN_PENDING] A nonread report needs to be sent for the message. The client or provider has read-only access to this flag.
/// </summary>
NonReadReportPending = 512,
/// <summary>
/// [MSGFLAG_ORIGIN_X400] The incoming message arrived over an X.400 link. It originated either outside the organization or from a source the gateway cannot consider trusted. The client should display an appropriate message to the user. Transport providers set this flag; the client has read-only access.
/// </summary>
OriginX400 = 4096,
/// <summary>
/// [MSGFLAG_ORIGIN_INTERNET] The incoming message arrived over the Internet. It originated either outside the organization or from a source the gateway cannot consider trusted. The client should display an appropriate message to the user. Transport providers set this flag; the client has read-only access.
/// </summary>
OriginInternet = 8192,
/// <summary>
/// [MSGFLAG_ORIGIN_MISC_EXT] The incoming message arrived over an external link other than X.400 or the Internet. It originated either outside the organization or from a source the gateway cannot consider trusted. The client should display an appropriate message to the user. Transport providers set this flag; the client has read-only access.
/// </summary>
OriginOtherExternal = 32768,
}
下面是创建项目之前的设置方式:
var item = new EmailMessage(service);
var messageFlags = MessageFlags.Read;
item.SetExtendedProperty(MapiSchema.MessageFlags, (int)messageFlags);
Exchange 漏洞百出,希望能解决问题。
取自MSDN documentation on SendItem:
An additional scenario
to consider is when a delegate creates an e-mail message and saves it
to the Drafts folder of the delegate's mailbox. If the delegate tries
to send the item and save a copy to the principal's Sent Items
distinguished folder, the message is sent correctly, the draft message
remains in the delegate's Drafts folder, the sent message does not
appear in either the delegate's or principal's Sent Items folder, and
the response is a success.
文档似乎说你运气不好...最好的解决方法可能是将发送和移动到已发送的项目也作为两个单独的函数执行。
我没有解决这个问题,只是按照 MS 支持人员的建议,尽可能确保没有其他应用程序同时与邮箱交互。我们更改了邮箱的权限,以阻止某些有权访问共享邮箱并可以通过 Outlook 访问该邮箱的人。这完全解决了遇到问题的主要客户的问题。但是对我来说仍然很奇怪 EWS/exchange 会如此不可靠,鉴于此类问题,我永远不会选择再次使用它。它也没有解释邮件已发送但仍保留在草稿文件夹中的情况,这意味着无法确定发送是成功还是失败。
我正在使用 EWS Managed API 通过交换发送电子邮件。发送带有附件的项目时,我首先执行 CreateItem
,然后执行 SendItem
。大多数情况下这工作正常,但有时项目会留在草稿文件夹中,即使 EWS 报告 SendItem
成功。我怎么知道这里发生了什么?
我从跟踪中看到的 EWS 消息是第一个 CreateItem
:
<?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="Exchange2013" />
</soap:Header>
<soap:Body>
<m:CreateItem MessageDisposition="SaveOnly">
<m:SavedItemFolderId>
<t:DistinguishedFolderId Id="drafts">
<t:Mailbox>
<t:EmailAddress>amailbox@thedomain.com</t:EmailAddress>
</t:Mailbox>
</t:DistinguishedFolderId>
</m:SavedItemFolderId>
...
</m:CreateItem>
</soap:Body>
</soap:Envelope>
</Trace>
我收到成功响应:
<?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="1104" MinorBuildNumber="3" Version="V2_22" 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: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="Success">
<m:ResponseCode>NoError</m:ResponseCode>
<m:Items>
<t:Message>
<t:ItemId Id="AAMkADExMmY0MTgzLWJmZmUtNDcxNi1iOTk0LWMzZTU3M2I3NjBkMwBGAAAAAABL/dBAdDByRbztYn12Cy/4BwCJZGY3HQ5zQpbF9WoRXD0sAAAAAAEPAACJZGY3HQ5zQpbF9WoRXD0sAAA6HNVuAAA=" ChangeKey="CQAAABYAAACJZGY3HQ5zQpbF9WoRXD0sAAA6JC4z" />
<t:Attachments>
<t:FileAttachment>
<t:AttachmentId Id="AAMkADExMmY0MTgzLWJmZmUtNDcxNi1iOTk0LWMzZTU3M2I3NjBkMwBGAAAAAABL/dBAdDByRbztYn12Cy/4BwCJZGY3HQ5zQpbF9WoRXD0sAAAAAAEPAACJZGY3HQ5zQpbF9WoRXD0sAAA6HNVuAAABEgAQAGiKX5lgtuFLgfIBgyg4IwM=" />
</t:FileAttachment>
<t:FileAttachment>
<t:AttachmentId Id="AAMkADExMmY0MTgzLWJmZmUtNDcxNi1iOTk0LWMzZTU3M2I3NjBkMwBGAAAAAABL/dBAdDByRbztYn12Cy/4BwCJZGY3HQ5zQpbF9WoRXD0sAAAAAAEPAACJZGY3HQ5zQpbF9WoRXD0sAAA6HNVuAAABEgAQADkNd4D6H0NAgxCM7uH6MGo=" />
</t:FileAttachment>
<t:FileAttachment>
<t:AttachmentId Id="AAMkADExMmY0MTgzLWJmZmUtNDcxNi1iOTk0LWMzZTU3M2I3NjBkMwBGAAAAAABL/dBAdDByRbztYn12Cy/4BwCJZGY3HQ5zQpbF9WoRXD0sAAAAAAEPAACJZGY3HQ5zQpbF9WoRXD0sAAA6HNVuAAABEgAQAKu2RdYFlBVIiLyPxshNCZQ=" />
</t:FileAttachment>
<t:FileAttachment>
<t:AttachmentId Id="AAMkADExMmY0MTgzLWJmZmUtNDcxNi1iOTk0LWMzZTU3M2I3NjBkMwBGAAAAAABL/dBAdDByRbztYn12Cy/4BwCJZGY3HQ5zQpbF9WoRXD0sAAAAAAEPAACJZGY3HQ5zQpbF9WoRXD0sAAA6HNVuAAABEgAQAJ2C2tyz2iJHm8XC9LmSkcA=" />
</t:FileAttachment>
</t:Attachments>
</t:Message>
</m:Items>
</m:CreateItemResponseMessage>
</m:ResponseMessages>
</m:CreateItemResponse>
</s:Body>
</s:Envelope>
</Trace>
然后我要求发送它并移动到 SentItems:
<?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="Exchange2013" />
</soap:Header>
<soap:Body>
<m:SendItem SaveItemToFolder="true">
<m:ItemIds>
<t:ItemId Id="AAMkADExMmY0MTgzLWJmZmUtNDcxNi1iOTk0LWMzZTU3M2I3NjBkMwBGAAAAAABL/dBAdDByRbztYn12Cy/4BwCJZGY3HQ5zQpbF9WoRXD0sAAAAAAEPAACJZGY3HQ5zQpbF9WoRXD0sAAA6HNVuAAA=" ChangeKey="CQAAABYAAACJZGY3HQ5zQpbF9WoRXD0sAAA6JC4z" />
</m:ItemIds>
<m:SavedItemFolderId>
<t:DistinguishedFolderId Id="sentitems">
<t:Mailbox>
<t:EmailAddress>amailbox@thedomain.com</t:EmailAddress>
</t:Mailbox>
</t:DistinguishedFolderId>
</m:SavedItemFolderId>
</m:SendItem>
</soap:Body>
</soap:Envelope>
</Trace>
然后我收到成功无错误响应:
<?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="1104" MinorBuildNumber="3" Version="V2_22" 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:SendItemResponse xmlns:m="http://schemas.microsoft.com/exchange/services/2006/messages" xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types">
<m:ResponseMessages>
<m:SendItemResponseMessage ResponseClass="Success">
<m:ResponseCode>NoError</m:ResponseCode>
</m:SendItemResponseMessage>
</m:ResponseMessages>
</m:SendItemResponse>
</s:Body>
</s:Envelope>
</Trace>
这些都是由同一个托管 ThreadId 跟踪的,所以我很确定它们都对应于同一个项目。
我没有使用交换模拟。我正在使用用户名和密码 auth 以及发送邮件的邮箱的凭据进行身份验证。
编辑(5 月 22 日):
我已将 X-AnchorMailbox header 添加到我的请求中并升级到 EWS Managed API 2.2(使用的是 2.1,尽管因为 SOAP 消息看起来正确,我认为这是一个问题)。问题仍然存在。
我在发送后向 re-retrieve 项目添加了代码,以检查它是否仍在“草稿”文件夹中。我通过 EmailMessage.Bind()
使用刚从草稿发送的项目的 ID 来执行此操作。当我 运行 针对 Office 365 上的 Exchange 时,总是会引发异常,因为该项目不再存在,这是预期的,因为项目移动文件夹时 ItemId 会发生变化。当我 运行 针对客户的 Exchange 服务器时,它通过该 ID 找到项目。然后我尝试重新发送它并获得 ServiceResponseException
消息 Access is denied. Check credentials and try again.
如果我尝试重新发送针对 Office 365 的消息,我会收到 SendItemResponse
消息 The specified object was not found in the store., The process failed to get the correct properties.
(SOAP 消息是SendItemResponse
响应代码 ErrorItemNotFound
.
我已经向 Microsoft 提出了支持请求(奇怪的是,超过 48 小时都没有得到回应......也许提出支持请求有一些技巧)。
编辑(5 月 24 日)
在重复测试时,我有时会看到保留在草稿中的项目,但收件人也收到了!通过 outlook 检查他们的属性 > Internet Headers 时,他们都具有相同的 Message-ID。更多迹象表明在 Exchange 方面出现问题?
编辑(5 月 30 日)
我从 Microsoft 支持人员那里听说,他们解释了一些关于发送交换的工作原理以及他们认为正在发生的事情:
a No error response from EWS means that the message was successfully flagged for submissions (PR_MESSAGE_FLAGS > MSGFLAG_SUBMIT). When the submission flag is set, the Mail Submission service on Exchange notifies the Transport Service that there are messages awaiting to be picked up in the Drafts (Outbox if Outlook). If any client reads the message after it’s been flagged for submission but before it’s picked up by the Transport service, the MSGFLAG_SUBMIT flag is removed which leads to the message being stuck in the Drafts folder.
In order to determine if this is the case, you can sign up for notifications using Streaming Notifications (and a tool the likes of EWSEditor or EwsStreaming) and check for any item Modified events and check for any PR_MESSAGE_FLAGS changes.
As discussed, the message could have been accessed by any client or API before the transport service went to pick it up, such as OWA, Outlook, EWS Managed API, Outlook add-ins or any mobile apps.
所以下一个任务是双重的:
在消息标记为要发送后立即确定是否有任何内容正在阅读我的消息,并重置 MSGFLAG_SUBMIT 标记。如果有,请他们停止。
为 re-send 我认为已发送但后来在草稿中找到的项目添加流程。
我没有得到任何关于为什么我在尝试重新发送时会收到 Access Denied
的信息,但也许这与修改项目的其他内容一致。
他们认为这不可能是 EWS 中的问题,EWS 错误地报告了成功,而实际上邮件还没有被标记为要发送。让人安心。
编辑(6 月 20 日):
为 re-send 卡在草稿中的项目引入流程效果不佳。事实证明,有时当项目留在草稿中时,它们实际上已经被收件人发送和接收,所以 re-send 发送它们意味着收件人得到了电子邮件的副本。或者多次,如果同样的问题再次发生。有时,该项目未发送但仍从草稿中删除并移至已发送项目 - 同样,发件人无法确定它是否已发送。完全奇怪。我在这里问了另一个问题,具体是 Exchange message sending is expected to be atomic and reliable。
也发布在 Exchange forums
将 'MessageFlags' MAPI 扩展 属性 设置为 'Read',这样项目就不会被标记为 'Draft'。
这里是扩展的 属性 定义:
/// <summary>
/// Definitions of Microsoft's Mail API (MAPI) extended properties that you can get/set on mailbox items via EWS interface
/// </summary>
public static class MapiSchema
{
/// <summary>
/// Definition of MAPI property unique identifiers
/// </summary>
public static class Tags
{
/// <summary>
/// Message flags (like 'read', 'unsent'; see PR_MESSAGE_FLAGS online)
/// </summary>
public const int MessageFlags = 0x0E07;
}
/// <summary>
/// Message flags (like 'read', 'unsent'; see PR_MESSAGE_FLAGS online)
/// </summary>
public static readonly ExtendedPropertyDefinition MessageFlags = new ExtendedPropertyDefinition(Tags.MessageFlags, MapiPropertyType.Integer);
}
以下是此 属性 的可能值(标志):
/// <summary>
/// Values for the PR_MESSAGE_FLAGS message property (Microsoft's Message API)
/// </summary>
[Flags]
public enum MessageFlags
{
/// <summary>
/// No flags set
/// </summary>
None = 0,
/// <summary>
/// [MSGFLAG_READ] The message is marked as having been read. This can occur as the result of a call at any time to IMessage::SetReadFlag or IMAPIFolder::SetReadFlags. Clients can also set this flag by calling a message's IMAPIProp::SetProps method before the message has been saved for the first time. This flag is ignored if the MSGFLAG_ASSOCIATED flag is set.
/// </summary>
Read = 1,
/// <summary>
/// [MSGFLAG_UNMODIFIED] The outgoing message has not been modified since the first time that it was saved; the incoming message has not been modified since it was delivered.
/// </summary>
Unmodified = 2,
/// <summary>
/// [MSGFLAG_SUBMIT] The message is marked for sending as a result of a call to IMessage::SubmitMessage. Message store providers set this flag; the client has read-only access.
/// </summary>
Submit = 4,
/// <summary>
/// [MSGFLAG_UNSENT] The message is still being composed. It is saved, but has not been sent. The client or provider has read/write access to this flag until the first IMAPIProp::SaveChanges call and read-only thereafter. If a client doesn't set this flag by the time the message is sent, the message store provider sets it when IMessage::SubmitMessage is called. Typically, this flag is cleared after the message is sent.
/// </summary>
Unsent = 8,
/// <summary>
/// [MSGFLAG_HASATTACH] The message has at least one attachment. This flag corresponds to the message's PR_HASATTACH (PidTagHasAttachments) property. The client has read-only access to this flag.
/// </summary>
HasAttachment = 16,
/// <summary>
/// [MSGFLAG_FROMME] The messaging user sending was the messaging user receiving the message. The client or provider has read/write access to this flag until the first IMAPIProp::SaveChanges call and read-only thereafter. This flag is meant to be set by the transport provider.
/// </summary>
FromMe = 32,
/// <summary>
/// [MSGFLAG_ASSOCIATED] The message is an associated message of a folder. The client or provider has read-only access to this flag. The MSGFLAG_READ flag is ignored for associated messages, which do not retain a read/unread state.
/// </summary>
Associated = 64,
/// <summary>
/// [MSGFLAG_RESEND] The message includes a request for a resend operation with a nondelivery report. The client or provider has read/write access to this flag until the first IMAPIProp::SaveChanges call and read-only thereafter.
/// </summary>
Resend = 128,
/// <summary>
/// [MSGFLAG_RN_PENDING] A read report needs to be sent for the message. The client or provider has read-only access to this flag.
/// </summary>
ReadReportPending = 256,
/// <summary>
/// [MSGFLAG_NRN_PENDING] A nonread report needs to be sent for the message. The client or provider has read-only access to this flag.
/// </summary>
NonReadReportPending = 512,
/// <summary>
/// [MSGFLAG_ORIGIN_X400] The incoming message arrived over an X.400 link. It originated either outside the organization or from a source the gateway cannot consider trusted. The client should display an appropriate message to the user. Transport providers set this flag; the client has read-only access.
/// </summary>
OriginX400 = 4096,
/// <summary>
/// [MSGFLAG_ORIGIN_INTERNET] The incoming message arrived over the Internet. It originated either outside the organization or from a source the gateway cannot consider trusted. The client should display an appropriate message to the user. Transport providers set this flag; the client has read-only access.
/// </summary>
OriginInternet = 8192,
/// <summary>
/// [MSGFLAG_ORIGIN_MISC_EXT] The incoming message arrived over an external link other than X.400 or the Internet. It originated either outside the organization or from a source the gateway cannot consider trusted. The client should display an appropriate message to the user. Transport providers set this flag; the client has read-only access.
/// </summary>
OriginOtherExternal = 32768,
}
下面是创建项目之前的设置方式:
var item = new EmailMessage(service);
var messageFlags = MessageFlags.Read;
item.SetExtendedProperty(MapiSchema.MessageFlags, (int)messageFlags);
Exchange 漏洞百出,希望能解决问题。
取自MSDN documentation on SendItem:
An additional scenario to consider is when a delegate creates an e-mail message and saves it to the Drafts folder of the delegate's mailbox. If the delegate tries to send the item and save a copy to the principal's Sent Items distinguished folder, the message is sent correctly, the draft message remains in the delegate's Drafts folder, the sent message does not appear in either the delegate's or principal's Sent Items folder, and the response is a success.
文档似乎说你运气不好...最好的解决方法可能是将发送和移动到已发送的项目也作为两个单独的函数执行。
我没有解决这个问题,只是按照 MS 支持人员的建议,尽可能确保没有其他应用程序同时与邮箱交互。我们更改了邮箱的权限,以阻止某些有权访问共享邮箱并可以通过 Outlook 访问该邮箱的人。这完全解决了遇到问题的主要客户的问题。但是对我来说仍然很奇怪 EWS/exchange 会如此不可靠,鉴于此类问题,我永远不会选择再次使用它。它也没有解释邮件已发送但仍保留在草稿文件夹中的情况,这意味着无法确定发送是成功还是失败。