0
votes

I'm trying to send emails from a .NET application using Outlook Object Model.

My application displays the Outlook message window so the user can see what we're sending and edit it first. When the user hits the Send button, the Outlook window closes, and the message gets sent. This works perfectly as long as the Outlook application is already running.

If the Outlook application isn't already running, the message gets stuck in the Outbox, and will not send until I start Outlook. When I start Outlook, I can see the message sitting in the Outbox folder for a few seconds, then it gets sent. I need to show the New Message form to Outlook user to select the recipient(s) and possibly edit the message before sending.

Note: I know that this question was already asked here Email sent with Outlook Object Model stays in Outbox until I start Outlook and the solution exists, but it is not provided (only the small hint is provided) and unfortunately I cannot ask for clarification / code example because I have not enough "reputation". I tried to write my own implementation of the hint provided, but the SyncEnd event is fired only when Outlook is already open (just to remind, the question is about the case then Outlook is closed). My code below. What is wrong?

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();
  }
}
1
Where and when do you run the code? Is it a web server or service?Eugene Astafiev
@EugeneAstafiev Thank you for the answer. It is neither web server nor service (as I understood, it's not possible to use OOM from the service - isn't it correct). I'm calling this class from the desktop application (Crystal Reports viewer) and want to send report through Outlook mail.Yumb
Try to get an instance of the Explorer class and hold that reference until you are done.Eugene Astafiev
@EugeneAstafiev 1.Explorer or Inspector (as it was recommended in another post)? Can you please provide or refer the example? 2."Try to get an instance of the Explorer class and hold that reference" - should it be to create a (static?) class variable and assign it? Thank you again!Yumb

1 Answers

0
votes

the SyncEnd event is fired only when Outlook is already open

That is not true. The SyncObjects collection contains all Send\Receive groups. You need to iterate over all objects in the collection and call the Start method, for example:

  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