Custom outlook plug in not downloading as expected - outlook

I have written a custom code such that when ever an email arrives which has an attachment,it must get downloaded into a shared location, and email arrives daily.
When I open my laptop daily it's working fine if i don't open and if there are continuous mails (with attachments) and it is not getting downloaded for example, when i open my laptop on monday I have 3 mails with attachment (from satu, sunday, monday).
It is not downloading the latest report from monday it is still showing me same report on saturday.
Here is my code..
private void ThisAddIn_Startup(object sender,System.EventArgs e) {
outlookNameSpace=this.Application.GetNamespace("MAPI");
inbox=outlookNameSpace.GetDefaultFolder(Microsoft.Office.Interop.Outlook.OlDefaultFolders.olFolderInbox);
items=inbox.Items;
items.ItemAdd +=new Outlook.ItemsEvents_ItemAddEventHandler(items_ItemAdd);
}
private void items_ItemAdd(object Item) {
Outlook.Items inboxitems;
const string destinationDirectory=#"\\Service Now\";
Outlook.MailItem newEmail=null;
inboxitems=inbox.Items.Restrict("[Unread] = true");
try {
foreach (object collectionItem in inboxitems) {
newEmail=collectionItem as Outlook.MailItem;
if (newEmail !=null) {
if (newEmail.Attachments.Count > 0) {
for (int i=1; i <= newEmail.Attachments.Count; i++) {
if (newEmail.Attachments[i].FileName.Contains("Logic")) {
// String Des= destinationDirectory.Remove(0, 1);
newEmail.Attachments[i].SaveAsFile(destinationDirectory + newEmail.Attachments[i].FileName);
// MessageBox.Show("Hurry");
}
}
}
}
}
}catch (System.Exception ex) {
MessageBox.Show(""+ex);
}
}

Did you try to debug the code?
I see the following conditions in the code:
inboxitems= inbox.Items.Restrict("[Unread] = true");
and
if (newEmail.Attachments[i].FileName.Contains( "Logic"))
Make sure that emails corresponds to the conditions shown above.
Be aware, the ItemAdd event of the Items class is not fired when a large number of items are added to the folder at once (more than 16).
P.S. Try to check out the MarkForDownload property of Outlook items - an OlRemoteStatus value that determines the status of an item once it is received by a remote user.

Related

Outlook-Redemption - RDOFolder.Items ItemAdd Event not triggered regular with Exchange in Online-Mode

System-Environment:
Windows 10 Pro - Version: 1909 - OS System Build: 18363.752
Microsoft Outlook 2019 MSO - Version 1808 - 32-Bit
Microsoft Exchange 2016 15.1 Build (Build 1979.3)
-- Microsoft Exchange is installed on Microsoft Server 2016
Outlook Redemption COM-Library - Version 5.22.0.5498
Issue Summary:
The application sends emails via Outlook using the Outlook-Redemption COM-Library. The class "RedemptionHandler" is our Singleton-Class which interacts with the Outlook-Redemption COM-Library. During the construction of the RedemptionHandler we create a RDOSession with a static class named RedemptionLoader and call Logon() on the RDOSession. The RDOSession is used afterwards in Initialize() to retrieve the Folders for Drafts and mails which are sent.
public static class RedemptionLoader
{
public static RDOSession new_RDOSession()
{
return (RDOSession)NewRedemptionObject(new Guid("29AB7A12-B531-450E-8F7A-EA94C2F3C05F"));
}
}
public class RedemptionHandler
{
private static RedemptionHandler instance = null;
private static readonly object padlock = new object();
private RDOSession _rdoSession;
private RDOFolder _rdoSentFolder;
private RDOFolder _rdoDraftsFolder;
private RDOItems _sentItems = null;
public EventHandler<MailGesendetEventArgs> MailSuccessfullySent;
private RedemptionHandler()
{
_rdoSession = RedemptionLoader.new_RDOSession();
_rdoSession.Logon(null, null, false, null, null, null);
Initialize();
}
public static RedemptionHandler Instance
{
get
{
lock (padlock)
{
if (instance == null)
{
instance = new RedemptionHandler();
}
return instance;
}
}
}
private void Initialize()
{
try
{
if (isInitialized) return;
_rdoSentFolder = _rdoSession.GetDefaultFolder(Redemption.rdoDefaultFolders.olFolderSentMail);
_sentItems = _rdoSentFolder.Items;
_sentItems.ItemAdd += MailSent;
_rdoDraftsFolder = _rdoSession.GetDefaultFolder(Redemption.rdoDefaultFolders.olFolderDrafts);
isInitialized = true;
}
catch
{
//TODO
isInitialized = false;
}
}
}
At this point, we have a working instance from our RedemptionHandler. The COM-Object RDOSession is created and referenced within just as the RDOFolder for Drafts and Sent. We have also registrered an event-listener for the Sent-Folder to recognize new Mails in this folder.
In the next steps we want to send an email and recognize this email if its stored in the sent-folder. We use the RDOMail.Fields - Property to store custom data within the RDOMail-Object.
public RDOMail CreateMail(string recipient, string subject, string body, Guid gdSender, string storagePath)
{
RDOMail newMail = _rdoDraftsFolder.Items.Add(Redemption.rdoItemType.olMailItem);
newMail.Recipients.Add(recipient);
newMail.Recipients.ResolveAll();
newMail.Subject = subject;
newMail.HTMLBody = body;
newMail.BodyFormat = (int)rdoBodyFormat.olFormatHTML;
// Here we want to store an identifier in the RDOMail.Fields
int id = newMail.GetIDsFromNames(PropertyGuid, PropertyGdItemId);
newMail.Fields[id] = Guid.NewGuid().ToString();
return newMail;
}
After the mail creation we want to display the mail to the user because we dont want to send data without letting the user know about it.
public void DisplayMail(RDOMail mail, bool modal = false)
{
mail.Display(modal, null);
}
The Outlook window now comes to front and the user checks the mail and clicks on send.
The Mail is now stored in the Sent-Folder.
The MailSent Event gets invoked by the RDOFolder.Items.Add Listener.
private void MailSent(RDOMail mail)
{
var test = mail.Fields[SenderId];
Console.WriteLine(test);
// test value is correct!
}
Difference between Exchange in Online-Mode and Cache-Mode:
If we use the Exchange with Cache-Mode, everything works fine. Everytime we send an email, the MailSent is triggered and we can read data from the RDOMail.Fields-Property. If we switch to Exchange without Cache, the MailSent Event is triggered only once, when the first mail is sent. All emails afterwars are sent but dont trigger the MailSent-Event. If we delete this line of code, everything works also fine without Cache-Mode.
var test = mail.Fields[SenderId];
This is because we think that reading data from the RDOMail.Fields - Property does something special if the cache-mode from exchange is deactivated.
We need to store custom data within the mails to check if new mails in the sent-folder are created by our application or not.
We highly appreciate help and hints.
I tried to fix this issue without success. I've set-up a new Project without any other code:
public partial class RedemptionTest : Form
{
static RDOSession _rdoSession;
static RDOFolder _rdoSentFolder;
static RDOFolder _rdoDraftsFolder;
static RDOItems _draftItems;
static RDOItems _sentItems;
public RedemptionTest()
{
InitializeComponent();
}
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
_rdoSession = RedemptionLoader.new_RDOSession();
_rdoSession.Logon();
_rdoSentFolder = _rdoSession.GetDefaultFolder(rdoDefaultFolders.olFolderSentMail);
_rdoDraftsFolder = _rdoSession.GetDefaultFolder(rdoDefaultFolders.olFolderDrafts);
_sentItems = _rdoSentFolder.Items;
_draftItems = _rdoDraftsFolder.Items;
_draftItems.ItemAdd += DraftAdd;
_sentItems.ItemAdd += MailSent;
}
private void DraftAdd(RDOMail Item)
{
Console.WriteLine(Item.Subject);
}
private void MailSent(RDOMail Item)
{
Console.WriteLine(Item.Subject);
}
}
The Drafts-Folder Event is fired all the time, the MailSent Event is only fired the first time. I have stored all RDO-Objects in static variables to avoid them from being garbage collected.
The object raising the events (RDOItems) must be alive be able to fire the events. Your code is using multiple dot notation, which means the compiler creates an implicit variable to hold the RDOItems collection. As soon as that variable is released by the Garbage Collector, no events will be fired.
The line
_rdoSentFolder.Items.ItemAdd += MailSent;
must be changed to
RDOItems _sentItems; //global/class variable
..
_sentItems = _rdoSentFolder.Items;
_sentItems .ItemAdd += MailSent;
Have the same issue in Outlook VSTO add-in using Redemption. Happens for both Sent and Inbox folder. The same code works correctly in cached mode but fires events only once in Online mode.
Native Outlook object model Items.ItemAdd works correctly in Online mode for the same folder.
Currently, we were able to do a workaround for this by unsubscribing and resubscribing to event right in the event handler. Like this:
private void SentItems_ItemAdd(RDOMail rdoMail)
{
_sentItems.ItemAdd -= SentItems_ItemAdd;
_sentItems.ItemAdd += SentItems_ItemAdd;
Log.Debug("SentItems.ItemAdd");
SentMailItemAdd?.Invoke(rdoMail);
}

Xamarin Forms - calling rest service from viewmodel of pcl

I created a class that connected to the API to retrieve the required data using httpclient. That file was called in the code behind file of the view and worked perfectly. Than I decided to implement the MVVM approach. As a result, I moved the code that initialized the rest service class to the view-model.
After doing that, i stopped getting the data. To investigate, I stated the the debugging session with the breakpoint placed at the line where i initialize the rest service class. Than i executed that line. By doing that, I found out that a huge android mono exception is thrown and the debugging session if stopped. The app exits the debugging session.
This has happened for the first time since i stated developing my app in Xamarin Forms. I have no idea about why it is breaking like that. Your help will be greatly appreciated.
This is the code that was working properly.
In the view code behind file
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class SubtaskPage : ContentPage
{
protected override void OnAppearing()
{
base.OnAppearing();
PopulateSubtaskData();
}
private async void PopulateSubtaskData()
{
lstSubtasks.IsRefreshing = true;
try
{
RestService rs = new RestService();
SResponse = await rs.GetSubtasksAsync(Convert.ToInt32(Application.Current.Properties["UserId"]));
if (SResponse.Status == 1)
{
lstSubtasks.ItemsSource = SResponse.Subtasks;
}
else
{
await DisplayAlert("Error", SResponse.Message, "Ok");
}
}
catch (Exception E)
{
Debug.WriteLine(#"GetSubtasksAsync -> ERROR {0}", E.Message);
}
lstSubtasks.IsRefreshing = false;
}
}
The rest service class is as follows
This class is in a separate folder named "Services". ip and url have been changed for security reason.
class RestService
{
HttpClient client;
public List<Ticket> Tickets { get; private set; }
string Server1 = "server ip";
string Server2 = "server ip";
public RestService()
{
client = new HttpClient();
client.MaxResponseContentBufferSize = 256000;
}
public async Task<SubtasksResponse> GetSubtasksAsync(int UserId)
{
SubtasksResponse SubtaskResponse = new SubtasksResponse();
string ApiUrl = "URL";
string Url = "";
HttpResponseMessage response;
if (CrossConnectivity.Current.IsConnected)
{
Url = await GetActiveServerAsync();
if (Url != "")
{
var uri = string.Format(Url + ApiUrl, UserId);
try
{
response = await client.GetAsync(uri);
if (response.IsSuccessStatusCode)
{
var content = await response.Content.ReadAsStringAsync();
SubtaskResponse.Subtasks = JsonConvert.DeserializeObject<List<Ticket>>(content);
SubtaskResponse.Status = 1;
}
else
{
SubtaskResponse.Subtasks = null;
SubtaskResponse.Status = 0;
SubtaskResponse.Message = "Attempt to fetch data from server was unsuccessful. Please try again";
}
}
catch (Exception E)
{
SubtaskResponse.Subtasks = null;
SubtaskResponse.Status = 0;
SubtaskResponse.Message = "Error occured while fetching data from the server. Please try again";
}
}
else
{
SubtaskResponse.Subtasks = null;
SubtaskResponse.Status = 0;
SubtaskResponse.Message = "Remote Server Not Responding! Please try again later";
}
}
else
{
SubtaskResponse.Subtasks = null;
SubtaskResponse.Status = 0;
SubtaskResponse.Message = "No Network Connection Found! Please connect to a network and try again";
}
return SubtaskResponse;
}
}
}
This was working fine until I added the view model into the mix.
This is how I am calling the function in the view model.
async Task<SubtasksResponse> PopulateSubtaskList()
{
RestService rs = new RestService();
IsBusy = true;
_subtaskList = await rs.GetSubtasksAsync(Convert.ToInt32(Application.Current.Properties["UserId"]));
IsBusy = false;
return _subtaskList;
}
"RestService rs = new RestService();" this is the line where the code breaks.
Here is the image of the exception that occurs when the code breaks.
Hope you get the clear picture of the situation. Please let me know if additional information is required.
Thanks
Don't do this. If you want to call rest from a mvvm Xamarin Forms app I can advice Refit. All the difficult work is already done for you and abstracted away. With a few lines of code you are up and running.
BTW the error message you are showing probably has nothing to do with your code but is a bug in a recent Xamarin version. See here: https://bugzilla.xamarin.com/show_bug.cgi?id=56787
Found the answer on this page (https://releases.xamarin.com/common-issues-in-the-xamarin-15-2-2-release-being-tracked-by-the-xamarin-team/).
The solution is as follows
Download the missing Mono.Posix file and unzip the archive.
Right-click the Mono.Posix.dll file in Explorer and select Properties.
Check the Digital Signatures tab to ensure the file shows a valid Xamarin Inc. signature.
At the bottom of the General tab, if an Unblock checkbox appears, enable it and select OK. (This checkbox appears depending on how the file was downloaded.)
For Visual Studio 2017, copy the Mono.Posix.dll file into the “Xamarin.VisualStudio” extension directory. For example, for a default installation of the Enterprise edition, copy the file into:
C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\Common7\IDE\Extensions\Xamarin.VisualStudio
For Visual Studio 2015, copy the file into the “Xamarin\Xamarin” extension directory:
C:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\IDE\Extensions\Xamarin\Xamarin\
Quit and restart Visual Studio.
For more detail, visit the link given above.

Stuck for over 2 months getting an outlook addin to work

This is basically a re-post of a previous question, but I've spent over 2 months stuck on this same issue and I haven't made any progress of any kind. Long story short, sometimes it fires and sometimes it doesn't. Sometimes it loads once, sometimes Outlook defaults it to "inactive" and there's nothing I seem to be able to do about it. When it DOES fire, it hangs up when trying to send the first email. So, I have old appointments outside of the date range I'm checking and the messagebox appears for those. When it gets to "new" appointments (within the date range), sometimes it pops up the first messagebox but hangs up trying to send the email. SOmetimes that first "good" messagebox fails to pop up. The last advice I got regarding this issue was to build a log file, but I couldn't figure out how/what good it was going to do me or honestly I wasn't even sure what I was going to need to log, and the gentleman who suggested it never responded to me when I asked. Thank you in advance for your help, this is easily one of the most frustrating things I've ever run in to as a developer.
using System;
using System.Threading;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Linq;
using Outlook = Microsoft.Office.Interop.Outlook;
using Office = Microsoft.Office.Core;
using Microsoft.Office.Interop.Outlook;
using System.Windows.Forms;
namespace OutlookAddIn1
{
public partial class ThisAddIn
{
//Outlook.Inspectors inspectors;
private void ThisAddIn_Startup(object sender, System.EventArgs e)
{
doStuff();
}
private void ThisAddIn_Shutdown(object sender, System.EventArgs e)
{
}
#region VSTO generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InternalStartup()
{
this.Startup += new System.EventHandler(ThisAddIn_Startup);
this.Shutdown += new System.EventHandler(ThisAddIn_Shutdown);
}
//https://msdn.microsoft.com/en-us/library/ms268866.aspx
private void doStuff()
{
Outlook.Application app = new Outlook.Application();
Thread.Sleep(30000); //120 seconds - was 120000
DateTime firstRun = DateTime.Now; //So we can check every 24 hours? Maybe once initially as well.
DateTime lastRun = DateTime.Now;//.AddHours(1); //We're going to compare this to firstRun
bool whileTrue = true;
//int test = 0;
try
{
while (whileTrue)
{
if (whileTrue == true)//(firstRun > lastRun.AddDays(1))
{
Outlook.MAPIFolder calendarFolder = Application.Session.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderCalendar);
Outlook.Items outlookCalendarItems = calendarFolder.Items;
outlookCalendarItems.IncludeRecurrences = true; //was true
List<Outlook.AppointmentItem> lst = new List<Outlook.AppointmentItem>();
foreach (Outlook.AppointmentItem item in outlookCalendarItems)
{
lst.Add(item);
//We can probably just handle logic in here without the second for loop that comes next
}
foreach (Outlook.AppointmentItem x in lst)
{
DateTime startDate = DateTime.Now.AddDays(1);
DateTime endDate = DateTime.Now.AddDays(5);
DateTime apptDate = x.Start;
if (x.Subject.ToLower().Contains("telos"))
{
MessageBox.Show("X: " + x.Start + "XYZ: " + x.Subject);
if (x.Start > startDate && x.Start < endDate)
{
Microsoft.Office.Interop.Outlook.MailItem email = app.CreateItem((OlItemType.olMailItem));
//Outlook.MailItem mail = (Outlook.MailItem)Globals.ThisAddIn.Application.CreateItem(Outlook.OlItemType.olMailItem);
//Outlook.Recipient recipient = Globals.ThisAddIn.Application.Session.CreateRecipient("cindy#soundstewardship.com");
//email.Sender = recipient.AddressEntry;
//Outlook.Recipient recipient = app.Session.CreateRecipient("someone#example.com");
//email.Sender = recipient.AddressEntry;
//email.SentOnBehalfOfName = "someone#example.com";
email.Display(true); //was false
email.Subject = "You have a new appointment";
email.Importance = Outlook.OlImportance.olImportanceLow;
email.To = Application.Session.CurrentUser.AddressEntry.Address; //Current email address.
email.Body = "This email was automatically generated to remind you have an upcoming appointment on: " + x.Start.ToString();
email.Save();
email.Close(OlInspectorClose.olSave);
//((Outlook._MailItem)email).Send();
//email.Send();
//((Outlook._MailItem)mailItem).Send();
}
}
}
lastRun = DateTime.Now;
whileTrue = false;
}
else
{
/*
Outlook.MailItem email = new Outlook.MailItem();
email.Subject = "This is only a test.";
email.To = Application.Session.CurrentUser.AddressEntry.Address; //Current email address.
email.Body = "This is only a test.";
//email.Send();
((Outlook._MailItem)email).Send();
* */
}
}
}
catch (System.Exception e) //Microsoft.Office.Interop.Outlook.Exception e
{
MessageBox.Show(e.InnerException.ToString());
}
finally
{
app.Quit();
}
}
#endregion
}
}
First of all, there is no need to create a new Outlook Application instance in the code. You need to use the Application property of the add-in class.
At startup, I need it to read all appointments whose subject contains a certain string
Don't use the foreach for iterating over all items in the folder. Instead, you need to use the Find/FindNext or Restrict methods of the Items class. You may read more about these methods in the following articles (the sample code is included):
How To: Retrieve Outlook calendar items using Find and FindNext methods
How To: Use Restrict method in Outlook to get calendar items
When you are done I'd recommend using the Resolve or ResolveAll methods of the Recipient(s) class to resolve all recipients against the address book.
Also, like 75% of the time this addin loads directly as "inactive" and doesn't fire.
Microsoft Office applications can disable add-ins that behave unexpectedly. If an application does not load your add-in, the application might have hard disabled or soft disabled your add-in.
Hard disabling can occur when an add-in causes the application to close unexpectedly. It might also occur on your development computer if you stop the debugger while the Startup event handler in your add-in is executing.
Soft disabling can occur when an add-in produces an error that does not cause the application to unexpectedly close. For example, an application might soft disable an add-in if it throws an unhandled exception while the Startup event handler is executing.When you re-enable a soft-disabled add-in, the application immediately attempts to load the add-in. If the problem that initially caused the application to soft disable the add-in has not been fixed, the application will soft disable the add-in again. Read more about that in the How to: Re-enable an Add-in That Has Been Disabled article.
Also Outlook 2013 monitors add-in performance metrics such as add-in startup, shutdown, folder switch, item open, and invoke frequency. Outlook records the elapsed time in milliseconds for each performance monitoring metric. For example, the startup metric measures the time required by each connected add-in during Outlook startup. Outlook then computes the median startup time over 5 successive iterations. If the median startup time exceeds 1000 milliseconds (1 second), then Outlook disables the add-in and displays a notification to the user that an add-in has been disabled. The user has the option of always enabling the add-in, in which case Outlook will not disable the add-in even if the add-in exceeds the 1000 millisecond performance threshold. See Performance criteria for keeping add-ins enabled for more information.
Why would you sleep on the main Outlook thread? And then loop through all items in the folder instead of using Items.Restrict or Items.Find/FindNext?

Outlook custom plugin code not working as expected (Downlaod Email attachment)

I am tring to save attachemnt from a incoming mail in outllok. This is my code. My issue is it downloads correctly when email arrives(when my laptop is open), but this mail is scheduled everyday at 6:00 AM, I open my laptop at 9 and mail is already present and it is not downloading as expected?Do i need to do anything with code?
const string destinationDirectory = #"\\prod_data\Service Now\";
Outlook.MAPIFolder inBox = this.Application.ActiveExplorer()
.Session.GetDefaultFolder(Outlook
.OlDefaultFolders.olFolderInbox);
Outlook.Items inBoxItems = inBox.Items;
Outlook.MailItem newEmail = null;
inBoxItems = inBoxItems.Restrict("[Unread] = true");
try
{
foreach (object collectionItem in inBoxItems)
{
newEmail = collectionItem as Outlook.MailItem;
if (newEmail != null)
{
if (newEmail.Attachments.Count > 0)
{
for (int i = 1; i <= newEmail
.Attachments.Count; i++)
{
if (newEmail.Attachments[i].FileName.Contains( "LogicView Issue Report"))
{
newEmail.Attachments[i].SaveAsFile(destinationDirectory +
newEmail.Attachments[i].FileName);
}
}
}
}
}
}
I'd suggest checking out the MarkForDownload property value. It returns an OlRemoteStatus constant that determines the status of an item once it is received by a remote user. For example:
Sub DownloadItems()
Dim mpfInbox As Outlook.Folder
Dim obj As Object
Dim i As Integer
Set mpfInbox = Application.GetNamespace("MAPI").GetDefaultFolder(olFolderInbox)
'Loop all items in the Inbox folder
For i = 1 To mpfInbox.Items.Count
Set obj = mpfInbox.Items.Item(i)
'Verify if the state of the item is olHeaderOnly
If obj.DownloadState = olHeaderOnly Then
MsgBox ("This item has not been fully downloaded.")
'Mark the item to be downloaded.
obj.MarkForDownload = olMarkedForDownload
End If
Next
End Sub
You can use the Start method of the SyncObject class to begin synchronizing a user's folders using the specified Send\Receive group.
Do not use Application.NewMail event - it fires only when Outlook is running at the time the email is received by the Exchange server.
Use Items.ItemAdd event on the Inbox folder (Namespace.GetDefaultFolder(olFolderInbox)) - it will fire when the email downloaded to the cached store when Outlook synchronizes the Inbox folder (assuming you are using cached mode). If Outlook is online, no events will fire. In that case, you can use Items.Find/FindNext to process all unread messages ([Unread] = 'true').
//declare on the global/class level to make sure
//it does not get garbage collected
private Outlook.Items inBoxItems;
...
//in your addin startup code
inBoxItems = inBox.Items
inBoxItems.ItemAdd += inboxItemsItemAdd;
...
private void inboxItemsItemAdd(object item)
{
...
}

Hooking to Send/Receive Sync event of Outlook Contacts

How can I attach an event handler for SendAndReceive event of Contact folders/Contact Items in Outlook 2007 using VSTO AddIn? I tried using:
Application.ActiveExplorer().SyncObjects.ForEach
{
SyncObject.SyncEnd += \\Do something
}
But it is not working.
I tried
Application.ActiveExplorer().SyncObjects.AppFolders.SyncEnd += \\EventHandler
This hooks on to send/receive of all default folders..
Actually my need was a bit different but may be the same:
I wanted to be notified of the changes of a folder (appointments in my case) after a send/receive.
My first thought (and I think you are on the same track) was to check for a send/receive event and maybe get some collection of items out of it or something similar, but no such thing is available. (as is also explained in this forum post)
My second path came from the following article: I can register to the Item_Add and Item_Change (and even Item_Removed) event of a folder (whom are also triggered by the changes done by a send receive):
Some code:
// Get the folder calendar folder and subscribe to the events.
private void ThisAddIn_Startup(object sender, System.EventArgs e)
{
Application.Session.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderCalendar).Items.ItemAdd += new Microsoft.Office.Interop.Outlook.ItemsEvents_ItemAddEventHandler(Items_ItemAdd);
Application.Session.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderCalendar).Items.ItemChange += new Microsoft.Office.Interop.Outlook.ItemsEvents_ItemChangeEventHandler(Items_ItemChange);
}
// Do something with it.
void Items_ItemAdd(object Item)
{
logItem(Item, "Add");
}
void logItem(object Item, string Action)
{
Outlook.AppointmentItem item = Item as Outlook.AppointmentItem;
File.AppendAllText(#"e:\log.txt", string.Format("Item {0}: {1}", Action, Item));
if (item != null)
{
File.AppendAllText(#"e:\log.txt", " - Appointment: " + item.Subject);
}
}
You can hook up the mail send/receive event and then check that the mail type is a ContactItem. Here is an example of the Send event.
// hook up the event
this.Application.ItemSend += ThisApplication_SentMail;
then in your event handler you check the mail item type;
internal void ThisApplication_SentMail(object item, ref bool cancel)
{
Outlook.ContactItem contactItem = item as Outlook.ContactItem;
// mail message is not a ContactItem, so exit.
if (contactItem == null) return;
// do whatever you need to here
}
In my case, I need to trigger an event after a new email is received & after email sync so that I get a new email, or else I will not receive a new email attachment.
Below my solution may help you.
private void ThisAddIn_Startup(object sender, System.EventArgs e)
{
this.Application.NewMail += Application_NewMail;
}
private void Application_NewMail()
{
_currentExplorer = Application.ActiveExplorer();
_currentExplorer.Session.SyncObjects[1].SyncEnd += AppFolders_SyncEnd;
_currentExplorer.Session.SyncObjects[1].Start();
}
private void AppFolders_SyncEnd()
{
//Your enter code here
}

Resources