How To: Perform Send/Receive in Outlook programmatically
Today I will continue my series of “How To” articles explaining the basics of Outlook development.
The NameSpace class in Outlook provides a programmatic equivalent of the “Send/Receive All” command (see Tools | Send/Receive in Outlook 2007 or below) – SendAndReceive method. This method allows you to initiate an immediate send/receive of e-mail messages submitted in the current session. It accepts a Boolean value indicating whether a progress bar should be displayed or not. However, if you don’t specify any value, the default behavior according to the user settings is expected.
The following code works like a charm in Outlook 2007 and 2010:
C#:
private void DirectSendAndReceiveCall(object sender, IRibbonControl control, bool pressed) { Outlook.NameSpace ns = OutlookApp.GetNamespace("MAPI"); ns.SendAndReceive(false); if (ns != null) Marshal.ReleaseComObject(ns); }
VB.NET:
Private Sub DirectSendAndReceiveCall() Dim ns As Outlook.NameSpace = OutlookApp.GetNamespace("MAPI") ns.SendAndReceive(False) If Not IsNothing(ns) Then Marshal.ReleaseComObject(ns) End Sub
However, what should we do if we want to use version-neutral interops? The answer is simple: the late-binding technology available in the .NET framework does the trick ;-)
C#:
private void SendReceiveUsingLateBinding() { Outlook.NameSpace ns = OutlookApp.GetNamespace("MAPI"); ns.GetType().InvokeMember("SendAndReceive", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.InvokeMethod | System.Reflection.BindingFlags.Public, null, ns, null); if (ns != null) Marshal.ReleaseComObject(ns); }
VB.NET:
Private Sub SendReceiveUsingLateBinding() Dim ns As Outlook.NameSpace = OutlookApp.GetNamespace("MAPI") ns.GetType().InvokeMember("SendAndReceive", _ System.Reflection.BindingFlags.Instance Or _ System.Reflection.BindingFlags.InvokeMethod Or _ System.Reflection.BindingFlags.Public, _ Nothing, ns, Nothing) If Not IsNothing(ns) Then Marshal.ReleaseComObject(ns) End Sub
But how can we call the SendAndReceive method in case of Outlook 2000, 2002 and 2003? The following code illustrates the way we can use to bridge the gap!
C#:
private void ExecuteSendReceiveButton() { Outlook.Explorer explorer = null; Office.CommandBars cmdBars = null; Office.CommandBarButton btnSendAndReceive = null; try { explorer = OutlookApp.ActiveExplorer(); cmdBars = explorer.CommandBars; // 5488 should be used for Outlook 2000, 2002 btnSendAndReceive = cmdBars.FindControl(Office.MsoControlType.msoControlButton, 7095) as Office.CommandBarButton; if (btnSendAndReceive != null) { btnSendAndReceive.Execute(); } } catch (Exception ex) { System.Windows.Forms.MessageBox.Show(ex.Message); } finally { if (btnSendAndReceive != null) Marshal.ReleaseComObject(btnSendAndReceive); if (cmdBars != null) Marshal.ReleaseComObject(cmdBars); if (explorer != null) Marshal.ReleaseComObject(explorer); } }
VB.NET:
Private Sub ExecuteSendReceiveButton() Dim explorer As Outlook.Explorer = Nothing Dim cmdBars As Office.CommandBars = Nothing Dim btnSendAndReceive As Office.CommandBarButton = Nothing Try explorer = OutlookApp.ActiveExplorer() cmdBars = explorer.CommandBars // 5488 should be used for Outlook 2000, 2002 btnSendAndReceive = cmdBars.FindControl(Office.MsoControlType.msoControlButton, 7095) If Not IsNothing(btnSendAndReceive) Then btnSendAndReceive.Execute() End If Catch ex As Exception System.Windows.Forms.MessageBox.Show(ex.Message) Finally If Not IsNothing(btnSendAndReceive) Then Marshal.ReleaseComObject(btnSendAndReceive) If Not IsNothing(cmdBars) Then Marshal.ReleaseComObject(cmdBars) If Not IsNothing(explorer) Then Marshal.ReleaseComObject(explorer) End Try End Sub
As you see, I used the Execute method of the CommandBarButton class in Outlook to simulate the SendAndReceive method. You can use the BuiltInControlScanner utility to find the controls’ IDs (it is 7095 and 5488 in our case).
However, there is one more way to imitate the “Send/Receive” button – use the SyncObjects classes. The SyncObjects class represents the Send/Receive groups for the end-user. Each group is represented by the SyncObject class in the Outlook Object Model. Currently we are interested in the Start method which allows implementing the required functionality (synchronize Send/Receive groups). This method doesn’t accept any parameters and doesn’t return any value.
C#:
private void AlternativeWay() { Outlook.NameSpace ns = null; Outlook.SyncObjects syncObjs = null; Outlook.SyncObject syncObj = null; try { ns = OutlookApp.GetNamespace("MAPI"); syncObjs = ns.SyncObjects; for (int i = 1; syncObjs.Count >= i; i++) { syncObj = syncObjs.Item(i); if (syncObj != null) { syncObj.Start(); Marshal.ReleaseComObject(syncObj); } } } catch (Exception ex) { System.Windows.Forms.MessageBox.Show(ex.Message); } finally { if (syncObjs != null) Marshal.ReleaseComObject(syncObjs); if (ns != null) Marshal.ReleaseComObject(ns); } }
VB.NET:
Public Sub AlternativeWay() Dim ns As Outlook.NameSpace = Nothing Dim syncObjs As Outlook.SyncObjects = Nothing Dim syncObj As Outlook.SyncObject = Nothing Try ns = OutlookApp.GetNamespace("MAPI") syncObjs = ns.SyncObjects For i As Integer = 1 To syncObjs.Count syncObj = syncObjs.Item(i) If Not IsNothing(syncObj) Then syncObj.Start() Marshal.ReleaseComObject(syncObj) End If Next Catch ex As Exception System.Windows.Forms.MessageBox.Show(ex.Message) Finally If Not IsNothing(syncObjs) Then Marshal.ReleaseComObject(syncObjs) If Not IsNothing(ns) Then Marshal.ReleaseComObject(ns) End Try End Sub
In this case there is one side effect: the Send/Receive progress window will not be shown to the user. The synchronization is performed silently.
There are four ways to initiate the send/receive process in Outlook. Which one to use depends on your needs!
22 Comments
kindly update our express outlook to assist us to send/receive messeges
Hi Makopung,
Thank you for visiting our technical blog.
Note, the article describes methods and properties from Microsoft Office Outlook. Unfortunately Outlook Express doesn’t provide such methods and properties.
Hello Eugene,
a very nice article!! i have been trying along similar lines to programmatically read emails from outlook 2007 using c#. i am able to conenct to outlook using follwoing code:
app = new Outlook.Application();
ns = app.GetNamespace(“MAPI”);
ns.Logon(Settings.Default.OutlookProfile, Settings.Default.password, false, false);
string criteria = “[Subject] = ‘with some specific subject'”;
inboxFolder = ns.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderInbox);
Outlook.Items oItems = inboxFolder.Items;
Outlook.Items filteredItems = oItems.Restrict(criteria);
Console.WriteLine(“total NJ emails:” + filteredItems.Count);
for (int i = 1; i <= filteredItems.Count; i++)
{
Outlook.MailItem oMailItem = (Outlook.MailItem)filteredItems[i];
mailBody = oMailItem.Body;
//some operations to fetch info from email body
}
i am still trying to figure it out, how to sync or update outlook with latest emails which are residing in exchange server.
Thanks,
Jaideep
Hi Jaideep,
Did you try to use SyncObjects class from the Outlook Object Model for this task?
Hello Eugene, Thanks!!my requirement is to fetch emails from a specific sender and parse its body. we are thinking of to create it as c# console application which would run as a scheduler.
does SyncObjects requires the use of Add-in project.is it possible to use SyncObjects using Microsoft.Office.Interop.Outlook assembly?
please suggest.
Thanks,
Jaideep
Hi Jaideep,
Yes, it is. The SyncObjects class comes from the Outlook Object Model and doesn’t depend on the Add-in Express classes. So, you can use it on your own.
Hi Eugene,
i am getting following error while compiling private void AlternativeWay() method:
‘Microsoft.Office.Interop.Outlook.SyncObjects’ does not contain a definition for ‘Item’ and no extension method ‘Item’ accepting a first argument of type ‘Microsoft.Office.Interop.Outlook.SyncObjects’ could be found (are you missing a using directive or an assembly reference?)
syncObj = syncObjs.Item(i);
i have added reference to Microsoft Outlook 12.0 Outlook Library reference from com components tab.
Hi Jaideep,
I regret to tell you but we provide technical support only for registered customers with active subscriptions. Which of our product do you use?
Hi Eugene,
we are not using any of your porduct, though we chanceed upon your blog while investigating above problem. thank you very much for your support to provide us the direction.
You are welcome, Jaideep!
An absolutely brilliant article Eugene. Has completely solved the “emails sitting in drafts folder” problem when using Redemption.
Thanks
Hi Patrick,
Thank you for the kind words ;-)
I have a c# web application/web form which uses interop.outlook to send email and create tasks (just like you described). it works perfectly on my local machine but not when i publish to the server.
i want it to use it such that that emails sent appear in the sender’s ‘sent box’. Is this concept just not allowed in a server environment? (The users internally here do have outlook opened so they are signed in.) Here is the snippet::
using Outlook = Microsoft.Office.Interop.Outlook;
OutLookMail sendRequestStatusUpdateViaEmail = new OutLookMail();
public class OutLookMail
{
private Outlook.Application oApp;
private Outlook._NameSpace oNameSpace;
private Outlook.MAPIFolder oSentboxFolder;
Outlook._MailItem oMailItem = (Outlook._MailItem)oApp.CreateItem(Outlook.OlItemType.olMailItem);
oMailItem.SaveSentMessageFolder = oSentboxFolder;
//…
oMailItem.To = toValue;
oMailItem.CC = ccValue;
oMailItem.BCC = bccValue;
oMailItem.HTMLBody = sHtml;
oMailItem.Send();
}
Hi Bill,
Where and how do you get the oApp object?
Please take a look at the similar Opening Outlook with new e-mail from Asp.net blog entry for more information on this.
Hi Eugene,
I want to catch send/Receive event when outlook is done synchronising emails, so I can execute my add-in after that.
Is there anyway I can do that in c#?
your help will be much appreciated.
thanks
Hello Sohaib,
You need to intercept SyncStart, SyncEnd, and SyncProgress events; see https://msdn.microsoft.com/en-us/library/office/ff862356.aspx, https://msdn.microsoft.com/en-us/library/office/ff866270.aspx and https://msdn.microsoft.com/en-us/library/office/ff865672.aspx. Note that in Add-in Express these events are disabled by default due to the issue we described at https://social.msdn.microsoft.com/Forums/office/en-US/7a20664c-7650-4d61-9d5f-13f1d929a8cd/outlook-2013-automatic-sendreceive-doesnt-work-with-the-sample-addin-below?forum=outlookdev. To enable these events, see the HandleEvents property of the Outlook Events component (ADXOutlookAppEvents).
Hi
Anybody can help me regarding my below query, thanks in advance.
I am using outlook 2010, where i want to execute a macro only when user press Send/Receive button in outlook 2010.
There is no issue of macro i wrote in VB. I only want to execute macro before receiving emails, kindly help me if it is possible.
Thank you
Hello Amq,
See https://msdn.microsoft.com/en-us/vba/outlook-vba/articles/syncobject-syncstart-event-outlook.
If you use Add-in Express, see the SyncStart event of the ADXOutlookAppEvents component. Note that by default the component doesn’t trigger this event to prevent your users from running in the issue we described at https://social.msdn.microsoft.com/Forums/office/en-US/7a20664c-7650-4d61-9d5f-13f1d929a8cd/outlook-2013-automatic-sendreceive-doesnt-work-with-the-sample-addin-below?forum=outlookdev. To let the component intercept this event, see the HandleEvents property the component provides.
I want to add a macro code from the text file to the outlook 2010 using c#. I have done a search for it but didn’t get any solution. Kindly help me on an urgent basis.
Thank you
Hello Vanaja,
Please check https://stackoverflow.com/questions/34837006/excel-vba-add-code-to-sheet-module-programmatically and https://stackoverflow.com/questions/12221837/programmatically-adding-references-to-outlook-2010-in-vba. These show how to do this using VBA. In your C# code, you need to add a reference to Microsoft Visual Basic for Applications Extensibility 5.3 library and use objects/methods shown in these pages.
This path only works if the ‘Trust access to the VBA project object model’ check box in Trust Center | Macro Settings is selected.
Hello,
When defining SEND & RECEIVE groups, there is a check mark called “Include the selected account in this group”. If this option is not selected for any specific account, that account is ignored during the send and receive process…. Is there a way to set up this option programmatically from Excel? I want to be able to Check and Uncheck this option from VB.
Thank you!
Hello Luidgi,
The Outlook object model provides no way to achieve this. But have a look at https://docs.microsoft.com/en-us/office/vba/api/outlook.folder.inappfoldersyncobject.