如果 Outlook 关闭,则从 C# OOM 发送的电子邮件将保留在发件箱中,直到下一次 Outlook 启动

Posted

技术标签:

【中文标题】如果 Outlook 关闭,则从 C# OOM 发送的电子邮件将保留在发件箱中,直到下一次 Outlook 启动【英文标题】:Email sent from C# OOM stays in Outbox if Outlook is closed until next Outlook start 【发布时间】:2018-05-31 18:00:38 【问题描述】:

我正在尝试使用 Outlook 对象模型从 .NET 应用程序发送电子邮件。

我的应用程序显示 Outlook 消息窗口,因此用户可以看到我们发送的内容并首先对其进行编辑。当用户点击“发送”按钮时,Outlook 窗口将关闭,并发送消息。只要 Outlook 应用程序已经在运行,它就可以完美运行。

如果 Outlook 应用程序尚未运行,则邮件会卡在发件箱中,并且在我启动 Outlook 之前不会发送。当我启动 Outlook 时,我可以看到邮件在发件箱文件夹中停留了几秒钟,然后它就被发送了。 我需要向 Outlook 用户显示新邮件表单以选择收件人并可能在发送前编辑邮件。

注意:我知道这个问题已经在这里问过Email sent with Outlook Object Model stays in Outbox until I start Outlook 并且存在解决方案,但没有提供(仅提供小提示),不幸的是我无法要求澄清/代码示例,因为我没有足够的“声誉”。 我尝试编写自己的所提供提示的实现,但 在 Outlook 已打开时触发 SyncEnd 事件(提醒一下,问题是关于此案的情况,然后 Outlook 已关闭)。 我的代码如下。怎么了?

using Microsoft.Office.Interop.Outlook;
using OutlookApp = Microsoft.Office.Interop.Outlook.Application;
class Mailer

  AutoResetEvent mailSentEvent = new AutoResetEvent(false);

  public void CreateMail()
  
    OutlookApp outlookApp = null;
    MailItem mailItem = null;
    try
    
      outlookApp = new OutlookApp();
      mailItem = outlookApp.CreateItem(OlItemType.olMailItem);

      mailItem.Subject = "Test Message";
      mailItem.Body = "This is the message.";
      string reportPath = @"C:\temp\aaaaa.pdf";
      mailItem.Attachments.Add(reportPath);
      mailItem.Display(true);

      StartSync(outlookApp);
      bool result = mailSentEvent.WaitOne();
     
    catch (System.Exception)
    
        throw;
    
    finally
    
      if (mailItem != null) Marshal.ReleaseComObject(mailItem);
      if (outlookApp != null) Marshal.ReleaseComObject(outlookApp);
    
  

  private static SyncObject _syncObject = null;

  private void StartSync(OutlookApp outlookApp)
  
    var nameSpace = outlookApp.GetNamespace("MAPI");
    _syncObject = nameSpace.SyncObjects[1];
    _syncObject.SyncEnd += new Microsoft.Office.Interop.Outlook.SyncObjectEvents_SyncEndEventHandler(OnSyncEnd);
    _syncObject.Start();


  private void OnSyncEnd()
  
    mailSentEvent.Set();
  

【问题讨论】:

您在何时何地运行代码?它是网络服务器还是服务? @EugeneAstafiev 谢谢你的回答。它既不是 Web 服务器也不是服务(据我了解,不可能从服务中使用 OOM - 不是吗)。我正在从桌面应用程序(Crystal Reports 查看器)调用此类,并希望通过 Outlook 邮件发送报告。 尝试获取Explorer 类的实例并保留该引用直到完成。 @EugeneAstafiev 1.Explorer 还是 Inspector(正如在另一篇文章中推荐的那样)?您能否提供或参考示例? 2.“尝试获取 Explorer 类的实例并保存该引用” - 是否应该创建一个(静态?)类变量并分配它?再次感谢您! 【参考方案1】:

仅当 Outlook 已打开时才会触发 SyncEnd 事件

那不是真的。 SyncObjects 集合包含所有发送\接收组。您需要遍历集合中的所有对象并调用Start 方法,例如:

  Set sycs = nsp.SyncObjects 
  For i = 1 To sycs.Count 
    Set syc = sycs.Item(i) 
    strPrompt = MsgBox("Do you wish to synchronize " &; syc.Name &;"?", vbYesNo) 
    If strPrompt = vbYes Then 
      syc.Start 
    End If 
  Next 

【讨论】:

感谢您的回答。 1.我觉得这种行为是因为 SyncEnd 事件仅在 Outlook 已打开时才会触发。如果我在 OnSyncEnd 事件处理程序中设置断点(请参阅上面的代码),则仅当 Outlook 先前打开时,流程才会停止。如果它已关闭,则单击“新邮件”窗口上的“发送”按钮后,该窗口将关闭,我可以等待一段时间,但不会调用 OnSyncEnd 事件处理程序。 2.如果我启动多个同步对象(我找到的所有),我怎样才能捕捉到 SyncEnd 事件?将相同的处理程序附加到每个处理程序?谢谢! 是的,您需要为每个 SyncObject 实例附加一个事件处理程序。

以上是关于如果 Outlook 关闭,则从 C# OOM 发送的电子邮件将保留在发件箱中,直到下一次 Outlook 启动的主要内容,如果未能解决你的问题,请参考以下文章

Outlook 加载项教程? [关闭]

outlook如何周期性定时发邮件

outlook2007写邮件无法用鼠标在行中插入光标

如果用户关闭浏览器,则从数据库中删除数据[重复]

Excel如何录制宏通过outlook发邮件,每天都有要发一样的邮件,可能就是数据有些不同?

用python调用outlook发邮件的问题