Parsing emails in outloook with C# - c#

I'm writing a program to read all my outlook emails, eventually the search will be more specific but for now i want to read all the email in my inbox. i have code running that reads what i want up to 169 for some reason...
namespace reademail
{
static class Program
{
public static Microsoft.Office.Interop.Outlook.Application myApp;
public static void Main(string[] args)
{
// myApp = new Microsoft.Office.Interop.Outlook.Application();
//myApp.NewMailEx += new Microsoft.Office.Interop.Outlook.ApplicationEvents_11_NewMailExEventHandler(OutlookNewMailReceived);
ReadMail();
}
static void ReadMail()
{
Microsoft.Office.Interop.Outlook.Application app = null;
Microsoft.Office.Interop.Outlook._NameSpace ns = null;
Microsoft.Office.Interop.Outlook.MailItem item = null;
Microsoft.Office.Interop.Outlook.MAPIFolder inboxFolder = null;
app = new Microsoft.Office.Interop.Outlook.Application();
ns = app.GetNamespace("MAPI");
//ns.Logon(null, null, false, false);
inboxFolder = ns.GetDefaultFolder(Microsoft.Office.Interop.Outlook.OlDefaultFolders.olFolderInbox);
// subFolder = inboxFolder.Folders["Inbox"]; //folder.Folders[1]; also works
Console.WriteLine("Folder Name: {0}, EntryId: {1}", inboxFolder.Name, inboxFolder.EntryID);
Console.WriteLine("Num Items: {0}", inboxFolder.Items.Count.ToString());
//System.IO.StreamWriter strm = new System.IO.StreamWriter("C:/Test/Inbox.txt");
for (int counter = 1; counter <= inboxFolder.Items.Count; counter++)
{
Console.Write(inboxFolder.Items.Count + " " + counter);
item = (Microsoft.Office.Interop.Outlook.MailItem)inboxFolder.Items[counter];
Console.WriteLine("Item: {0}", counter.ToString());
Console.WriteLine("Subject: {0}", item.Subject);
Console.WriteLine("Sent: {0} {1}", item.SentOn.ToLongDateString(), item.SentOn.ToLongTimeString());
Console.WriteLine("Sendername: {0}", item.SenderName);
Console.WriteLine("Body: {0}", item.Body);
//strm.WriteLine(counter.ToString() + "," + item.Subject + "," + item.SentOn.ToShortDateString() + "," + item.SenderName);
}
//strm.Close();
}
}
}
The loop reads up to 169 emails and then crashes, also it starts reading emails at what seems to be an arbitrary date...I'm not sure whats preventing it from reading all emails...
Folder Name: Inbox, EntryId: 000000003527EA8DB4FFC04EB6ABA4DE31CB4BA40100C6D3EBA
DBDB57E438D0B53C5FB515CC50000660627C70000
Num Items: 1048
System.InvalidCastException: Unable to cast COM object of type 'System.__ComObje
ct' to interface type 'Microsoft.Office.Interop.Outlook.MailItem'. This operatio
n failed because the QueryInterface call on the COM component for the interface
with IID '{00063034-0000-0000-C000-000000000046}' failed due to the following er
ror: No such interface supported (Exception from HRESULT: 0x80004002 (E_NOINTERF
ACE)).
at CallSite.Target(Closure , CallSite , Object )
at reademail.Program.ReadMail() in C:\Documents and Settings\DBubel\my docume
nts\visual studio 2010\Projects\reademail\reademail\Program.cs:line 60
Press any key to continue . . .

My guess is that you have items in your inbox that do not apply the Microsoft.Office.Interop.Outlook.MailItem interface and therefore the code crashes while going through the loop and attempting to cast. One possible workaround, if you are using .NET4 since it has support for dynamic, is not to cast the object but rather pass it to a dynamic variable.
dynamic item = inboxFolder.Items[counter];
This worked for me as your code was having problems handling meeting invites in the inbox folder.
Full modified code:
namespace reademail
{
static class Program
{
public static Microsoft.Office.Interop.Outlook.Application myApp;
public static void Main(string[] args)
{
// myApp = new Microsoft.Office.Interop.Outlook.Application();
//myApp.NewMailEx += new Microsoft.Office.Interop.Outlook.ApplicationEvents_11_NewMailExEventHandler(OutlookNewMailReceived);
ReadMail();
}
static void ReadMail()
{
Microsoft.Office.Interop.Outlook.Application app = null;
Microsoft.Office.Interop.Outlook._NameSpace ns = null;
//Microsoft.Office.Interop.Outlook.MailItem item = null;
Microsoft.Office.Interop.Outlook.MAPIFolder inboxFolder = null;
app = new Microsoft.Office.Interop.Outlook.Application();
ns = app.GetNamespace("MAPI");
//ns.Logon(null, null, false, false);
inboxFolder = ns.GetDefaultFolder(Microsoft.Office.Interop.Outlook.OlDefaultFolders.olFolderInbox);
// subFolder = inboxFolder.Folders["Inbox"]; //folder.Folders[1]; also works
Console.WriteLine("Folder Name: {0}, EntryId: {1}", inboxFolder.Name, inboxFolder.EntryID);
Console.WriteLine("Num Items: {0}", inboxFolder.Items.Count.ToString());
//System.IO.StreamWriter strm = new System.IO.StreamWriter("C:/Test/Inbox.txt");
for (int counter = 1; counter <= inboxFolder.Items.Count; counter++)
{
Console.Write(inboxFolder.Items.Count + " " + counter);
dynamic item = inboxFolder.Items[counter];
//item = (Microsoft.Office.Interop.Outlook.MailItem)inboxFolder.Items[counter];
Console.WriteLine("Item: {0}", counter.ToString());
Console.WriteLine("Subject: {0}", item.Subject);
Console.WriteLine("Sent: {0} {1}", item.SentOn.ToLongDateString(), item.SentOn.ToLongTimeString());
Console.WriteLine("Sendername: {0}", item.SenderName);
Console.WriteLine("Body: {0}", item.Body);
//strm.WriteLine(counter.ToString() + "," + item.Subject + "," + item.SentOn.ToShortDateString() + "," + item.SenderName);
}
//strm.Close();
}
}
}

If you want only MailItems then you should check that the item you retrieve is a valid MailItem instead of assuming you have one. It could be CalendarItem, DocumentItem, etc. which varies by olItemType. Your current code explicitly assumes you only have MailItems in your inbox.
item = inboxFolder.Items[counter] as Microsoft.Office.Interop.Outlook.MailItem;
if (item != null)
{
....
}
Your error indicates that you may have a MailItem - but it could be a Mail Delivery Report (Read Receipt, etc.). See this post for reference with the casting error. They suggest leveraging the Outlook Table interface as a workaround and checking the object Class. This may be another option for you.

Related

How to fix 'System.OutOfMemoryException' while exporting mail items from Outlook?

I'm trying to build an Windows Forms application for exporting the folder structure of Outlook including the mail items to the hard drive.
private void ExportItems(MAPIFolder folder)
{
Directory.CreateDirectory(ExportPathField.Text + folder.FullFolderPath);
Items items = folder.Items;
if (items.Count > 0)
{
for (int counter = 1; counter <= items.Count; counter++)
{
object item = items[counter];
switch (Microsoft.VisualBasic.Information.TypeName(item))
{
case "MailItem":
MailItem mailitem = item as MailItem;
mailitem.SaveAs(ExportPathField.Text + folder.FullFolderPath + #"\" + mailitem.ReceivedTime.ToOADate() + ".msg");
System.Runtime.InteropServices.Marshal.ReleaseComObject(mailitem);
mailitem = null;
break;
case "MeetingItem":
MeetingItem meetingitem = item as MeetingItem;
meetingitem.SaveAs(ExportPathField.Text + folder.FullFolderPath + #"\" + meetingitem.ReceivedTime.ToOADate() + ".msg");
System.Runtime.InteropServices.Marshal.ReleaseComObject(meetingitem);
meetingitem = null;
break;
default:
break;
}
System.Runtime.InteropServices.Marshal.ReleaseComObject(item);
item = null;
}
}
for(int counter = 1; counter <= folder.Folders.Count; counter++)
{
ExportItems(folder.Folders[counter]);
}
}
This function works properly as long as the content of the Inbox is less than 1GB. If the Inbox exceeds this size, the following error message appears: 'System.OutOfMemoryException'.
All mail items up to here were correctly exported however.
I'm calling the function like this:
Outlook.Application app = new Outlook.Application();
Outlook.NameSpace outlookNs = app.GetNamespace("MAPI");
Outlook.MAPIFolder emailFolder = outlookNs.Folders[POBoxField.Text];
ExportItems(emailFolder);

How do i access an outlook account inbox using c#?

How do i access an outlook account inbox using c#? I've tried using the outlook object model and imap but it only displays the outlook account logged into my machine. I try logging into a different account with its username and password but it still logs into my local machine account. I read that logging out and closing outlook should fix this problem but it didn't change the results
Here is the code
using System;
using System.Reflection;
using Outlook = Microsoft.Office.Interop.Outlook;
namespace ConsoleApplication1
{
public class Class1
{
public static int Main(string[] args)
{
try
{
Outlook.Application oApp = new Outlook.Application();
// Get the MAPI namespace.
Outlook.NameSpace oNS = oApp.GetNamespace("MAPI");
oNS.Logon("email address placeholder", "password placeholder", false, true);
//Get the Inbox folder.
Outlook.MAPIFolder oInbox = oNS.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderInbox);
String user = oNS.CurrentUser.EntryID;
//Get the Items collection in the Inbox folder.
Outlook.Items oItems = oInbox.Items;
Console.WriteLine(oItems.Count);
Outlook.MailItem oMsg = (Outlook.MailItem)oItems.GetFirst();
Console.WriteLine(oMsg.Subject);
Console.WriteLine(oMsg.SenderName);
Console.WriteLine(oMsg.ReceivedTime);
Console.WriteLine(oMsg.Body);
int AttachCnt = oMsg.Attachments.Count;
Console.WriteLine("Attachments: " + AttachCnt.ToString());
if (AttachCnt > 0)
{
for (int i = 1; i <= AttachCnt; i++)
Console.WriteLine(i.ToString() + "-" + oMsg.Attachments[i].DisplayName);
}
for (int i = 0; i < oItems.Count; i++)
{
if (oItems.GetNext() is Outlook.MailItem)
{
oMsg = (Outlook.MailItem)oItems.GetNext();
Console.WriteLine(oMsg.Subject);
Console.WriteLine(oMsg.SenderName);
Console.WriteLine(oMsg.ReceivedTime);
Console.WriteLine(oMsg.Body);
AttachCnt = oMsg.Attachments.Count;
if (AttachCnt > 0)
{
for (int j = 1; j <= AttachCnt; j++)
Console.WriteLine(j.ToString() + "-" + oMsg.Attachments[j].DisplayName);
}
Console.WriteLine("Attachments: " + AttachCnt.ToString());
Console.WriteLine("CURRENT EMAIL # IS: " + i);
}
else
{
oItems.GetNext();
Console.WriteLine("NOT AN EMAIL");
Console.WriteLine("CURRENT EMAIL # IS: " + i);
}
}
oNS.Logoff();
oMsg = null;
oItems = null;
oInbox = null;
oNS = null;
oApp = null;
}
catch (Exception e)
{
Console.WriteLine("{0} Exception caught: ", e);
}
return 0;
}
}
}
You can try using this code:
public List<Outlook.MailItem> GetMails()
{
Microsoft,Office.Interop.Outlook.NameSpace nameSpace = OutLookName.Application.GetNameSpace("MAPI");
nameSpace.Logon("","",System.Reflection.Missing.Value,System.Reflection.Missing.Value);
Microsoft.Office.Interop.Outlook.MAPIFolder inboxFolder = nameSpace.GetDefaultFolder(Microsoft.Office.Interop.Outlook.OlDefaultFolders.olFolderInbox);
List<Outlook.MailItem> eMails = new List<Outlook.MailItem>();
foreach(Microsoft.Office.Interop.Outlook.MailItem mailItem in inboxFolder.Items)
{
if(mailItem.UnRead)
eMails.Add(mailItem);
}
return eMails;
}

Retrieve Public Outlook Calendar Appointments?

I am trying to retrieve the appointments for the same day from any given user's name.
So far, I am able to retrieve my own appointments for today with the code below.
else if (UserSelection == "2")
{
//Create the Outlook application
Outlook.Application oApplication = new Outlook.Application();
// Get the NameSpace and Logon information.
Outlook.NameSpace oNameSpace = oApplication.GetNamespace("mapi");
//Log on by using a dialog box to choose the profile.
oNameSpace.Logon(Missing.Value, Missing.Value, true, true);
// Get the Calendar folder.
Outlook.MAPIFolder oCalendar = oNameSpace.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderCalendar);
// Get the appointments (items) collection from the Calendar folder.
Outlook.Items oItems = oCalendar.Items;
oItems.IncludeRecurrences = true;
List<Outlook.AppointmentItem> lst = new List<Outlook.AppointmentItem>();
foreach (Outlook.AppointmentItem item in oItems)
{
if (item.Start.Day == DateTime.Today.Day && item.Start.Month == DateTime.Today.Month && item.Start.Year == DateTime.Today.Year)
{
Console.WriteLine("Organizer: " + item.Organizer);
Console.WriteLine("Start: " + item.Start.ToString());
Console.WriteLine("End: " + item.End.ToString());
Console.WriteLine("Location: " + item.Location);
Console.WriteLine("Recurring: " + item.IsRecurring);
Console.WriteLine("Subject: " + item.Subject);
Console.WriteLine("Attendees: " + item.OptionalAttendees);
Console.WriteLine("");
}
}
//Get the last appointment(item)
//Outlook.AppointmentItem oAppt = (Outlook.AppointmentItem)oItems.GetLast();
//Show the appointment(item) in outlook.
//oAppt.Display(true);
// Done. Log off.
oNameSpace.Logoff();
//Clean up.
oItems = null;
oCalendar = null;
oNameSpace = null;
oApplication = null;
Console.ReadLine();
This works fine. However, the following code below doesnt return the given user "userName"'s appointments.
if (UserSelection == "1")
//try (used for error handling)
{
string userName = Console.ReadLine();
Outlook.Application oApplication;
oApplication = new Outlook.Application();
Outlook.NameSpace oNameSpace = oApplication.GetNamespace("mapi");
oNameSpace.Logon(Missing.Value, Missing.Value, true, true);
Outlook.Recipient oRecip = (Outlook.Recipient)oNameSpace.CreateRecipient(userName);
Outlook.MAPIFolder oCalendar = (Outlook.MAPIFolder)oNameSpace.GetSharedDefaultFolder(oRecip, Outlook.OlDefaultFolders.olFolderCalendar);
// Get the appointments (items) collection from the Calendar folder.
Outlook.Items oItems = oCalendar.Items;
oItems.IncludeRecurrences = true;
List<Outlook.AppointmentItem> lst = new List<Outlook.AppointmentItem>();
foreach (Outlook.AppointmentItem item in oItems)
{
if (item.Start.Day == DateTime.Today.Day && item.Start.Month == DateTime.Today.Month && item.Start.Year == DateTime.Today.Year)
{
Console.WriteLine("Organizer: " + item.Organizer);
Console.WriteLine("Start: " + item.Start.ToString());
Console.WriteLine("End: " + item.End.ToString());
Console.WriteLine("Location: " + item.Location);
Console.WriteLine("Recurring: " + item.IsRecurring);
Console.WriteLine("Subject: " + item.Subject);
Console.WriteLine("Attendees: " + item.OptionalAttendees);
Console.WriteLine("");
}
}
//Show the appointment(item) in outlook.
//oAppt.Display(true);
// Done. Log off.
oNameSpace.Logoff();
// Clean up.
oItems = null;
oCalendar = null;
oNameSpace = null;
oApplication = null;
Console.ReadLine();
The code line producing the error is foreach (Outlook.AppointmentItem item in oItems)
The error returned is "An unhandled exception of type 'System.Runtime.InteropServices.COMException' occurred in mscorlib.dll
Additional information: Exception from HRESULT: 0x8834010F"
Any help to make this work would be greatly appreciated, thanks.
I'd suggest starting from releasing 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. See Systematically Releasing Objects for more information.
Also I'd suggest using the Find/FindNext or Restrict methods of the Items class. You can read more about them in the following articles:
How To: Retrieve Outlook calendar items using Find and FindNext methods
How To: Use Restrict method in Outlook to get calendar items

How do I parse ms outlook 2003 email body for a string i.e. keyword 'error'

I am trying to figure out how to parse ms outlook 2003 email body for a string using C# eg: read all the email in certain folder and search the email body for the word "error" in these emails.
Once this string error is found in the email body I would like to display the email and the error message.
I have the following code so far which basically just reads all the emails in the folder and displays all the information about the emails.
The issue I am having is actually trying to read into the mail item body in each individual email so I can search for the string.
I have been searching quite a while for this on web and have found code very similar to what I have below but none which shows you or if it is possible to read a folder containing emails, read through individual each email and search for the string 'errors', if this keyword is found in the email display the details from email i.e email subject, error message etc.
Any help would be much appreciated.
Thanks a million.
John.
using System;
using System.Reflection;
using Outlook = Microsoft.Office.Interop.Outlook;
namespace AccessOutlook
{
public class Class1
{
public static void Main(string[] args)
{
Microsoft.Office.Interop.Outlook.Application app = null;
Microsoft.Office.Interop.Outlook._NameSpace ns = null;
Microsoft.Office.Interop.Outlook.MailItem item = null;
Microsoft.Office.Interop.Outlook.MAPIFolder inboxFolder = null;
Microsoft.Office.Interop.Outlook.MAPIFolder subFolder = null;
try
{
app = new Microsoft.Office.Interop.Outlook.Application();
ns = app.GetNamespace("MAPI");
ns.Logon(null,null,false, false);
inboxFolder = ns.GetDefaultFolder
(Microsoft.Office.Interop.Outlook.OlDefaultFolders.olFolderInbox);
subFolder = inboxFolder.Folders["Docs"];
Console.WriteLine("Folder Name: {0}, EntryId: {1}", subFolder.Name,
subFolder.EntryID);
Console.WriteLine("Num Items: {0}",
subFolder.Items.Count.ToString());
for(int i=1;i<=subFolder.Items.Count;i++)
{
item =
(Microsoft.Office.Interop.Outlook.MailItem)subFolder.Items[i];
Console.WriteLine("Item: {0}", i.ToString());
Console.WriteLine("Subject: {0}", item.Subject);
Console.WriteLine("Sent: {0} {1}",
item.SentOn.ToLongDateString(), item.SentOn.ToLongTimeString());
Console.WriteLine("Categories: {0}", item.Categories);
Console.WriteLine("Body: {0}", item.Body);
Console.WriteLine("HTMLBody: {0}", item.HTMLBody);
}
}
catch (System.Runtime.InteropServices.COMException ex)
{
Console.WriteLine(ex.ToString());
}
finally
{
ns = null;
app = null;
inboxFolder = null;
}
}
}
}
How about this:
for(int i=1;i<=subFolder.Items.Count;i++)
{
item = (Microsoft.Office.Interop.Outlook.MailItem)subFolder.Items[i];
if(item.Body.Contains("errors"))
{
Console.WriteLine("Item: {0}", i.ToString());
Console.WriteLine("Subject: {0}", item.Subject);
Console.WriteLine("Sent: {0} {1}",
item.SentOn.ToLongDateString(), item.SentOn.ToLongTimeString());
Console.WriteLine("Categories: {0}", item.Categories);
Console.WriteLine("Body: {0}", item.Body);
Console.WriteLine("HTMLBody: {0}", item.HTMLBody);
}
}

Error while reading inbox items from outlook using C#

HI
When i am trying to read data from inbox of outlook , i am getting the below error
Unable to cast COM object of type 'System.__ComObject' to interface type 'Microsoft.Office.Interop.Outlook.PostItem'. This operation failed because the QueryInterface call on the COM component for the interface with IID '{00063024-0000-0000-C000-000000000046}' failed due to the following error: No such interface supported (Exception from HRESULT: 0x80004002 (E_NOINTERFACE)).
Below is my C# code
Microsoft.Office.Interop.Outlook.Application app = null;
Microsoft.Office.Interop.Outlook._NameSpace ns = null;
Microsoft.Office.Interop.Outlook.PostItem item = null;
Microsoft.Office.Interop.Outlook.MAPIFolder inboxFolder = null;
Microsoft.Office.Interop.Outlook.MAPIFolder subFolder = null;
try
{
app = new Microsoft.Office.Interop.Outlook.Application();
ns = app.GetNamespace("MAPI");
ns.Logon(null,null,false, false);
inboxFolder = ns.GetDefaultFolder(Microsoft.Office.Interop.Outlook.OlDefaultFolders.olFolderInbox);
Console.WriteLine("Folder Name: {0}, EntryId: {1}", inboxFolder.Name, inboxFolder.EntryID);
Console.WriteLine("Num Items: {0}", inboxFolder.Items.Count.ToString());
Console.ReadLine();
for (int i = 1; i <= inboxFolder.Items.Count; i++)
{
item = (Microsoft.Office.Interop.Outlook.PostItem)inboxFolder.Items[i];
Console.WriteLine("Item: {0}", i.ToString());
Console.WriteLine("Subject: {0}", item.Subject);
Console.WriteLine("Categories: {0}", item.Categories);
Console.WriteLine("Body: {0}", item.Body);
Console.WriteLine("HTMLBody: {0}", item.HTMLBody);
}
}
catch (System.Runtime.InteropServices.COMException ex)
{
Console.WriteLine(ex.ToString());
}
finally
{
ns = null;
app = null;
inboxFolder = null;
}
Thanks in Advance
item = (Microsoft.Office.Interop.Outlook.PostItem)inboxFolder.Items[i];
Console.WriteLine("Item: {0}", i.ToString());
Console.WriteLine("Subject: {0}", item.Subject);
Console.WriteLine("Categories: {0}", item.Categories);
Console.WriteLine("Body: {0}", item.Body);
Console.WriteLine("HTMLBody: {0}", item.HTMLBody);
Change this part as
Microsoft.Office.Interop.Outlook.MailItem item = (Microsoft.Office.Interop.Outlook.MailItem)subFolder.Items[i];
Console.WriteLine( "Item: {0}", i.ToString() );
Console.WriteLine( "Subject: {0}", item.Subject );
Console.WriteLine( "Categories: {0}", item.Categories );
Console.WriteLine( "Body: {0}", item.Body );
Console.WriteLine( "HTMLBody: {0}", item.HTMLBody );
further refer
http://www.dotnetspider.com/forum/160348-how-read-items-from-outlook-inbox-subfolders-C-NET.aspx

Categories

Resources