Setting Outlook signature for multiple accounts - c#

I am in the process of writing an application that sets a signature based on pre-acquired data for each Microsoft Outlook account(a user may have multiple Outlook accounts for various purposes).
I am able to set a signature for the default account, but I have yet to find how to set a signature for each Outlook account individually. I have done a lot of my own research and poked around the Microsoft.Office.Interop objects without much luck.
Is there a way to achieve this?

To choose the Outlook profile programmatically, you just use
Microsoft.Office.Interop.Outlook.Application App =
new Microsoft.Office.Interop.Outlook.Application();
NameSpace mapi = App.GetNamespace("MAPI");
mapi.Logon(profileName);
obviously setting the profileName to what is shown in the dropdown list upon starting Outlook (if you do not set a default profile in the control panel email settings).
This however is problematic in a number of ways since Outlook does not support multiple sessions even though the MAPI logon does:
http://msdn.microsoft.com/en-us/library/bb219914(v=office.12).aspx
Meaning: if Outlook is already running, you can even set NewSession to true, but it won't help. It will give you the currently-logged-in profile regardless of what name you set. If you have an Outlook zombie (I got that while testing, check with task manager), i.e. an Outlook without an UI showing up, the problem is the same.
If you can ensure Outlook does not run while doing stuff with signatures, you should be fine though.

Related

VSTO - When get Outlook accounts list from NameSpace.Accounts it returns cached data

I'm working on a plugin for Outlook. I need to always have an up-to-date list of Outlook accounts (File->Add Account), but when I take this data from NameSpace.Accounts, they are relevant only at the time Outlook starts. If I add another account or delete the old one, these changes will not be reflected in NameSpace.Accounts. Is there any way to refresh this data?
I am using the following code to get accounts
var outlookObj = new Outlook.Application();
var accounts = outlookObj.Application.Session.Accounts;
foreach (Outlook.Account account in accounts)
{
//do something
}
Firstly, do not use new Outlook.Application() in an addin - an instance of the Application object is provided to your addin on startup, and it is not handicapped by the security prompts..
Also try to avoid caching/keeping a reference to the Accounts or Account object.
If using Redemption is an option (I am its author), it exposes RDOAccounts collection (which is never cached) and, unlike the Accounts collection in OOM, also exposes events when accounts are added/deleted/modified/rearranged.
The Outlook object model doesn't provide such events for accounts. But you may try to handle the Stores.StoreAdd event which is fired when a Store has been added to the current session either programmatically or through user action.
Note, as a possible workaround you may consider using a third-party library such as Redemption which can monitor changes to Accounts in Outlook.
There is no need to create a new Application instance in the code:
var outlookObj = new Outlook.Application();
Instead, in VSTO based add-ins you need to use the ThisAddin class where the Application property is provided out of the box.

Outlook VSTO Add-In C# Events - Events not triggered anymore after some time

currently I'm developing a small VSTO Outlook Add-In. While I've some experience in C#, I'm not very familiar with the Outlook object model.
The scope of my Add-In is pretty easy. My colleagues and I have a shared Outlook inbox (beside our own ones). The shared inbox has categories and subfolders with the same name. E.g. there’s a subfolder “Michael” and there exists a category “Michael”. When somebody applies his own category to a mail in the shared inbox, the mail is automatically moved to the matching subfolder, the reply window opens and the sender address is changed from the shared email address to the personal one (our IT adjusted the shared mail address to not be able to send emails).
Right now the current version of the Add-In works flawlessly, beside the fact that it somehow stops to work after some time. So when I start outlook, everything works like expected, I can categorize mails in the shared inbox and they’re moved etc. But after some time (sometimes hours, sometimes even after 30 minutes) it’s not working anymore. Neither the debug view in Visual Studio nor Outlook are indicating any errors. At first I thought something terminated my Add-In, but then I configured a timer to send a “I’m alive” message to the log file and now I can see that the Add-In is still running.
Hence I assume that somehow the events I’ve registered to are not sufficient to keep track of the users action in Outlook. This can be confirmed as a break point in the event handlers is not triggered when this behavior appears and a mail is categorized. I’ve registered to the following events in the startup method:
Outlook.Application application = this.Application;
Outlook.Inspectors inspectors = application.Inspectors;
Outlook.Explorer activeExplorer = this.Application.ActiveExplorer();
// When a new mail is created, trigger Inspectors_AddTextToNewMail() methode
inspectors.NewInspector = new Outlook.InspectorsEvents_NewInspectorEventHandler(Inspectors_AddTextToNewMail);
// Whenever something in the explorer is selected, run the event handler
activeExplorer.SelectionChange += ActiveExplorer_SelectionChange;
In the selectionChange() Event-Handler another Event-listener for the change of the mail properties is registered:
Outlook.MailItem mailItem = selectedItem as Outlook.MailItem;
// Register an Event handler that listens for changes of the mailitem's properties in order to check the category
mailItem.PropertyChange += MailItem_PropertyChange;
This way I can check whether a category has been applied.
But after some time not even the ActiveExplorer_SelectionChange Event is triggered, independent on what I select in Outlook.
Does anybody know whether I missed something? Do I have to register to further events so the Add-In won’t lose track?
Thanks for your help in advance!
Best Regards,
Percy
You need to declare the variables application, inspectors and activeExplorer on the global (class) level to prevent them from being released by the Garbage Collector.

Enabling events C# VSTO Workbook

I have a VSTO workbook. I have a set of security measures that check the users credentials when opening the file (checks e-mail account exchange and other company security policies) which ensures that only someone within the company can open the file.
I do this in the startup property; however, I know a simple way to get round this is to simply have another workbook open and set enableevents to false in VBA. This will stop the security check from firing.
Is there a way to always ensure that events are active?
I have tried checking if the events are turned on but I cannot get it to work.
Excel workbooks are not secure. Period.
Embedded code can always be viewed, changed, removed and/or disabled.
The data can be typically be accessed without even opening Excel.

Outlook API GetItemFromID() fails with error "Could not open the item.Try again." when using multiple outlook accounts

I am using two outlook accounts from the same exchange server (i.e. same domain). We have an outlook add-in which we use to archive some emails from outlook to an external web application. While composing a new mail, it's possible to attach some files from external application to the mail being composed using the add-in.
Now things work perfectly when I have a single account on outlook. But after configuring another account and trying to do the same from secondary account, outlook gives error:
Outlook Initiator exception:
System.Runtime.InteropServices.COMException (0x80040107): Could not
open the item. Try again. at
Microsoft.Office.Interop.Outlook.NameSpaceClass.GetItemFromID(String
EntryIDItem, Object EntryIDStore)
I tried to dig into the code and found that the call to GetItemFromID() gives the exception shown above.
object item = ns.GetItemFromID(objectID, storeId);
The first parameter objectID (which is EntryIDItem) is different for different accounts but second parameter storeId is same.
I also tried to see the body of the method GetItemFromID() using disassembler but the method is defined as an extern method that means it's defined outside of the current assembly as un-managed code.
Tried to search for anything similar to that on stackoverflow but no luck. Can anybody please help me on this?
Try to leave only the first parameter. The EntryIDStore parameter is optional. See NameSpace.GetItemFromID for more information.
Note, the Entry ID changes when an item is moved into another store, for example, from your Inbox to a Microsoft Exchange Server public folder, or from one Personal Folders (.pst) file to another .pst file. Solutions should not depend on the EntryID property to be unique unless items will not be moved.

Closing an Outlook Contact window created and opened from code shuts down Outlook itself (bad)?

I have an C# WPF application that reads in a bunch of local Outlook contacts and stores them in memory. When a search is conducted in the app, a list of ResultObjects is generated and bound to a ListBox which is show onscreen in my app. A property of a ResultObject is the Outlook Contact it was derived from (Outlook.ContactItem), and I use that to bind to a buttons Tag property (which can be anything you want to assign to it), so that when a user click on the button beside a result they want, the Outlook contact window itself will open to display the contact.
When I pull the list of contacts initially an instance of Outlook is required and created, and the running process is there.
public Outlook.Application usersOutlook = new Outlook.Application();
The problem is, after my code opens an Outlook contact window for the object associated with the clicked button:
buttonContact = (Outlook.ContactItem) ((Button)sender).Tag;
buttonContact.Display();
and then the user closes that window, my running Outlook.Application (and it's process/PID) closes with it - which is not what I want. I need Outlook to stay running for the next contact the user wants to see. With no Outlook still running, the button to show the contact fails. If I brute force a new instance of Outlook, thus creating a new process, clicking the button to show a contact raises an nasty "RPC Server is Unavailable" error which I've yet been able to get around / figure out.
The only way for my app to work properly is if the user starts up Outlook them selves, so the whole app is running on their machine, and then they leave it running while my app is running. That way when they close a contact opened by Outlook via my code, Outlook itself keeps chugging along, and then next contact the user wants to see will work . That is not an acceptable compramise for my customer - they demand Outlook running not be a requirement for the user. The app needs to create a hidden instance in code-behind and maintain it for the lifetime of my running app.
I'd suggest keeping the id of Outlook items in the Tag property of your controls instead. So, you will be able to recover them back with any Outlook instance (even if it is gone). The GetItemFromID method of the Namespace class returns a Microsoft Outlook item identified by the specified entry ID (if valid). For more information about Entry IDs, see the EntryID property:
A MAPI store provider assigns a unique ID string when an item is created in its store. Therefore, the EntryID property is not set for an Outlook item until it is saved or sent. The Entry ID changes when an item is moved into another store, for example, from your Inbox to a Microsoft Exchange Server public folder, or from one Personal Folders (.pst) file to another .pst file. Solutions should not depend on the EntryID property to be unique unless items will not be moved. The EntryID property returns a MAPI long-term Entry ID.
That's what Outlook does - closes itself when the last window (Explorer or Inspector) is closed, even if there are still references to Outlook Object Model objects. The only exceptions are the Explorer and Inspector objects, even if they are not visible.
Try to retrieve an Explorer object from an instance of the MAPIFolder object (MAPIFolder.GetExplorer) and keep it referenced until you are done. You don't have to do anything with it, just keep it referenced in a global/class variable. MAPIFolder can be any Outlook folder, e.g. the default Contacts folder returned by Namespace.GetDefaultFolder(olFolderContacts).

Categories

Resources