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.
Related
I need to get the "Sent Date" from the Sent Items e-mails, but I am following the example from Microsoft's documentation, for the implementation, making changes to get it from the sent items folder, it doesn't give any errors, but it doesn't work. Microsoft Documentation.
private void ThisAddIn_Startup(object sender, System.EventArgs e)
{
outlookNameSpace = this.Application.GetNamespace("MAPI");
inbox = outlookNameSpace.GetDefaultFolder(
Microsoft.Office.Interop.Outlook
.OlDefaultFolders.olFolderSentMail);
items = inbox.Items;
items.ItemAdd +=
new Outlook.ItemsEvents_ItemAddEventHandler(items_ItemAdd);
}
UPDATE
It doesn't even give an error, I have done tests to check, what seems to happen is that it is picking up from submitted items 1, and I need it to pick up from submitted items 2.
The code in the ThisAddIn_Startup event handler looks good. Try to set a breakpoint in the code and see how it works and whether any exception is thrown at runtime.
Be aware, Outlook may block add-ins that throw exceptions at runtime. So, if your breakpoint is not hit in the ThisAddIn_Startup event handler it makes sense to check the Disabled Items list in Outlook. Most probably your add-in was disabled automatically by the host application. See Support for keeping add-ins enabled for more information.
To get the default folder from another store you need to use the Store.GetDefaultFolder method instead of the following code:
inbox = outlookNameSpace.GetDefaultFolder(
Microsoft.Office.Interop.Outlook
.OlDefaultFolders.olFolderSentMail);
This method is similar to the GetDefaultFolder method of the NameSpace object. The difference is that this method gets the default folder on the delivery store that is associated with the account, whereas NameSpace.GetDefaultFolder returns the default folder on the default store for the current profile.
You can iterate over all stores in the profile in the following way:
private void EnumerateStores()
{
Outlook.Stores stores = Application.Session.Stores;
foreach (Outlook.Store store in stores)
{
if (store.IsDataFileStore == true)
{
Debug.WriteLine(String.Format("Store: "
+ store.DisplayName
+ "\n" + "File Path: "
+ store.FilePath + "\n"));
}
}
}
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.
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'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;
The plot:
I am creating an outlook 2007 add-in using VSTO and C# in Visual Studio 2010. The purpose of the add-in is to cause tracking of mails sent to customers. The add-in should insert a tracking code into every outbound mail that later enables it to be recognized and auto archived once the customer replies. My goal is to insert a tracking code as an attribute in the opening tag of the mail's HTML:
<html tracking="ddfwer4w5c45cgx345gtg4g" ...>
This will be done in the event handler of the Application.ItemSend event:
private void ThisAddIn_Startup(object sender, System.EventArgs e)
{
this.Application.ItemSend += new Microsoft.Office.Interop.Outlook.ApplicationEvents_11_ItemSendEventHandler(Application_ItemSend);
}
void Application_ItemSend(object Item, ref bool Cancel)
{
if (Item is Outlook.MailItem)
{
Outlook.MailItem mail = (Outlook.MailItem)Item;
mail.HTMLBody = "<html tracking=\"4w5te45yv5e6ye57j57jr6\" ...";
}
}
The problem:
It seem to never change the HTMLBody property. And it does not throw any exceptions. It just does nothing. I rewrote this logic directly in VBA in Outlook, and tried to change the HTMLBody, but it still did not change. How I know it did not change the HTMLBody is by stepping through and hovering over the property to see the current value.
I am however able to make changes to the MailItem.Body property. But since I need to hide the tracking code in some way, the Body property does not help me at all. I also added the MailItem.Save() method after changing the HTMLBody property, but no change.
I thought that perhaps the ItemSend event is to late and I can't change the HTMLBody at that time anymore, but I can't find any event like BeforeSend or alike.
Any ideas would be much appreciated.
I use VB a lot more than C#, but I think I see your problem.
Check the function signature of Application_ItemSend. I see that Cancel is passed by reference; shouldn't Item be passed that way too?
void Application_ItemSend(ref object Item, ref bool Cancel)
{
// ...
}
If Item is passed by value, then your code is only manipulating the copy that was made; the original object isn't being touched. At least, that's how it worked in C++ (but my C++ experience is before .Net, so maybe that doesn't apply).
I had a similar need to put some ids into the message. Seems like Outlook thoroughly scrubs the email before sending it, so by the time it is sent, all the nice hidden properties that you set have been removed.
For my particular need, I ended up instead using the UserProperties element of MailItem. This persists from when the email is created to when it ends up in the Sent Items folder. Perhaps this approach can work for you if the customer reply is tried to the sent email through a conversation?
mailItem.UserProperties.Add("myid", Outlook.OlUserPropertyType.olText);
mailItem.UserProperties["myid"].Value = myid;