How to Program Outlook 2007 Add-In with Multiple Mailboxes - c#

I'm trying to figure how to write a simple add-in for Excel 2007, but one that only interacts with one of my mailboxes. Currently I have two email addresses coming into my outlook, each in a specific 'mailbox'. I was wondering, how would I specify a NewMail event for a specific mailbox?
Or, perhaps not as clean, but how could I write an if function that specifies which mailbox / email any new item is addressed to...
Hopefully this makes sense. Thanks

To catch new mail event, add this code to addin startup method:
this.Application.NewMailEx +=
new Outlook.ApplicationEvents_11_NewMailExEventHandler(Application_NewMailEx);
Then add method to handle NewMailEx event:
void Application_NewMailEx(string EntryID)
{
// get MailItem for this new mail
Outlook.Explorers explorers = this.Application.Explorers;
Outlook.MailItem newMail =
(Outlook.MailItem)explorers.Application.Session.GetItemFromID(EntryID, System.Reflection.Missing.Value);
// check SendUsingAccount to see if it came in mailbox we are interested in
if (newMail.SendUsingAccount.DisplayName == "your.name#your.domain.com")
{
// do whatever You like
}
}
Add using statement also:
using Outlook = Microsoft.Office.Interop.Outlook;

Related

Adding to Outlook Email Recipient using VSTO before sending email

Looking a bit of advise or direction in regards to VSTO Ribbons with Outlook in C#.
So far I’ve built an Outlook 2010 Ribbon (using TabMail), this Ribbon opens a WinForms window which allows my users to select contacts from a Custom Built Address Book from a SQL database, via a DataGridView.
The users basically select from a datagridview who they want to email, which then gets added to a toLine list.
Application app = new Microsoft.Office.Interop.Outlook.Application();
Mail item item = app.CreateItem((OlItemType.olMailItem));
item.To = toLine;
Item.Display();
This.close();
The downside of using this approach is the user has to build their To List before they actually compose their email.
I’m now trying to make use of TabMailNewMessage. This should allow the user to compose their email, then click the Ribbon icon within the new message and add to their To List from there.
I’ve got the icon showing okay in the TabMailNewMessage, and I’ve got it to open a 2nd Win Form [currently as a test].
I’m a little unsure how to add to the To List of an already open existing mailItem.
At present all I have on the 2nd Win Form is a button, can someone explain how I can click that button and simply add someone to the To List [of this already composed email]. (I don’t have any code behind the button click as I’m not sure what to do)
I also need to make sure that it doesn’t send the email, but simply adds the user to the To List.
Currently using Office 2010, and VS 2013 (with C#).
Hopefully I’m making some sense here.
Thanks
EDIT:
Not sure if its a simple as
Application app = Globals.ThisAddIn.Application;
MailItem mi = (Outlook.MailItem)app.ActiveInspector().CurrentItem;
Mi.Recipients.Add(“joe#email.com”);
This.Close();
The MailItem.Recipients.Add method allows creating a new recipient in the Recipients collection. The name of the recipient can be a string representing the display name, the alias, or the full SMTP email address of the recipient.
using System.Runtime.InteropServices;
// ...
private bool AddRecipients(Outlook.MailItem mail)
{
bool retValue = false;
Outlook.Recipients recipients = null;
Outlook.Recipient recipientTo = null;
Outlook.Recipient recipientCC = null;
Outlook.Recipient recipientBCC = null;
try
{
recipients = mail.Recipients;
// first, we remove all the recipients of the e-mail
while(recipients.Count != 0)
{
recipients.Remove(1);
}
// now we add new recipietns to the e-mail
recipientTo = recipients.Add("Eugene Astafiev");
recipientTo.Type = (int)Outlook.OlMailRecipientType.olTo;
recipientCC = recipients.Add("Somebody");
recipientCC.Type = (int)Outlook.OlMailRecipientType.olCC;
recipientBCC = recipients.Add("eugene.astafiev#somedomain.com");
recipientBCC.Type = (int)Outlook.OlMailRecipientType.olBCC;
retValue = recipients.ResolveAll();
}
catch (Exception ex)
{
System.Windows.Forms.MessageBox.Show(ex.Message);
}
finally
{
if (recipientBCC != null) Marshal.ReleaseComObject(recipientBCC);
if (recipientCC != null) Marshal.ReleaseComObject(recipientCC);
if (recipientTo != null) Marshal.ReleaseComObject(recipientTo);
if (recipients != null) Marshal.ReleaseComObject(recipients);
}
return retValue;
}
You may find the following articles helpful:
How To: Fill TO,CC and BCC fields in Outlook programmatically
How To: Create and send an Outlook message programmatically
Also, I'd suggest developing an Outlook form region which can be displayed on the same window instead of using a standalone window, see Create Outlook form regions for more information.
Yes, it is as simple as using Application.ActiveInspector.CurrentItem. But you can do better than that - your ribbon button event handler takes IRibbonControl object as a parameter. Cast the IRibbonControl.Context property to Inspector or Explorer (depending on where the button is hosted).
Also keep in mind that in a COM addin there is no reason to create a new instance of the Outlook.Application object (it will be crippled with the security prompts anyway) - use Globals.ThisAddIn.Application

How to search an email from all folders in store using Linq Outlook C#

I am performing custom action on all incoming replies through VSTO add-in. The add-in will compare ConversationID of incoming reply with existing email. It works fine if I have to search inside one folder but my problem is email can be in any folder in store. Here is my code.
void items_ItemAdd(object Item)
{
Outlook.Application application = new Outlook.Application();
string filter = "RE: ";
Outlook.MailItem mail = (Outlook.MailItem)Item;
Outlook.Folder folder = mail.Parent as Outlook.Folder;
if (Item != null)
{
if (mail.MessageClass == "IPM.Note" && mail.Subject.ToUpper().Contains(filter.ToUpper()))
{
var RequiredMail = (from e in folder.Items.Cast<Outlook.MailItem>().OrderBy(X => X.ReceivedTime).Where(C => C.ConversationID == mail.ConversationID) select mail).FirstOrDefault();
// Perform custom action
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
}
}
Also, I have read that searching for an email using Linq is not very efficient. Is there any other more efficient way to get RequiredMail?
Any help will be highly appreciated.
Thank you.
First of all, you must be aware that ItemAdd event may not be fired if more than sixteen items are added to the collection. This is a known issue in Outlook. The following series of articles describes possible workarounds for that:
Outlook NewMail event unleashed: the challenge (NewMail, NewMailEx, ItemAdd)
Outlook NewMail event: solution options
Outlook NewMail event and Extended MAPI: C# example
Outlook NewMail unleashed: writing a working solution (C# example)
Mixing LINQ and COM objects is not a really good idea. You should release underlying COM objects instantly to prevent any known issues.
If you need to search for items in all folders you may use the AdvancedSearch method of the Application class which allows to perform a search based on a specified DAV Searching and Locating (DASL) search string.
The key benefits of using the AdvancedSearch method in Outlook are:
The search is performed in another thread. You don’t need to run another thread manually since the AdvancedSearch method runs it automatically in the background.
Possibility to search for any item types: mail, appointment, calendar, notes etc. in any location, i.e. beyond the scope of a certain folder. The Restrict and Find/FindNext methods can be applied to a particular Items collection (see the Items property of the Folder class in Outlook).
Full support for DASL queries (custom properties can be used for searching too). You can read more about this in the Filtering article in MSDN. To improve the search performance, Instant Search keywords can be used if Instant Search is enabled for the store (see the IsInstantSearchEnabled property of the Store class).
You can stop the search process at any moment using the Stop method of the Search class.
Read more about that in the Advanced search in Outlook programmatically: C#, VB.NET article.

Issues reading unread mails in Outlook

I am trying to develop an add-in for Outlook. In that I want remove attachment when a new mail is received.
So I call my function on the NewMailEx event. It is working fine. In that function I try to find unread mails in the Outlook inbox. From those I remove the attachments.
My problem is: when I open Outlook, the first mail I received is not showing in the inbox (not in outlook c# code), so I can't remove the attachment from that mail.
From the second mail (after the first mail), I can get the received mail, so I can remove the attachments.
Whenever I close and reopen Outlook, the first mail I receive gives this problem.
At the first mail received there is no unread mail.
private void Application_NewMailEx(object Item)
{
string senderEmailid = string.Empty;
outlookNameSpace = this.Application.GetNamespace("MAPI");
Outlook.Application myApp = new Outlook.Application();
Outlook.NameSpace mapiNameSpace = myApp.GetNamespace("MAPI");
Outlook.MAPIFolder myInbox = mapiNameSpace.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderInbox);
Outlook.Attachments attachments;
int test = myInbox.Items.Count;
Microsoft.Office.Interop.Outlook.Recipients recipients = ((Outlook.MailItem)myInbox.Items[test]).Recipients;
Outlook.Items unreadItems = myInbox.Items.Restrict("[Unread]=true");
if (unreadItems.Count > 0)
{
foreach (Outlook.MailItem mail in unreadItems)
{
Outlook.Recipient recip;
Outlook.ExchangeUser exUser;
string sAddress;
if (mail.SenderEmailType.ToLower() == "ex")
{
recip = Globals.ThisAddIn.Application.GetNamespace("MAPI").CreateRecipient(mail.SenderEmailAddress);
exUser = recip.AddressEntry.GetExchangeUser();
sAddress = exUser.PrimarySmtpAddress;
}
else
{
sAddress = mail.SenderEmailAddress.Replace("'", "");
}
string[] emailAddressPart = sAddress.Split('#');
string strSenderDomain = emailAddressPart[1];
if (lstDomain.Any(item => item.Contains(strSenderDomain)))
{
attachments = mail.Attachments;
int nAttachmentCount = mail.Attachments.Count;
if (nAttachmentCount > 0)
{
int j = nAttachmentCount;
for (int i = 1; i <= nAttachmentCount; i++)
{
mail.Attachments[j].Delete();
j--;
}
}
}
}
}
}
The NewMailEx event of the Application class is not the best place for searching unread emails. This event fires once for every received item that is processed by Microsoft Outlook. The item can be one of several different item types, for example, MailItem, MeetingItem, or SharingItem. The EntryIDsCollection string contains the Entry ID that corresponds to that item. The alternative way is to handle the ItemAdd event of the Items class.
Instead, you can wait until Outlook finishes synchronizing items and run your code for searching unread emails. The SyncEnd event of the SyncObject class is fired immediately after Microsoft Outlook finishes synchronizing a user’s folders using the specified Send/Receive group.
Also you may consider handling the Startup or MAPILogonComplete events. But they are fired before the synchronization is completed. Consider using a timer to run the procedure a bit after Outlook is started.
You can read about possible ways of handling incoming emails in the following series of articles:
Outlook NewMail event unleashed: the challenge (NewMail, NewMailEx, ItemAdd)
Outlook NewMail event: solution options
Outlook NewMail event and Extended MAPI: C# example
Outlook NewMail unleashed: writing a working solution (C# example)
Also I'd recommend breaking the chain of calls and delaclaring each property or method call on a separate line of code. Use System.Runtime.InteropServices.Marshal.ReleaseComObject to release an Outlook object when you have finished using it. This is particularly important if your add-in attempts to enumerate more than 256 Outlook items in a collection that is stored on a Microsoft Exchange Server. If you do not release these objects in a timely manner, you can reach the limit imposed by Exchange on the maximum number of items opened at any one time. Then set a variable to Nothing in Visual Basic (null in C#) to release the reference to the object. Read more about that in the Systematically Releasing Objects article in MSDN.
There is nothing you can do about that. From the documentation on NewMailEx:
Also, the event will fire only if Outlook is running. In other words, it will not fire for the new items that are received in the Inbox when Outlook was not open.
That means you have to manually call your method to walk down all the unread emails when opening Outlook.

Parse Outlook email in Inbox which belongs to other account

I am trying to create a service which will run as a background service on a server. This service will parse email as soon as it enters the Inbox.
We have one email account abc#organization.com. We are using Outlook to check the emails. It is a service so Outlook won't be running all the time on the server. I want to parse the email automatically for this account. This account is not my email account. I am using Microsoft.Office.Interop.outlook in C# program.
This program is running but it is parsing email from my email inbox. I don't know how to specify specific email to parse the Inbox. Need to know the event which triggers as soon as new mail arrives. My program parsed half the emails from my inbox but after that it is throwing object null reference error.
static void Main(string[] args)
{
Microsoft.Office.Interop.Outlook.Application myApp=new Microsoft.Office.Interop.Outlook.Application();
try
{
String Subject, Body, Createdate, Sender = null;
Microsoft.Office.Interop.Outlook.NameSpace mapinamespace = myApp.GetNamespace("MAPI");
mapinamespace.Logon(null, null,true,true);
Microsoft.Office.Interop.Outlook.MAPIFolder myInbox = mapinamespace.GetDefaultFolder(Microsoft.Office.Interop.Outlook.OlDefaultFolders.olFolderInbox);
Microsoft.Office.Interop.Outlook.Accounts accounts = myApp.Session.Accounts;
try
{
foreach (Microsoft.Office.Interop.Outlook.Account account in accounts)
{
if (account.SmtpAddress == "abc#organization.com")
{
Console.Write(account);
}
else
{
Console.Write("Not found ---");
}
}
}
catch{
throw new System.Exception(string.Format("No account with amtp:{0} exists!"));}
foreach (object item in myInbox.Items)
{
try
{
var mail = item as MailItem;
if (mail != null)
{
//Creation date
Createdate = mail.CreationTime.ToString();
Console.WriteLine("CreationTime---" + Createdate);
//Grab the senders address
Sender = mail.SenderEmailAddress.ToString();
Console.WriteLine("Sender's E-mail---" + Sender);
//grab the Subject
Subject = mail.Subject.ToString();
Console.WriteLine("Subject--" + Subject);
//Grab the body
Body = mail.Body.ToString();
Console.WriteLine("Body---" + Body);
//Grab the Attachment
}
else
{
Console.Write("Error in mail---");
}
}
catch (System.Runtime.InteropServices.COMException e)
{
Console.Write(e);
}
}
}
catch (System.Runtime.InteropServices.COMException e)
{
Console.Write(e);
}
}
I am trying to create a service which will run as a background service on server.
Microsoft does not currently recommend, and does not support, Automation of Microsoft Office applications from any unattended, non-interactive client application or component (including ASP, ASP.NET, DCOM, and NT Services), because Office may exhibit unstable behavior and/or deadlock when Office is run in this environment.
If you are building a solution that runs in a server-side context, you should try to use components that have been made safe for unattended execution. Or, you should try to find alternatives that allow at least part of the code to run client-side. If you use an Office application from a server-side solution, the application will lack many of the necessary capabilities to run successfully. Additionally, you will be taking risks with the stability of your overall solution.
You can read more about that in the Considerations for server-side Automation of Office article.
Anyway, it looks like you are interested in the NewMailEx event of the Application class. Also I'd suggest reading the following series of articles:
Outlook NewMail event unleashed: the challenge (NewMail, NewMailEx, ItemAdd)
Outlook NewMail event: solution options
Outlook NewMail event and Extended MAPI: C# example
Outlook NewMail unleashed: writing a working solution (C# example)

Outlook Add-In, right Eventhandler

I try to build a Add-In that saves Attachments form a Mail with a specific Subject.
Till now that works fine, but i think that im using the wrong Eventhandler for my needs.
It should start if a new Mail comes in, and then check the whole Inbox + the new mail.
atm im using Microsoft.Office.Interop.Outlook.ApplicationEvents_11_NewMailEventHandler()
so he just looking for the Inbox without the new item, because at that moment the new mail isnt part of the inbox
private void ThisAddIn_Startup(object sender, System.EventArgs e)
{
this.Application.NewMail += new Microsoft.Office.Interop.Outlook
.ApplicationEvents_11_NewMailEventHandler(ThisAddIn_NewMail);
}
What can i do instead ?
You can assume that the email will be unread, so you should be able to use Items.Find/FindNext to look for the unread messages. Or you can store the date of the last processed e-mail and, again, use Items.Find/FindNext to search for messages with CreationTime greater than some value.

Categories