Outlook ContactItem DeleteEvent - c#

Currently I´m writing a sync tool for GMail contacts and outlook, but there is a little problem:
I need an event in my addin when the user deletes a contact, otherwise the sync tool would detect the missing contact on the outlook side and the tool will create the contact from the google side.
I´m accessing all Outlook contacts from the default folder with this code:
Microsoft.Office.Interop.Outlook.NameSpace mapiNamespace = GetCurrentNamespace();
Microsoft.Office.Interop.Outlook.MAPIFolder contacts = mapiNamespace.GetDefaultFolder(Microsoft.Office.Interop.Outlook.OlDefaultFolders.olFolderContacts);
IList<Microsoft.Office.Interop.Outlook.ContactItem> items = new List<Microsoft.Office.Interop.Outlook.ContactItem>();
foreach (var contact in contacts.Items)
{
items.Add(contact as Microsoft.Office.Interop.Outlook.ContactItem);
}
return items;
Edit 1:
I already tried to subscribe to an BeforeDelete Event as John Saunders commented, but with no success. When I try to delete a contact in Outlook the event wont get fired.
Code:
Microsoft.Office.Interop.Outlook.NameSpace mapiNamespace = GetCurrentNamespace();
_contactMapiFolder = mapiNamespace.GetDefaultFolder(Microsoft.Office.Interop.Outlook.OlDefaultFolders.olFolderContacts);
//IList<Microsoft.Office.Interop.Outlook.ContactItem> items = new List<Microsoft.Office.Interop.Outlook.ContactItem>();
this._contacts = new List<Microsoft.Office.Interop.Outlook.ContactItem>();
foreach (var contact in _contactMapiFolder.Items)
{
Outlook.ContactItem item = contact as Microsoft.Office.Interop.Outlook.ContactItem;
item.BeforeDelete += ItemOnBeforeDelete;
this._contacts.Add(item);
}
return this._contacts;
Can anybody provide me an example what events are available for such mapi (especially contact folders) folders are available and how they are working?

It is a really bad idea to set up an event sink on each and every item in a folder.
When Items.ItemRemove even fires, there is no way for you to figure out which item was deleted. You have no choice but to compare the current collection with what you have on the server or in some kind of local cache.
You can try to use Redemption (I am its author) and its RDOItems.ItemRemove event - it passes the value of the PR_INSTANCE_KEY MAPI property from the folder contents table. If you cache the values of the PR_INSTANCE_KEY property for all items ahead of time (you can use RDOITems.MAPITable.ExecSQL for that), you can figure out which item was deleted without looping through all items in the folder.

Related

Outlook - How to access the auto-complete address list

I want to be able to access the auto-complete address list that appears when typing into either the TO,CC or BCC lines within an email. I wish to be able to extract this data similarly to how I access other address lists within Outlook.
Would anyone be able to confirm if this is possible and if so how I could go about doing it.
This is currently how I'm extracting email addresses various other address lists.
foreach (Outlook.AddressEntry item in addressList.AddressEntries)
{
using (item.ComDisposable())
{
switch (item.AddressEntryUserType)
{
case Outlook.OlAddressEntryUserType.olExchangeUserAddressEntry:
case Outlook.OlAddressEntryUserType.olExchangeRemoteUserAddressEntry:
var exUser = item.GetExchangeUser();
Debug.WriteLine(exUser.PrimarySmtpAddress, "_GetOutlookContacts");
yield return new EGContact(exUser.Name, exUser.PrimarySmtpAddress, item.ID);
break;
case Outlook.OlAddressEntryUserType.olOutlookContactAddressEntry:
var contact = item.GetContact();
yield return new EGContact(contact.FullName, contact.Email1Address, item.ID);
break;
case Outlook.OlAddressEntryUserType.olExchangeDistributionListAddressEntry:
break;
default:
break;
}
}
}
Autocomplete stream is stored as a hidden (associated) message with the message class of "IPM.Configuration.Autocomplete" in the Inbox folder. You can see the data in OutlookSpy (I am its author): go to the Inbox folder, click IMAPIFolder button on the OutlookSpy ribbon, go to the "Associated Contents" tab, locate a message with PR_MESSAGE_CLASS == "IPM.Configuration.Autocomplete", select the PR_ROAMING_BINARYSTREAM property to see its contents.
You can open that message using the Outlook Object Model (MAPIFolder.GetStorage("IPM.Configuration.Autocomplete", OlStorageIdentifierType.olIdentifyByMessageClass), read the property using PropertyAccessor.GetProperty, then parse it. Note that large autocomplete streams cannot be opened using PropertyAccessor.
If using Redemption an option (I am also its author), it exposes autocomplete as the RDONicknames collection:
set Session = CreateObject("Redemption.RDOSession")
Session.MAPIOBJECT = Application.Session.MAPIOBJECT
set Nicknames = Session.GetNicknames
for each NickName in NickNames
Debug.Print NickName.Name & " - " & NickName.SmtpAddress
next
In an earlier version of Outlook, this information was stored in local .NK2 files. In Outlook 2010 and up, this information is stored in your mailbox (AutoComplete Stream). See Clearing AutoComplete and other Recipient Caches for more information.
You can use the Recipients collection (see the corresponding property of the MailItem class) for accessing the data entered to the To, Cc or Bcc fields.

Outlook email to pdf security prompt

I have a task which i need to create a program that converts outlook email to pdf.
this is my code
Microsoft.Office.Interop.Outlook.Application app = new Microsoft.Office.Interop.Outlook.Application();
NameSpace outlookNs = app.GetNamespace("MAPI");
MAPIFolder rootFolder = outlookNs.Stores["Blah"].GetRootFolder();
List<MailItem> mailItems = new List<MailItem>();
Folders subFolders = rootFolder.Folders;
foreach (Folder folder in subFolders)
{
if (folder.Name == "Inbox")
{
Items items = folder.Items;
foreach (object item in items)
{
if (item is MailItem)
{
MailItem mailItem = item as MailItem;
string fileName = System.IO.Path.Combine(System.IO.Path.GetTempPath(), "New folder", mailItem.EntryID + mailItem.SenderName.Replace("/", "") + ".msg");
mailItem.SaveAs(fileName, Microsoft.Office.Interop.Outlook.OlSaveAsType.olMSG);
}
}
}
}
the code is working but the outlook contains thousands of email. The outlook prompt a message every 10 minutes similar to the screenshot below
is there a way to avoid getting the message? Programatically or a setting will do?
Basically, it's not related to the programming instead of it's related the outlook security settings.
For every version of outlook you can find the settings for this pop-up just follow the instruction on this blog.
You can do a setting in your out look.
Mine is outlook 2013.
File->options : a window opens
In the window select Trust Center
You can see a button Trust center Settings
Options in window changes. Select Programmatic access
UnCheck the radio button Never warn me about suspicious activity (not recommended)
Through program, you can change below registry settings:
Go to "HKEY_CURRENT_USER\Software\Policies\Microsoft\Office\15.0\outlook\security"
Change below settings programatically:
PromptSimpleMAPISend -- 2
PromptSimpleMAPINameResolve -- 2
PromptSimpleMAPIOpenMessage -- 2
By default when outlook is installed, the above values comes with zero value. What I do in my program is, I turn them to "2" programatically just before sending the email and turn them back to zero later point of time.

C# Outlook AddIn - Determine EWS Item ID for the selected Email

Is it possible to determine the Exchange Server ItemID for a MailItem (the selected Item in the active explorer)? The solution I am working on has an Outlook AddIn component and another component that accesses mail items through EWS.
I have code similar to the below in my Outlook addin:
Outlook.Explorer ActiveExplorer = Globals.ThisAddIn.Application.ActiveExplorer();
object selectedItem = ActiveExplorer.Selection[1];
Outlook.MailItem selectedEmail = selectedItem as Outlook.MailItem;
In this way I can access certain properties of the email but it is important to the workings of the overall solution that the property values are exactly the same as those returned by EWS. For example, if the property returned a time, it would be important that the time matched down to the millisecond.
If I had the ItemID I could bind to and work with the Item (from within the addin) using something like the below.
Item myItem = Item.Bind(MyExchangeService, MyItemID);
On a whim I have tried binding to MailItem.EntryID but I got a malformed ID error (which didn't surprise me). I have been trying to determine if the Exchange ID was available through MailItem.PropertyAccessor.GetProperty but I am not really familiar with accessing properties in this way and haven't had any luck so far.
Thoughts?
I came across the following Stack Overflow post which didn't exactly answer my question but changed my focus to converting the EntryID into the EWS ID rather than finding the EWS ID.
Exchange ItemID differs from GlobalAppointmentID for Outlook AddIn
With this new angle I was able to find the following site which directly addressed my issue.
https://bernhardelbl.wordpress.com/2013/04/15/converting-entryid-to-ewsid-using-exchange-web-services-ews/
I have posted the code here in full in case the link gets broken.
string ConvertHexEntryIdToEwsId(ExchangeService esb, string sID, string strSMTPAdd)
{
AlternateId objAltID = new AlternateId();
objAltID.Format = IdFormat.HexEntryId;
objAltID.Mailbox = strSMTPAdd;
objAltID.UniqueId = sID;
AlternateIdBase objAltIDBase = esb.ConvertId(objAltID, IdFormat.EwsId);
AlternateId objAltIDResp = (AlternateId)objAltIDBase;
return objAltIDResp.UniqueId;
}

Outlook Interop ClearSelection Method

I am having difficulties with Interop in a WPF application.
What I actually want to do is drag and drop an Outlook file into my application and extract the attachments and store them. Apart from that I want to read the subject and search for a 4-digit-number which will then be the name of the folder the attachments are to be stored to.
I have been searching the web for solutions that don't use Interop, but I wasn't able to find anything that worked for me.
So I thought 'let's give it a shot' and it sounded pretty simple, because I found so many examples that followed this pattern:
if (e.Data.GetDataPresent("FileGroupDescriptor"))
{
Microsoft.Office.Interop.Outlook.Application app = new Microsoft.Office.Interop.Outlook.Application();
Microsoft.Office.Interop.Outlook.Selection selection = app.ActiveExplorer().Selection;
foreach (object mi in selection)
{
Microsoft.Office.Interop.Outlook.MailItem mailItem = (Microsoft.Office.Interop.Outlook.MailItem)mi;
string subject = "Untitled";
if (!string.IsNullOrEmpty(mailItem.Subject))
{
subject = mailItem.Subject;
MessageBox.Show(subject);
}
}
}
This works, but I have one problem: the selection keeps on growing. I tried the methods RemoveFromSelection and ClearSelection, but they don't work. Everytime I drag a new Outlook item to the surface it keeps displaying all the previous items as well.
Can anybody help me? I'm at a complete loss
Do you handle the Drag event in your application?
If so, try to call the following code in the event handler:
e.Data.GetData(“RenPrivateMessages”);
See Outlook, custom task pane and drag-drop problem for more information.

Grabbing Currently Selected Folder in Outlook Add-In

I'm working on an Outlook Add-In that can work in one of two ways, depending on a user's choice - it can process selected emails, or alternatively, process all emails in the selected folder. I've gotten the first part working, but the second part is giving me trouble, possibly because I'm just adapting the code from the first part incorrectly. I believe the trouble comes down to grabbing the currently selected folder properly in a C# Outlook add-in. I'm using .NET 3.5 and Outlook 2007, by the way.
First, the email code - if a user selects one or more emails in their inbox, and runs my add-in with the "selected emails" option, the following code is run (and works fine!):
public static void processSelectedEmails(Outlook.Explorer explorer)
{
//Run through every selected email
for (int i = 1; i <= explorer.Selection.Count; i++)
//alternatively, foreach (Object selectedObject in explorer.Selection)
{
Object selectedObject = explorer.Selection[i];
if (!(selectedObject is Outlook.Folder))
{
string errorMessage = "At least one of the items you have selected is not an email.";
//Code for displaying the error
return;
}
else
Outlook.MailItem email = (selectedObject as Outlook.MailItem);
//Do something with current email
}
}
I've tried to adapt this code to do something else if a user goes to the Navigation Pane (on the left by default) in Outlook, selects a folder or subfolder (perhaps Inbox, Sent Items, or another folder they've created). The user can then choose the "process selected folder" option in my Add-In, which will do essentially the same thing as the code above, but process all of the email inside the selected folder. I have set it to only work if the user has selected a single folder.
public static void processFolder(Outlook.Explorer explorer)
{
//Assuming they have selected only one item
if (explorer.Selection.Count == 1)
{
//Make sure that that selected item is a folder
Object selectedObject = explorer.Selection[1];
if (!(selectedObject is Outlook.Folder))
{
string errorMessage = "The item you have selected is not a folder.";
//Code for displaying the error
return;
}
//Code for running through every email in that folder
}
}
I have not yet written the code to actually run through all of the emails in the selected folder, because my code never gets past the if (!(selectedObject is Outlook.Folder)). Even if the most recently selected item is your Inbox, I receive the error I have programmed in at that point. Perhaps I am misusing the explorer.Selection thing? Any help would be much appreciated.
This may be important to answering my question - the add-in has a field called 'explorer', which is generated on startup: explorer = this.Application.ActiveExplorer. This is the 'explorer' that is passed to my functions so that they can know what is selected. As I said, this works fine for selected emails, but does not work for selected folders. Any insight would be greatly appreciated!
Edit 1: It appears that this question is basically a duplicate of Get all mails in outlook from a specific folder, but it has no answers.
Edit 2: I've been doing further research, it appears that I can get virtually the same functionality (but with an additional step unfortunately) by creating a popup to select a folder using the Application.Session.PickFolder() method. Is there any way to do it based on the currently selected folder, instead of forcing the user to pick a new folder?
Edit 3: I have modified the code found here: http://msdn.microsoft.com/en-us/library/ms268994(v=vs.80).aspx to further show what is not working properly for me:
public static void processFolder(Outlook.Explorer explorer)
{
string message;
if (explorer.Selection.Count > 0)
{
Object selObject = explorer.Selection[1];
if (selObject is Outlook.MailItem)
{
message = "The item is an e-mail";
}
else if (selObject is Outlook.Folder)
{
message = "The item is a folder";
}
else
{
message = "No idea what the item is!";
}
Console.WriteLine(Message);
return;
}
}
Whether I select a message, or go to the Navigation Pane and select a folder, I receive the message "This item is an e-mail".
Explorer.Selection is for Items only (MailItem, AppointmentItem, etc.) - not Folders. To get access to the currently selected Folder you would need Explorer.CurrentFolder.
Folder.Items would provide you access to all the Items in a given Folder.

Categories

Resources