I am setting the property (for making them As Read and with High Importance) of the mail those are coming to the MS Outlook 2010 inbox using below code -
Microsoft.Office.Interop.Outlook.Application myApp = new Microsoft.Office.Interop.Outlook.Application();
Microsoft.Office.Interop.Outlook.NameSpace mapiNameSpace = myApp.GetNamespace("MAPI");
Microsoft.Office.Interop.Outlook.MAPIFolder myInbox = mapiNameSpace.GetDefaultFolder(Microsoft.Office.Interop.Outlook.OlDefaultFolders.olFolderInbox);
int i = myInbox.Items.Count;
((Microsoft.Office.Interop.Outlook.MailItem)myInbox.Items[i]).UnRead = false;
((Microsoft.Office.Interop.Outlook.MailItem)myInbox.Items[i]).Importance = OlImportance.olImportanceHigh;
This works fine when only one mail comes at a time (I can see the mail as Read and with High Importance) after the code execution but when three or four mails coming at a time then it set the property of only one mail not for all the three or four mails.
Please suggest.
Remember to save the message after setting any property.
Most importantly, your code uses multiple dot notation - for each ".", you get back a brand new COM object, so you end up setting Importance property on an object different from the one used to set the UnRead property.
int i = myInbox.Items.Count;
MailItem msg = (Microsoft.Office.Interop.Outlook.MailItem)myInbox.Items[i];
msg.UnRead = false;
msg.Importance = OlImportance.
msg.Save();
Another problem is that you assume that the last item in the Items collection is the latest one. This is not generally true. As cremor suggested, use Items.ItemAdd event, but still do not forget to save the message.
You can use the ItemAdd event of the Items property of the folder:
Items inboxItems = myInbox.Items;
inboxItems.ItemAdd += HandleItemAdded;
private void HandleItemAdded(object item)
{
MailItem mail = item as MailItem;
if (mail == null) { return; }
mail.UnRead = false;
mail.Importance = OlImportance.olImportanceHigh;
}
Related
I am trying to create an outlook add-in in C# which collects header information from new emails in the inbox. Googling it says to use the following code to get the header information for the email.
mailitem.PropertyAccessor.GetProperty("http://schemas.microsoft.com/mapi/proptag/0x007D001F/")
However when I use this the error Object reference not set to an instance of an object. Click the schema address also says the resource is no longer there is there another way of getting this or do I need to use a different language?
For reference I have added the below.
private void Quarantine()
{
Outlook.MAPIFolder inBox = (Outlook.MAPIFolder)this.Application.
ActiveExplorer().Session.GetDefaultFolder
(Outlook.OlDefaultFolders.olFolderInbox);
Outlook.Items items = (Outlook.Items)inBox.Items;
Outlook.MailItem MailItem = null;
items.Restrict("[UnRead] = true");
var destFolder = inBox.Folders["test"];
string StrRegex = #"(Final Score - [-][0-9] | Final Score - [2][0 - 1] | Final Score - [0 - 1][0-9])";
Regex Reg = new Regex(StrRegex);
foreach (object email in items)
{
MailItem = email as Outlook.MailItem;
String Header= MailItem.PropertyAccessor.GetProperty("http://schemas.microsoft.com/mapi/proptag/0x007D001F/");
if (!(Reg.IsMatch(Header)))
{
MailItem.Move(destFolder);
}
}
}
}
as operator will return null is the object is not a MailItem. Your code never checks for that. You can have objects other than MailItem in the Inbox folder, such as ReportItem, MeetingItem, etc.
I am using visual studio 2017 installed office development pack,want to create a plugin which responds based on incoming email.
Basically I am tying to monitor an Infra support mailbox ,which forwards the email to concerned team based on the incoming message content.
Any suggestion on how this can be done
There are several ways for implementing the required functionality:
Use rules for setting up forward rules. You can do that manually in Outlook and programmatically as well. The Outlook object model provides all the required classes for that, see How to: Create a Rule to Assign Categories to Mail Items Based on Multiple Words in the Subject for more information.
Use the NewMailEx event for handling incoming emails. The NewMailEx event fires when a new message arrives in the Inbox and before client rule processing occurs. You can use the Entry ID represented by the EntryIDCollection parameter passed to call the NameSpace.GetItemFromID method and process the item. In the event handler, you may check the email received and forward the email programmatically. The Forward method of the MailItem class executes the Forward action for an item and returns the resulting copy as a MailItem object.
Sub RemoveAttachmentBeforeForwarding()
Dim myinspector As Outlook.Inspector
Dim myItem As Outlook.MailItem
Dim myattachments As Outlook.Attachments
Set myinspector = Application.ActiveInspector
If Not TypeName(myinspector) = "Nothing" Then
Set myItem = myinspector.CurrentItem.Forward
Set myattachments = myItem.Attachments
While myattachments.Count > 0
myattachments.Remove 1
Wend
myItem.Display
myItem.Recipients.Add "Dan Wilson"
myItem.Send
Else
MsgBox "There is no active inspector."
End If
End Sub
You may find the How To: Respond to an Outlook email programmatically article helpful.
This code using a event to incoming mails to the default inbox
using Outlook = Microsoft.Office.Interop.Outlook;
public partial class ThisAddIn
{
Outlook.NameSpace outlookNameSpace;
Outlook.MAPIFolder inbox;
Outlook.Items items;
private void ThisAddIn_Startup(object sender, System.EventArgs e)
{
outlookNameSpace = this.Application.GetNamespace("MAPI");
inbox = outlookNameSpace.GetDefaultFolder(
Microsoft.Office.Interop.Outlook.
OlDefaultFolders.olFolderInbox);
items = inbox.Items;
items.ItemAdd +=
new Outlook.ItemsEvents_ItemAddEventHandler(items_ItemAdd);
}
void items_ItemAdd(object Item)
{
Outlook.MailItem mail = (Outlook.MailItem)Item;
if (Item != null)
{
Outlook.MailItem replyMail = mail.Reply();
//Do your response
mail.Send();
}
}
}
I'm developing an Office VSTO add-in in C# which looks up calendar appointments in Outlook, and reads/writes some data in them.
Recently, one of the clients had issues with the add-in, namely they can't read/write the calendar appointment, and it throws an exception :
The operation failed.
There's not much info from the exception log, but I suspect they have synchronization problems with Exchange.
I asked the client, and they said, that they also have a random popup in Outlook as well, which sometimes happens when there's a mishap while syncing with Exchange. I told them to 'repair' the Outlook data files, but that didn't fix the problem.
The outlook items are basically looked up based on their Outlook EntryIDs OR a Subject (the subjects are unique, and for the sake of simplicity I translated the code a little bit)
...main alghorythm...
Outlook.AppointmentItem calAppointment = null;
calAppointment = SearchforCalendarMatch(EntryID, Subject); //we try to find either by EntryID or by Subject
if (calAppointment != null)
{
calAppointment.Start = StartDate;
calAppointment.End = FinishDate;
calAppointment.Body = Notes;
calAppointment.Save(); //we're changing the found calendar appointment here
}
...
public Outlook.AppointmentItem SearchforCalendarMatch(String EntryID, String Subject)
{
Outlook.NameSpace ns = null;
Outlook.MAPIFolder calendarFolder = null;
Outlook.Items calendarFolderItems = null;
Outlook.Items filteredcalendarFolderItems = null;
Outlook.AppointmentItem calAppointment = null;
Outlook.Application OutlookApp = new Outlook.Application();
outlookversion = OutlookApp.Version;
ns = OutlookApp.Session;
//Try to find the calendar appointment by the EntryID
dynamic OutlookItem = ns.GetItemFromID(t.Text28);
if (OutlookItem != null)
{
if (OutlookItem is Outlook.AppointmentItem)
{
Outlook.AppointmentItem foundItem = (Outlook.AppointmentItem)OutlookItem;
return foundItem;
}
}
//If the EntryID was missing, we try to find the calendar appointment by the Subject.
//(original code is very long, and there are multiple things here, but let's just assume that 100% sure that the subject is unique, so it will find it)
String SubjectMatch = "[Subject] = '" + Subject + "'";
filteredcalendarFolderItems = calendarFolderItems.Restrict(SubjectMatch);
for (int i = 1; i <= filteredcalendarFolderItems.Count; i++)
{
//appointment has to be one of these
calAppointment = (Microsoft.Office.Interop.Outlook.AppointmentItem)filteredcalendarFolderItems[i];
if (!calAppointment.IsConflict) //conflict check here, not sure if it helps at all
{
return calAppointment; //this is not the complete code, but this is the basic idea of it.
}
}
}
Any ideas how I could make the application recognize these failed Exchange syncs, and handle them differently?
I would still like to sync in these cases, if it's possible... (change the 'local data' in Outlook, then let Outlook handle everything from that on)
You need to release underlying COM objects 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. Read more about that in the Systematically Releasing Objects article.
I'm trying to add custom UserProperty to MailItem while creating it.
I add an attachement's Hash as UserProperty to my MailItem object.
Then I open my new MailItem in Outlook.
mi = olApp.CreateItem(Outlook.OlItemType.olMailItem) as Outlook.MailItem;
Outlook.UserProperties mailUserProperties = null;
Outlook.UserProperty mailUserProperty = null;
mi.Attachments.Add(file.FilePath);
mailUserProperties = mi.UserProperties;
mailUserProperty = mailUserProperties.Add("AttachementsHash", Outlook.OlUserPropertyType.olText);
mailUserProperty.Value = file.Hash;
mi.Save();
mi.Display();
If I check MailItem.UserProperties using OutlookSpy BEFORE sending I see that my mail has one UserProperty.
Then I click "Send Mail" in Outlook and I check my mail in SentItems folder.
I can see UserProperties.Count == 0.
If anyone knows why my UserProperty disappear, please help me and tell :)
With a lot of effort i resolved my problem.
UserProperties are removed after sending mail. But in stead of UserProperties I used MailItem.PropertyAccessor.SetProperty
MSDN Documentation of Property Accessor
string prop = "http://schemas.microsoft.com/mapi/string/{00020386-0000-0000-C000-000000000046}/PropertyName";
mi.PropertyAccessor.SetProperty(prop, propertyValue.ToString());
And then on event 'ItemAdd' I checked, if item was added to sentItems.
If it Was added to sentItems I read properties using such construction:
Outlook.MailItem AddedMail = item as Outlook.MailItem;
string attachmentProperty = AddedMail.PropertyAccessor.GetProperty("http://schemas.microsoft.com/mapi/proptag/0x007D001E");
And then finnally I parse string in order to get my data.
I hope it will help anyone :)
in my outlook addin I want to add a button on the Ribbon so when user click this button I want to retrieve the current selected email's body , I have this code but it retrieve only the first email from the inbox because the index is 1 :
Microsoft.Office.Interop.Outlook.Application myApp = new Microsoft.Office.Interop.Outlook.Application();
Microsoft.Office.Interop.Outlook.NameSpace mapiNameSpace = myApp.GetNamespace("MAPI");
Microsoft.Office.Interop.Outlook.MAPIFolder myInbox = mapiNameSpace.GetDefaultFolder(Microsoft.Office.Interop.Outlook.OlDefaultFolders.olFolderInbox);
String body = ((Microsoft.Office.Interop.Outlook.MailItem)myInbox.Items[1]).Body;
so how to retrieve the current opened email in outlook? , this method work for me but I need to get the index for the current email.
Thanks.
You shouldn’t initialize a new Outlook.Application() instance each time. Most add-in frameworks provide you with an Outlook.Application instance, corresponding to the current Outlook session, typically through a field or property named Application. You are expected to use this for the lifetime of your add-in.
To get the currently-selected item, use:
Outlook.Explorer explorer = this.Application.ActiveExplorer();
Outlook.Selection selection = explorer.Selection;
if (selection.Count > 0) // Check that selection is not empty.
{
object selectedItem = selection[1]; // Index is one-based.
Outlook.MailItem mailItem = selectedItem as Outlook.MailItem;
if (mailItem != null) // Check that selected item is a message.
{
// Process mail item here.
}
}
Note that the above will let you process the first selected item. If you have multiple items selected, you might want to process them in a loop.
On Top add reference to
using Outlook = Microsoft.Office.Interop.Outlook;
Then inside a method;
Outlook._Application oApp = new Outlook.Application();
if (oApp.ActiveExplorer().Selection.Count > 0)
{
Object selObject = oApp.ActiveExplorer().Selection[1];
if (selObject is Outlook.MailItem)
{
Outlook.MailItem mailItem = (selObject as Outlook.MailItem);
String htmlBody = mailItem.HTMLBody;
String Body = mailItem.Body;
}
}
Also you can change the body which will show in outlook before viewing the mail.