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.
Related
i am working on a code that get's a list and checks if the items is in emails subjects, i am trying to go through all the emails to compare to the list but the program crashes after 190 emails or so (there are 289 emails in the folder)
I searched online for solutions for this problem and nothing worked for me
oApp = new Microsoft.Office.Interop.Outlook.Application();
// Get the MAPI namespace.
oNS = oApp.GetNamespace("mapi");
// Log on by using the default profile or existing session (no dialog box).
oNS.Logon(Missing.Value, Missing.Value, false, true);
// Alternate logon method that uses a specific profile name.
// TODO: If you use this logon method, specify the correct profile name
// and comment the previous Logon line.
//oNS.Logon("profilename",Missing.Value,false,true);
//Get the Inbox folder.
oInbox = oNS.GetDefaultFolder(Microsoft.Office.Interop.Outlook.OlDefaultFolders.olFolderInbox);
//Get the Items collection in the Inbox folder.
oItems = oInbox.Items;
MessageBox.Show(oItems.Count+"");
oMsg = (Microsoft.Office.Interop.Outlook.MailItem)oItems.GetLast();
public void SearchEmail()
{
if (counter<oItems.Count)
{
try
{
string s;
if (oMsg != null)
{
s = oMsg.Subject;
for (int i = 0; i < allTickets.Count; i++)
{
label2.Text = oMsg.Subject;
string ticketID = allTickets[i].ToString();
if (s.Contains(ticketID) && oMsg.UnRead)
{
unreadTickets.Add(ticketID);
}
}
}
oMsg = (Microsoft.Office.Interop.Outlook.MailItem)oItems.GetPrevious();
counter++;
button2.Text = counter + "";
}
//Error handler.
catch (Exception x)
{
//MessageBox.Show(x.ToString());
}
}
}
the catch exception gives me this:
unable to cast com object of type 'system.__comobject' to interface type 'microsoft.office.interop.outlook
and afterward i am getting this error:
nullreferenceexception object reference not set to an instance of an object
Keep in mind that Inbox can contain items other than MailItem, such as ReportItem or MeetingItem. That would explain the cast error. You need to treat items as a generic object and read the Class property (exposed by all OOM objects) using reflection - if it is 43 (olMailItem), you can cast it to MailItem. Or you can use the "as" operator and check for null.
Also keep in mind that the Items collection is not sorted in any particular order unless you first call Items.Sort and specify a sort order; otheriwise what you get from Items.GetLast is undetermined.
I'm trying to fetch attachments from a particular folder in Outlook 2010 in a C# Windows Forms app. I have a class called MailInbox that contains the Outlook namespace, inbox, and message objects.
Here is the code for that class and its methods:
public class mailInbox
{
//declare needed variables for outlook office interop
public Outlook.Application oApp = new Outlook.Application();
//public Outlook.MAPIFolder oInbox;
public Outlook.MAPIFolder idFolder;
public Outlook.NameSpace oNS;
public Outlook.Items oItems;
public Outlook.MailItem oMsg;
public Outlook.MAPIFolder subFolder;
public string subFolderName;
public mailInbox()
{
//read the subfoldername from a text file
using (StreamReader subFolderNameRead = new StreamReader(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + #"\SuperVerify\config\subfoldername.txt"))
{
subFolderName = subFolderNameRead.ReadLine().Trim();
}
oNS = oApp.GetNamespace("mapi");
//oInbox = oNS.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderInbox);
idFolder = oNS.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderInbox).Folders[subFolderName]; // use the subFolderName string, read from the config text file, to get the folder from outlook
oItems = idFolder.Items;
//oMsg = (Outlook.MailItem)oItems.GetNext();
}
public void FetchEmail() // fetches the next email in the inbox and saves the attachments to the superverify folder
{
oNS.Logon(Missing.Value, Missing.Value, false, true); //login using default profile. This might need to be changed.
oMsg = (Outlook.MailItem) oItems.GetNext(); //fetch the next mail item in the inbox
if(oMsg.Attachments.Count > 0) // make sure message contains attachments **This is where the error occurs**
{
for (int i =0; i< oMsg.Attachments.Count; i++)
{
oMsg.Attachments[i].SaveAsFile(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + #"\SuperVerify\images\" + oMsg.Attachments[i].FileName); //save each attachment to the specified folder
}
} else //if no attachments, display error
{
MessageBox.Show("The inbox folder has no messages.", "TB ID Verification Tool", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
}
}
public void changeSubFolderName(string newSubFolderName)
{
subFolderName = newSubFolderName;
}
}
When I click the button that invokes the FetchEmail method, I get the error
System.NullReferenceException: 'Object reference not set to an instance of an object.'
oMsg was null. I thought that
public Outlook.MailItem oMsg;
instantiated the object and that
oMsg = (Outlook.MailItem) oItems.GetNext();
assigned it an Outlook MailItem, but it seems I don't understand what's going on here.
From the documentation which curiously references VB.NET's Nothing instead of null,
It returns Nothing if no next object exists, for example, if already positioned at the end of the collection.To ensure correct operation of the GetFirst, GetLast, GetNext, and GetPrevious methods in a large collection, call GetFirst before calling GetNext on that collection, and call GetLast before calling GetPrevious. To ensure that you are always making the calls on the same collection, create an explicit variable that refers to that collection before entering the loop.
So GetNext will return null if you're at the end of the folder. You'd have to check it for null before attempting to use it.
You can also use oItems.Count to determine that there are no items when you initially access the folder's items. But if Count is one or more you'd still have to check for null, because you're dealing with a collection that can change. Hypothetically someone could remove items from the folder while you're reading it, so you can't get the count up front and then rely on it.
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 :)
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;
}
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.