英文:
EWS ExtendedPropertyDefinition search filter no longer filtering
问题
在过去的十多年里,我们一直在使用C#代码通过EWS与Exchange进行通信。几乎所有的客户都迁移到了Office 365,我们的代码在O365通过EWS上运行得非常正常,直到最近。
我们的软件处理接收到Exchange邮箱的电子邮件。这个邮箱既被人类使用,也被我们的软件使用,因此我们一直使用扩展属性来跟踪我们已经处理过的电子邮件。以下是代码示例:
// 构建扩展属性定义
Guid readByEmailComponentGUID = new Guid("{FCF74ABF-684E-4cc7-8A83-B36D3A209219}"); //我们属性的GUID
ExtendedPropertyDefinition X_READBYCOMPONENT = new ExtendedPropertyDefinition(readByEmailComponentGUID, "X_READBYCOMPONENT", MapiPropertyType.Boolean); //我们属性的设置和名称
// 创建用于查询EWS的搜索过滤器
SearchFilter.SearchFilterCollection srchFilter = new SearchFilter.SearchFilterCollection(LogicalOperator.Or);
srchFilter.Add(new SearchFilter.Not(new SearchFilter.Exists(X_READBYCOMPONENT))); //显示没有我们新属性的消息(从未接收过的)
srchFilter.Add(new SearchFilter.IsEqualTo(X_READBYCOMPONENT, false)); //显示具有我们新属性但其值为false的消息(重新接收)
ItemView view = new ItemView(250, 0, OffsetBasePoint.Beginning);
// 使用我们的搜索过滤器和视图查询EWS
FindItemsResults<Item> findResults = EWSService.FindItems("Inbox", srchFilter, view);
// 处理我们搜索的结果
foreach (Item item in findResults){
// 检查这封电子邮件是否有我们的内部读取标志,并且如果有,不要再次处理它。
ExtendedProperty ReadByComponentFlag = item.ExtendedProperties.FirstOrDefault(itm => itm.PropertyDefinition == X_READBYCOMPONENT);
if (!(ReadByComponentFlag is null) && (bool)ReadByComponentFlag.Value == true)
{
continue;
}
if (item is EmailMessage){
EmailMessage em = item as EmailMessage; //加载电子邮件消息
// 处理邮件消息,处理完成后将其标记为已读
em.SetExtendedProperty(X_READBYCOMPONENT, true); //将我们的新属性设置为TRUE,以排除将来接收此邮件的情况
em.Update(ConflictResolutionMode.NeverOverwrite);
}
}
自2011年以来,这段代码一直运行得非常出色,但大约一个月前,我们的Office 365客户的搜索过滤器开始失败,EWS返回了每封电子邮件消息。当电子邮件消息进来时,手动查看其扩展属性,我可以看到我们的自定义属性仍然存在,并且仍然设置为true。
EWS在O365上如何处理这些过滤器是否发生了任何变化?是否有其他人遇到类似的问题?
目前,我们已经添加了一个解决方法(您可以在上面的代码中看到),手动检查扩展属性并跳过电子邮件,但这不是一个可行的长期解决方案,因为其中一些邮箱中包含了14,000封电子邮件,我们每次运行都要提取和接收它们。
英文:
For literally over a decade we have had C# code that talks to Exchange via EWS. Virtually all our clients have migrated to Office 365, and the our code was operating perfectly fine on O365 via EWS, until recently.
Our software processes emails that are received into an Exchange mailbox. This mailbox is used by humans as well as our software, so we've been using an ExtendedProperty to keep track of which emails we have processed. The code is thus:
// Build our extended property definition
Guid readByEmailComponentGUID = new Guid("{FCF74ABF-684E-4cc7-8A83-B36D3A209219}"); //GUID for our property
ExtendedPropertyDefinition X_READBYCOMPONENT = new ExtendedPropertyDefinition(readByEmailComponentGUID, "X_READBYCOMPONENT", MapiPropertyType.Boolean); //Settings and name for our property
// Create a search filter for querying EWS
SearchFilter.SearchFilterCollection srchFilter = new SearchFilter.SearchFilterCollection(LogicalOperator.Or);
srchFilter.Add(new SearchFilter.Not(new SearchFilter.Exists(X_READBYCOMPONENT))); //Show messages that do not have our new property (thus have never been received)
srchFilter.Add(new SearchFilter.IsEqualTo(X_READBYCOMPONENT, false)); //Show messages that have our new property, but it's set to false (to re-receive)
ItemView view = new ItemView(250, 0, OffsetBasePoint.Beginning);
// Query EWS with our search filter and our view
FindItemsResults<Item> findResults = EWSService.FindItems("Inbox", srchFilter, view);
// Process the results of our search
foreach (Item item in findResults){
// Check to see if this email has our internal read flag on it, and if it does, do not process it again.
ExtendedProperty ReadByComponentFlag = item.ExtendedProperties.FirstOrDefault(itm => itm.PropertyDefinition == X_READBYCOMPONENT);
if (!(ReadByComponentFlag is null) && (bool)ReadByComponentFlag.Value == true)
{
continue;
}
if (item is EmailMessage){
EmailMessage em = item as EmailMessage; //Load the email message
// process the mail message and when that's done mark it as read
em.SetExtendedProperty(X_READBYCOMPONENT, true); //Sets our new property to TRUE to exclude this email from future receive actions
em.Update(ConflictResolutionMode.NeverOverwrite);
}
}
Since 2011 that code has been working brilliantly, but starting around a month ago our customers on Office 365 have had their search filters failing, and EWS has been returning every single email message. Inspecting the email messages as they come through and manually looking at their extended properties I can see that our custom property IS present, and that it IS still set to true.
Has anything changed in how EWS on O365 processes these filters? Has anyone else run into similar issues?
Right now we've added a workaround (which you can see in the code above) to manually inspect the extended properties and skip the email but this is not a viable long-term solution as some of these mailboxes have 14,000 emails in them that we are pulling and receiving every run.
答案1
得分: 1
以下是您要求的代码部分的翻译:
我尝试使用相同的属性和逻辑来重现此问题,但无法如下所示:
var InboxFolder = Folder.Bind(exchangeService, WellKnownFolderName.Inbox);
// 为查询EWS构建搜索过滤器
// 构建扩展属性定义
Guid readByEmailComponentGUID = new Guid("{FCF74ABF-684E-4cc7-8A83-B36D3A209219}"); // 我们属性的GUID
ExtendedPropertyDefinition X_READBYCOMPONENT = new ExtendedPropertyDefinition(readByEmailComponentGUID, "X_READBYCOMPONENT", MapiPropertyType.Boolean); // 我们属性的设置和名称
Item it = InboxFolder.FindItems(new ItemView(1)).Items[0];
it.SetExtendedProperty(X_READBYCOMPONENT, true);
it.Update(ConflictResolutionMode.AutoResolve);
SearchFilter.SearchFilterCollection srchFilter = new SearchFilter.SearchFilterCollection(LogicalOperator.Or);
srchFilter.Add(new SearchFilter.Not(new SearchFilter.Exists(X_READBYCOMPONENT))); // 显示没有我们新属性的消息(从未接收过的消息)
srchFilter.Add(new SearchFilter.IsEqualTo(X_READBYCOMPONENT, false));
FindItemsResults<Item> findResults = InboxFolder.FindItems(srchFilter, new ItemView(100));
if (findResults.Items.Any(x => x.Id.UniqueId == it.Id.UniqueId))
{
Console.WriteLine("找到项目");
}
else
{
Console.WriteLine("未找到项目");
}
Console.WriteLine("完成");
如果在多个邮箱和多个环境中发生,并且您可以构建一个测试环境来重现此问题,那么您应该将其记录为Microsoft的错误报告,因为这是唯一一种能够获得某种类型的关注和修复的方式。搜索过滤器不应该出现故障,您还可以尝试在Graph上运行它,以查看是否存在相同的问题,例如,在Graph上的查询可能如下所示:
https://graph.microsoft.com/v1.0/me/mailFolders('Inbox')/messages?$filter=singleValueExtendedProperties/any(ep: ep/id eq 'Boolean {FCF74ABF-684E-4cc7-8A83-B36D3A209219} Name X_READBYCOMPONENT' and cast(ep/value, Edm.Boolean) eq null) OR singleValueExtendedProperties/any(ep: ep/id eq 'Boolean {FCF74ABF-684E-4cc7-8A83-B36D3A209219} Name X_READBYCOMPONENT' and cast(ep/value, Edm.Boolean) eq false)
您可以使用Graph Explorer进行测试,如果在Graph中发现相同的问题,那么您也可以提交一个错误报告。
英文:
I tried to reproduce the issue with the same property and logic and can't eg
var InboxFolder = Folder.Bind(exchangeService, WellKnownFolderName.Inbox);
// Create a search filter for querying EWS
// Build our extended property definition
Guid readByEmailComponentGUID = new Guid("{FCF74ABF-684E-4cc7-8A83-B36D3A209219}"); //GUID for our property
ExtendedPropertyDefinition X_READBYCOMPONENT = new ExtendedPropertyDefinition(readByEmailComponentGUID, "X_READBYCOMPONENT", MapiPropertyType.Boolean); //Settings and name for our property
Item it = InboxFolder.FindItems(new ItemView(1)).Items[0];
it.SetExtendedProperty(X_READBYCOMPONENT, true);
it.Update(ConflictResolutionMode.AutoResolve);
SearchFilter.SearchFilterCollection srchFilter = new SearchFilter.SearchFilterCollection(LogicalOperator.Or);
srchFilter.Add(new SearchFilter.Not(new SearchFilter.Exists(X_READBYCOMPONENT))); //Show messages that do not have our new property (thus have never been received)
srchFilter.Add(new SearchFilter.IsEqualTo(X_READBYCOMPONENT, false));
FindItemsResults<Item> findResults = InboxFolder.FindItems(srchFilter, new ItemView(100));
if(findResults.Items.Any(x => x.Id.UniqueId == it.Id.UniqueId))
{
Console.WriteLine("Item Found");
}
else
{
Console.WriteLine("Item not found");
}
Console.WriteLine("Done");
If it's happening on multiple mailboxes in multiple environment and you can build a test rig and reproduce the issue then you should log it as a bug with Microsoft as that is the only way you will get some type of traction/repair. Search Filter shouldn't fail open, you may also want to try it out on the Graph to see if the same problem exists eg on the Graph that query would be something like
https://graph.microsoft.com/v1.0/me/mailFolders('Inbox')/messages? $filter=singleValueExtendedProperties/any(ep: ep/id eq 'Boolean {FCF74ABF-684E-4cc7-8A83-B36D3A209219} Name X_READBYCOMPONENT' and cast(ep/value, Edm.Boolean) eq null) OR singleValueExtendedProperties/any(ep: ep/id eq 'Boolean {FCF74ABF-684E-4cc7-8A83-B36D3A209219} Name X_READBYCOMPONENT' and cast(ep/value, Edm.Boolean) eq false)
You should be able to test it with the Graph Explorer, if you find the same issue in the Graph then you can create a bug against that as well.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论