我们编写了一个Outlook插件,它可以在邮件发送后启动一个动作。只有在邮件撰写过程中设置了一个标志时,才会发生动作。通过点击一个切换按钮来设置标志。当邮件正在发送时,一个事件会被触发,我们将邮件的id存储在一个队列中。如果邮件出现在发送文件夹中,事件就会触发,如果在队列中发现了相同的id,那么就会发生操作。
下面我有两个方法。Application_ItemSend将在邮件被发送时发生,在该方法中EnQueue将在SentItemsQueue上被调用。EnQueue方法将一个事件附加到Sent Items文件夹中,当一个项目被添加时,它应该启动一个事件来启动我们的动作。
当邮件在Outlook中组成和发送时,这一切都很正常。如果我们从外部程序(如Word)中启动电子邮件,那么Application_ItemSend就会被执行,但EMailFoundInSentItems(附加在EnQueue中)从未被触发。为什么该事件从未被触发?
public partial class ThisAddIn {
void Application_ItemSend(object item, ref bool cancel)
{
try
{
Trace.TraceInformation("E-mail is being sent. Checking for archive flag.");
MailItem mail = item as MailItem;
bool? archive = mail.GetArchiveFlag();
if (archive == true)
{
Trace.TraceInformation("Archive flag was set, going to queue e-mail for archiving.");
this.SentItemsQueue.EnQueue(mail);
}
Marshal.ReleaseComObject(mail);
}
catch (System.Exception ex)
{
Trace.TraceError("An exception was thrown while trying to archive a sent mail item. Exception: {0}.", ex.ToString());
}
}
...
public class SentItemsArchiveQueue
{
public void EnQueue(MailItem mail)
{
// remove and re-add handler (remove first, so it's not registered twice)
mail.SaveSentMessageFolder.Items.ItemAdd -= new ItemsEvents_ItemAddEventHandler(EMailFoundInSentItems);
mail.SaveSentMessageFolder.Items.ItemAdd += new ItemsEvents_ItemAddEventHandler(EMailFoundInSentItems);
this.Queue.Add(mail.ConversationIndex);
Trace.TraceInformation("Queue ConversationIndex is {0}", mail.ConversationIndex);
}
...
引起事件的对象(Items集合)必须保持活着才能引起事件。你使用的是多点符号,一旦编译器创建的隐式变量超出范围,被垃圾收集,就不会引发事件。
public class SentItemsArchiveQueue
{
Items _items;
public void EnQueue(MailItem mail)
{
_items = mail.SaveSentMessageFolder.Items;
_items.ItemAdd += new ItemsEvents_ItemAddEventHandler(EMailFoundInSentItems);
this.Queue.Add(mail.ConversationIndex);
Trace.TraceInformation("Queue ConversationIndex is {0}", mail.ConversationIndex);
}