首页 > 解决方案 > C# Exchange Web 服务 - 发送并立即检索已发送的消息

问题描述

我正在使用的系统要求将MimeContent刚刚发送的电子邮件存储在本地数据库中。我对 Exchange 工作原理的理解是,它将MimeContent在服务器上创建,除非我查询服务以获取刚刚发送的消息,否则我无法访问它。

所以,我采取的步骤是:

-- 发送电子邮件并得到它Id

message.SendAndSaveCopy();
return message.Id.UniqueId;

-- 使用新的id获取刚刚发送的EmailMessage

ExchangeService exchangeService = ExchangeService;

var properties = new List<PropertyDefinitionBase>
{
    ItemSchema.MimeContent
};

EmailMessage message = EmailMessage.Bind(exchangeService, new ItemId(messageId), new PropertySet(BasePropertySet.IdOnly, properties));

当这段代码不间断地运行时,它就可以工作。返回的Id仍然有效(消息可能在发件箱文件夹中),我得到了结果。但是,如果我将其放慢一秒钟,则 Id 将不再有效(我猜它现在已移至已发送的文件夹中)。

我不能这样离开它,因为不能保证我会及时回到服务器以检索带有它的消息Id

如果有一个解决方案让我不必再次查询服务以获取消息,那就太好了。但是,如果没有,有没有办法可以使用IdandChangeKey来获取刚刚发送的电子邮件?

标签: c#asp.netemailexchange-server

解决方案


最终回答了我自己的问题。我通过在我控制的每封电子邮件上添加一个自定义属性来做到这一点。然后我使用相同的值来搜索电子邮件。我在查询之间的文件夹之间移动电子邮件时遇到了一些问题,但它现在已排序。

  • 在某处定义它,我在我的 EmailProvider 类中有它:

    private readonly PropertyDefinitionBase _TempEmailId = new ExtendedPropertyDefinition(DefaultExtendedPropertySet.PublicStrings, "TempEmailId", MapiPropertyType.String);
    
  • 然后在发送电子邮件之前添加它:

    string messageId = null;
    if (getTempId)
    {
        messageId = Guid.NewGuid().ToString();
        message.SetExtendedProperty((ExtendedPropertyDefinition) _TempEmailId, messageId);
    }
    
    message.SendAndSaveCopy();
    return messageId;
    
  • 最后,使用messageId获取MimeContent(或您想要的任何其他属性):

    /// <summary>
    /// Get the mime content for an email just sent
    /// </summary>
    /// <param name="messageId"></param>
    /// <returns></returns>
    public byte[] GetJustSentMimeContent(string messageId)
    {
        ExchangeService exchangeService = ExchangeService;
    
        // Use the following search filter to get mail with TempEmailId set to what we just got
        var searchCriteria = new SearchFilter.IsEqualTo(_TempEmailId, messageId);
    
        var itemView = new ItemView(1) {PropertySet = new PropertySet(BasePropertySet.IdOnly)};
    
        byte[] GetMimeContent(WellKnownFolderName folder)
        {
            var items = exchangeService.FindItems(folder, searchCriteria, itemView);
    
            if (items.TotalCount > 0)
            {
                // if it's still in there, try and load the properties for it
                exchangeService.LoadPropertiesForItems(items,
                    new PropertySet(BasePropertySet.IdOnly,
                        ItemSchema.MimeContent));
    
                var emailMessage = (EmailMessage) items.First();
    
                // if the content has been loaded, return it
                if (emailMessage.MimeContent != null)
                    return emailMessage.MimeContent.Content;
            }
    
            return null;
        }
    
        // check the drafts folder to see if it's still in there
        var mimeContent = GetMimeContent(WellKnownFolderName.Drafts);
    
        if (mimeContent != null)
            return mimeContent;
    
        // if at this point, either: 
        // - email was moved to SentItems before the first search was done
        // - or email was found in Drafts but then moved to SentItems but before the MimeContent could be loaded. Need to restart the process and find the email in SentItems instead
    
        // should be in here (sentItems) now, try and load the properties for it
        return GetMimeContent(WellKnownFolderName.SentItems);
    }
    

推荐阅读