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.
Related
I am using Outlook.Application and Outlook.MailItem object for opening Outlook in my C# desktop application. My outlook doesn't display attachments although when I send the mail to myself, I receive mail with attachments. But it is not showing before sending mail (when outlook is open). I am using Outlook 2007. Below is my code:
Outlook.Application oApp = new Outlook.Application();
Outlook.NameSpace oNS = oApp.GetNamespace("mapi");
// Log on by using a dialog box to choose the profile.
oNS.Logon(Missing.Value, Missing.Value, true, true);
// Create a new mail item.
Outlook.MailItem oMsg = (Outlook.MailItem)oApp.CreateItem(Outlook.OlItemType.olMailItem);
......
//Check if we need to add attachments
if (_files.Count > 0)
{
foreach (string attachment in _files)
{
oMsg.Attachments.Add(attachment,Outlook.OlAttachmentType.olByValue,null,null);
}
}
oMsg.Save();
oMsg.Display(false);
Of course, Type.Missing is used to omit the parameter and use the default value in COM add-ins.
Also I'd suggest breaking the chain of calls and declaring each property or method call on a separate line of code. It will allow to release each underlying COM object instantly.
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. You can read more about that in the Systematically Releasing Objects article in MSDN.
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)
I am writing an outlook add-in,
and I need when receiving an email, it goes to default inbox folder as normal, but it make a copy of that incoming email and put it into another folder(say Junk folder as example).
but I encounter the exception "Cannot move the items." all the time when i move the copy of the email. any ideas?
private void items_ItemAdd(object Item)
{
Outlook.MAPIFolder inBox = (Outlook.MAPIFolder)
this.Application.ActiveExplorer().Session.GetDefaultFolder
(Outlook.OlDefaultFolders.olFolderInbox);
// the incoming email
Outlook.MailItem mail = (Outlook.MailItem)Item;
//make a copy of it but error occurs
Outlook.MailItem cItem = mail.copy();
//
cItem = (Outlook.MailItem)cItem.Move((Outlook.MAPIFolder)
this.Application.ActiveExplorer().Session.GetDefaultFolder
(Outlook.OlDefaultFolders.olFolderJunk));
You are in the ItemAdd event handler. Try to store the item's entry id in a variable or a list and start a timer (use the one from the Forms namespace). When the time fires, you will be out of the event handler and should be able to call MailItem.Move.
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.
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;