Solved

Outlook automation in C#

Posted on 2004-04-13
36
1,724 Views
Last Modified: 2008-12-19
I need a jumpstart getting Outlook automation working under C#:

Here are the requirements:

1)  I need to be able to navigate to a specific folder in Outlook
2)  Once I am in this folder, I need to programmatically loop through the e-mails in the folder.
3)  Inside the loop, I need to open each e-mail and read the message body into a C# string variable.
4)  Then I want to parse the string variable (containing the e-mail message body) and look for certain phrases.

#4 I can do, but 1 thru 3 I'd like some sample code.

Please only respond if you are pretty experienced in Outlook Automation and can provide working code in C# only.

My Sincere Thanks,


Tom
0
Comment
Question by:knowlton
  • 21
  • 15
36 Comments
 
LVL 8

Expert Comment

by:RomanPetrenko
ID: 10816930
Take a look here:

.NET Connector for Microsoft Outlook
http://www.codeproject.com/csharp/OutlookConnector.asp

Here you can find good list of How-To's about programming outlook in VS.NET
http://www.microeye.com/resources/res_tech_vsnet.htm

Later I'll give you sample for Outlook 2003(Only this version I have), But I think you can get  some information from links I posted above...
0
 
LVL 5

Author Comment

by:knowlton
ID: 10816960
I've been to both sites and they are not *quite* what I am looking for.

For example, they always seem to navigate to default folders that Outlook provides, using constants.

I need to know how to navigate to a folder that Outlook does not provide.....one that I created myself.
0
 
LVL 5

Author Comment

by:knowlton
ID: 10817140
Roman:

I look forward to seeing your sample code.

Here is what I have so far, plus pseudocode describing what I want to accomplish:

private void ProcessFailures()
            {

                  Outlook.Application oApp;
                  Outlook._NameSpace oNameSpace;
                  Outlook.MAPIFolder oFolder;

                  oApp = new Outlook.ApplicationClass();
                  oNameSpace = oApp.GetNamespace("MAPI");
                  oNameSpace.Logon(null,null,true,true);

                  oFolder.MoveTo("FaxSuccess");  //navigate to custom folder??????

//loop through folder contents
//assign message body to a C# string variable
//parse string variable looking for certain tokens






                  //objOutlook.Explorers objOutlookExplorer = objOutlook.Explorers.Add(objOutlook.ActiveExplorer
                  
            }
0
 
LVL 5

Author Comment

by:knowlton
ID: 10817513
Inside OnStart just before call to ProcessFailures
Inside ProcessFailures beginning of Try
Exception thrown inside function ProcessFailures.  Message:  Could not complete the operation because the service provider does not support it.::StackTrace:     at Outlook.NameSpaceClass.get_Folders()
   at WindowsServiceTrackRequestProgress.ServiceTrackRequestProgress.ProcessFailures() in n:\clientdevelopment\neo\buyersfund\windowsservicetrackrequestprogress\servicetrackrequestprogress.cs:line 101
etrackrequestprogress\servicetrackrequestprogress.cs:line 99

How can it not be supported?
0
 
LVL 8

Expert Comment

by:RomanPetrenko
ID: 10822840
Here is the sample:

private Outlook.MAPIFolder GotoFolder(Outlook.MAPIFolder fldr, string FolderName)
{
if (fldr == null ) return null;
if (fldr.Name == FolderName) return fldr;
foreach( Outlook.MAPIFolder folder in fldr.Folders)
{
      if (folder.DefaultItemType != Outlook.OlItemType.olMailItem)
            continue;
      if (folder.Name == FolderName)
            return folder;
      Outlook.MAPIFolder f = GotoFolder(folder,FolderName);
      if (f != null)
            return f;
}
return null;
}

private void button1_Click(object sender, System.EventArgs e)
{
string FolderName = "Anekdots";//<=== Folder name you want to open.
oApp = new Outlook.ApplicationClass();
oNamespace = oApp.GetNamespace("MAPI");
oNamespace.Logon(null,null,true,true);
Outlook.MAPIFolder fldr = GotoFolder(oNamespace.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderInbox) ,FolderName);<-- if you have more than one account,get corresponding folder from oNamespace.Folders collection
if (fldr == null)
      MessageBox.Show("Folder Not Found");
if (fldr.DefaultItemType != Outlook.OlItemType.olMailItem )
      MessageBox.Show("Can't work with non-Mail Items");
foreach(Outlook.MailItem mitem in fldr.Items)
{
      string forParsing = mitem.Body; <<=== Here if you running this code from external application you'll get outlook warning "Another program tying to access ... bla-bla-bla... Allow access for 1(2)(5) minute(s)?". You will not recieve this message if you are running in Outlook addin or outlook custom form code.
      //<write here parsing code>
}
}
0
 
LVL 5

Author Comment

by:knowlton
ID: 10824621
Roman:

Getting a bunch of errors with your sample code.  Can you please help me debug?

http://www.knowltonfamily.com/a.gif


Here are the errors:

N:\ClientDevelopment\NEO\BuyersFund\WindowsServiceTrackRequestProgress\ServiceTrackRequestProgress.cs(126): foreach statement cannot operate on variables of type 'Outlook.Items' because 'Outlook.Items' does not contain a definition for 'GetEnumerator', or it is inaccessible
N:\ClientDevelopment\NEO\BuyersFund\WindowsServiceTrackRequestProgress\ServiceTrackRequestProgress.cs(93): foreach statement cannot operate on variables of type 'Outlook.Folders' because 'Outlook.Folders' does not contain a definition for 'GetEnumerator', or it is inaccessible
N:\ClientDevelopment\NEO\BuyersFund\WindowsServiceTrackRequestProgress\ServiceTrackRequestProgress.cs(110): The name 'oApp' does not exist in the class or namespace 'WindowsServiceTrackRequestProgress.ServiceTrackRequestProgress'
N:\ClientDevelopment\NEO\BuyersFund\WindowsServiceTrackRequestProgress\ServiceTrackRequestProgress.cs(111): The name 'oNamespace' does not exist in the class or namespace 'WindowsServiceTrackRequestProgress.ServiceTrackRequestProgress'
N:\ClientDevelopment\NEO\BuyersFund\WindowsServiceTrackRequestProgress\ServiceTrackRequestProgress.cs(112): The type or namespace name 'oNamespace' could not be found (are you missing a using directive or an assembly reference?)
N:\ClientDevelopment\NEO\BuyersFund\WindowsServiceTrackRequestProgress\ServiceTrackRequestProgress.cs(114): The type or namespace name 'oNamespace' could not be found (are you missing a using directive or an assembly reference?)
N:\ClientDevelopment\NEO\BuyersFund\WindowsServiceTrackRequestProgress\ServiceTrackRequestProgress.cs(117): The type or namespace name 'MessageBox' could not be found (are you missing a using directive or an assembly reference?)
N:\ClientDevelopment\NEO\BuyersFund\WindowsServiceTrackRequestProgress\ServiceTrackRequestProgress.cs(122): The type or namespace name 'MessageBox' could not be found (are you missing a using directive or an assembly reference?)
0
 
LVL 5

Author Comment

by:knowlton
ID: 10824637
Sorry, the screenshot is:

http://www.knowltonfamily.com/b.gif
0
 
LVL 5

Author Comment

by:knowlton
ID: 10824782
UPDATE:

Roman, I have taken the errors down to just 2 errors:


http://www.knowltonfamily.com/c.gif


Some problem with the foreach statement:

N:\ClientDevelopment\NEO\BuyersFund\WindowsServiceTrackRequestProgress\ServiceTrackRequestProgress.cs(93): foreach statement cannot operate on variables of type 'Outlook.Folders' because 'Outlook.Folders' does not contain a definition for 'GetEnumerator', or it is inaccessible
N:\ClientDevelopment\NEO\BuyersFund\WindowsServiceTrackRequestProgress\ServiceTrackRequestProgress.cs(130): foreach statement cannot operate on variables of type 'Outlook.Items' because 'Outlook.Items' does not contain a definition for 'GetEnumerator', or it is inaccessible




Here is my updated source code for the Windows Service:


using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.ServiceProcess;

namespace WindowsServiceTrackRequestProgress
{
      public class ServiceTrackRequestProgress : System.ServiceProcess.ServiceBase
      {
            /// <summary>
            /// Required designer variable.
            /// </summary>
            private System.ComponentModel.Container components = null;
            private System.Timers.Timer timerCheckFaxStatus;

            public BuyersFund.GatherMessages.GatherMessages gmMessage = new BuyersFund.GatherMessages.GatherMessages();

            public ServiceTrackRequestProgress()
            {
                  // This call is required by the Windows.Forms Component Designer.
                  InitializeComponent();

                  // TODO: Add any initialization after the InitComponent call
            }

            // The main entry point for the process
            static void Main()
            {
                  System.ServiceProcess.ServiceBase[] ServicesToRun;
      
                  // More than one user Service may run within the same process. To add
                  // another service to this process, change the following line to
                  // create a second service object. For example,
                  //
                  //   ServicesToRun = New System.ServiceProcess.ServiceBase[] {new Service1(), new MySecondUserService()};
                  //
                  ServicesToRun = new System.ServiceProcess.ServiceBase[] { new ServiceTrackRequestProgress() };

                  System.ServiceProcess.ServiceBase.Run(ServicesToRun);
            }

            /// <summary>
            /// Required method for Designer support - do not modify
            /// the contents of this method with the code editor.
            /// </summary>
            private void InitializeComponent()
            {
                  this.timerCheckFaxStatus = new System.Timers.Timer();
                  ((System.ComponentModel.ISupportInitialize)(this.timerCheckFaxStatus)).BeginInit();
                  //
                  // timerCheckFaxStatus
                  //
                  this.timerCheckFaxStatus.Interval = 5000;
                  this.timerCheckFaxStatus.Elapsed += new System.Timers.ElapsedEventHandler(this.timerCheckFaxStatus_Elapsed);
                  //
                  // ServiceTrackRequestProgress
                  //
                  this.ServiceName = "Service1";
                  ((System.ComponentModel.ISupportInitialize)(this.timerCheckFaxStatus)).EndInit();

            }

            /// <summary>
            /// Clean up any resources being used.
            /// </summary>
            protected override void Dispose( bool disposing )
            {
                  if( disposing )
                  {
                        if (components != null)
                        {
                              components.Dispose();
                        }
                  }
                  base.Dispose( disposing );
            }

            /// <summary>
            /// Set things in motion so your service can do its work.
            /// </summary>
            protected override void OnStart(string[] args)
            {
                  // TODO: Add code here to start your service.
                  this.timerCheckFaxStatus.Enabled=true;
            }

            private Outlook.MAPIFolder GotoFolder(Outlook.MAPIFolder fldr, string FolderName)
            {
                  if (fldr == null ) return null;
                  if (fldr.Name == FolderName) return fldr;
                  foreach(Outlook.MAPIFolder folder in fldr.Folders)
                  {
                        if (folder.DefaultItemType != Outlook.OlItemType.olMailItem)
                              continue;
                        if (folder.Name == FolderName)
                              return folder;
                        Outlook.MAPIFolder f = GotoFolder(folder,FolderName);
                        if (f != null)
                              return f;
                  }
                  return null;
            }


            private void ProcessFailures()
            {
                  string FolderName = "Anekdots";//<=== Folder name you want to open.

                  Outlook.Application oApp;
                  Outlook.NameSpace oNamespace;

                  oApp = new Outlook.ApplicationClass();
                  oNamespace = oApp.GetNamespace("MAPI");
                  oNamespace.Logon(null,null,true,true);
                  //if you have more than one account,get corresponding folder from oNamespace.Folders collection
                  Outlook.MAPIFolder fldr = GotoFolder(oNamespace.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderInbox) ,FolderName);
                  if (fldr == null)
                  {
                        gmMessage.AddMessage("IT","Folder Not Found");
                  }

                  if (fldr.DefaultItemType != Outlook.OlItemType.olMailItem )
                  {                        
                        gmMessage.AddMessage("IT","Can't work with non-Mail Items");
                  }


                  foreach(Outlook.MailItem mitem in fldr.Items)
                  {
                        //Here if you running this code from external application you'll get outlook warning "Another program tying to access ... bla-bla-bla... Allow access for 1(2)(5) minute(s)?". You will not recieve this message if you are running in Outlook addin or outlook custom form code.
                        string forParsing = mitem.Body;
                        //<write here parsing code>
                  }
            }

            private void ProcessSuccesses()
            {
            }

            /// <summary>
            /// Stop this service.
            /// </summary>
            protected override void OnStop()
            {
                  // TODO: Add code here to perform any tear-down necessary to stop your service.
            }

            private void timerCheckFaxStatus_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
            {                  
                  try
                  {
                        gmMessage.AddMessage("IT","Inside OnStart just before call to ProcessFailures");
                        ProcessFailures();
                        gmMessage.AddMessage("IT","Inside OnStart just after call to ProcessFailures");
                  }
                  catch(Exception ee)
                  {
                        gmMessage.AddMessage("IT","Exception thrown inside function OnStart.  Message:  " + ee.Message + "::StackTrace:  " + ee.StackTrace);
                        gmMessage.WriteMessagesOutToFile("IT","C:\\faxprogressFAILURE.txt");
                  }            
            }
      }
}

0
 
LVL 5

Author Comment

by:knowlton
ID: 10825076
0
 
LVL 8

Expert Comment

by:RomanPetrenko
ID: 10825869
0
 
LVL 5

Author Comment

by:knowlton
ID: 10826056
I looked at your answer.

It is looking like I am using the wrong code....based on the other posts you have made in my other questions.

Like I said in my other post, I am using Outlook 2000 and VS .NET 2002.
0
 
LVL 8

Expert Comment

by:RomanPetrenko
ID: 10826438
As I said in my first post I gave you sample for outlook 2003, but you can work with it
just change foreach statements:
for(Outlook.MAPIFolder folder = fldr.Folders.GetFirst();folder != null; folder = fldr.Folders.GetNext())
instead of
foreach(Outlook.MAPIFolder folder in fldr.Folders) in GotoFolders
and
for(Outlook.MailItem mitem = fldr.Items.GetFirst();mitem != null; mitem = fldr.Items.GetNext())
instead of
foreach(Outlook.MailItem mitem in fldr.Items)

that's all,

PS: Sorry, I can't check this code, I'm already at home. Try to check this code I'll be waiting for your answers.
0
 
LVL 5

Author Comment

by:knowlton
ID: 10826465
Roman:

You code does not work under VS .NET 2002.....even after converting the foreach statements over to just for loops.
0
 
LVL 8

Expert Comment

by:RomanPetrenko
ID: 10826473
What errors you get?
0
 
LVL 5

Author Comment

by:knowlton
ID: 10826499
Now I am getting:

Inside OnStart just before call to ProcessFailures
Exception thrown inside function OnStart.  Message:  Could not complete the operation because the service provider does not support it.::StackTrace:     at Outlook.NameSpaceClass.GetDefaultFolder(OlDefaultFolders FolderType)
   at WindowsServiceTrackRequestProgress.ServiceTrackRequestProgress.ProcessFailures() in n:\clientdevelopment\neo\buyersfund\windowsservicetrackrequestprogress\servicetrackrequestprogress.cs:line 120
   at WindowsServiceTrackRequestProgress.ServiceTrackRequestProgress.timerCheckFaxStatus_Elapsed(Object sender, ElapsedEventArgs e) in n:\clientdevelopment\neo\buyersfund\windowsservicetrackrequestprogress\servicetrackrequestprogress.cs:line 166
ckrequestprogress.cs:line 166


Here is line 120:

     Outlook.MAPIFolder fldr = GotoFolder(oNamespace.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderInbox) ,FolderName);


Here is line 166:

      ProcessFailures();
0
 
LVL 8

Expert Comment

by:RomanPetrenko
ID: 10826518
and what mail server you connected to?
0
 
LVL 5

Author Comment

by:knowlton
ID: 10826528
Exchange with an Outlook client.
0
 
LVL 8

Expert Comment

by:RomanPetrenko
ID: 10826555
1. try to install .Net ver 1.1 from here:
http://www.microsoft.com/downloads/details.aspx?FamilyId=262D25E3-F589-4842-8157-034D1E7CF3A3&displaylang=en
2. Try to check if you're logged in correctly.(May be open Outlook and after that start your program)
What results do you got?
0
Do You Know the 4 Main Threat Actor Types?

Do you know the main threat actor types? Most attackers fall into one of four categories, each with their own favored tactics, techniques, and procedures.

 
LVL 8

Expert Comment

by:RomanPetrenko
ID: 10826614
Take a look here:
http://support.microsoft.com/?kbid=329554
It's exactly your problem, am I right? You have to install hotfix...
0
 
LVL 5

Author Comment

by:knowlton
ID: 10826672
The error message is very close to what I have been getting in VS .NET.......but the cause of the error message seems specific to another problem???????
0
 
LVL 5

Author Comment

by:knowlton
ID: 10826688
If you read carefully the solution page says:

RESOLUTION
A supported fix is now available from Microsoft, but it is only intended to correct the problem that is described in this article. Apply it only to computers that are experiencing this specific problem.


My question is....is the article describing my problem?
0
 
LVL 8

Expert Comment

by:RomanPetrenko
ID: 10826698
But you use API, that they use for reply... so they will not write "When you access Folders property..." they gives sample that every one can understand...
0
 
LVL 5

Author Comment

by:knowlton
ID: 10826708
Okay.  :)
0
 
LVL 8

Expert Comment

by:RomanPetrenko
ID: 10826717
I think this is exactly your problem, try to install hofix.
BTW: They wrote such resolution for each Hotfix they posts, it's politics. And also they include the hotfix into future SP so from this time it's for everyone, strange ?! :)
0
 
LVL 5

Author Comment

by:knowlton
ID: 10826730
Roman:  Good point.  If they are putting the fix in the SP then it is most likely "Okay" for me to apply the hotfix.

Tom
0
 
LVL 5

Author Comment

by:knowlton
ID: 10826737
What is the easiest way to determine what SP my Outlook 2000 is using right now?
0
 
LVL 8

Expert Comment

by:RomanPetrenko
ID: 10826738
But read carefully this article, you should have SP3 installed befor you install hotfix. It's post-SP3.
0
 
LVL 5

Author Comment

by:knowlton
ID: 10826756
I am looking for SP3  (I assume it includes   SP1   and SP2    as well?  )
0
 
LVL 8

Expert Comment

by:RomanPetrenko
ID: 10826761
run Office update:
http://office.microsoft.com/OfficeUpdate/default.aspx it will tell you what you need to install
0
 
LVL 5

Author Comment

by:knowlton
ID: 10827429
Roman:

I just finished installing all of the pending Windows Crititcal Updates.

My code compiles and builds the .EXE just fine, but when I run the Windows Service I get an error file that says:

Inside OnStart just before call to ProcessFailures
Exception thrown inside function OnStart.  Message:  Could not complete the operation because the service provider does not support it.::StackTrace:     at Outlook.NameSpaceClass.GetDefaultFolder(OlDefaultFolders FolderType)
   at WindowsServiceTrackRequestProgress.ServiceTrackRequestProgress.ProcessFailures() in n:\clientdevelopment\neo\buyersfund\windowsservicetrackrequestprogress\servicetrackrequestprogress.cs:line 121
   at WindowsServiceTrackRequestProgress.ServiceTrackRequestProgress.timerCheckFaxStatus_Elapsed(Object sender, ElapsedEventArgs e) in n:\clientdevelopment\neo\buyersfund\windowsservicetrackrequestprogress\servicetrackrequestprogress.cs:line 168
ckrequestprogress.cs:line 166



0
 
LVL 8

Expert Comment

by:RomanPetrenko
ID: 10830433
I think you have problem with Window Service security, What account do you use to run the service?
If you run this code not as service but as windows application - it works?
0
 
LVL 8

Accepted Solution

by:
RomanPetrenko earned 500 total points
ID: 10830719
Look here:
INFO: Outlook Object Model Unsuitable to Run in a Windows Service
http://support.microsoft.com/default.aspx?scid=http://support.microsoft.com:80/support/kb/articles/q237/9/13.asp&NoWebContent=1

so you can't use outlook in Windows Service. and, I think, the sample I gave you should work in windows application.
0
 
LVL 5

Author Comment

by:knowlton
ID: 10834220
Roman:

Agreed.....does not look like Outlook automation would work in a Windows Service.

BUT

What about Exchange Event Sinks?
0
 
LVL 8

Expert Comment

by:RomanPetrenko
ID: 10836656
I think they should work, It's COM+, but I've never used them...
0
 
LVL 5

Author Comment

by:knowlton
ID: 11120018
UPDATE:

Well, guess what?

I finally had a major breakthrough on this @!#$^% problem that has been driving me crazy for the last few weeks!!!!!!!


It is a very small change.

Apparently the method   MoveFirst(   ) does not work so well with Exchange.

This was the cause of my COMException:   "Interface not registered" error message this entire time.


The solution is to use    Move(1,0)     instead of MoveFirst(  ).


That's it.   Simple.

This answer came courtesy of Tom Rizzo, an author who was kind enough to correspond with me and help me figure-out finally what the problem was.:

Looking for a good book on programming Exchange, Outlook, ADSI and
SharePoint?  Check out http://www.microsoft.com/MSPress/books/5517.asp

My I also reommend:

.NET and COM: The Complete Interoperability Guide  ISBN:067232170X
http://www.amazon.ca/exec/obidos/ASIN/067232170X/componentsnot-20/701-9386310-4703553
0
 
LVL 5

Author Comment

by:knowlton
ID: 11120315
More on the MoveFirst problem I described:

http://support.microsoft.com/default.aspx?scid=kb;en-us;273791


If you are getting into Event Sinks....I recommend the following tutorial:

http://www.codeproject.com/csharp/CsManagedEventSinksHooks.asp

Make sure and read the article questions and follow-ups at the bottom!

There are a few caveats.  E-mail me at my Profile e-mail address and we can talk about them.  :)
0

Featured Post

How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

Join & Write a Comment

Bit flags and bit flag manipulation is perhaps one of the most underrated strategies in programming, likely because most programmers developing in high-level languages rely too much on the high-level features, and forget about the low-level ones. Th…
Real-time is more about the business, not the technology. In day-to-day life, to make real-time decisions like buying or investing, business needs the latest information(e.g. Gold Rate/Stock Rate). Unlike traditional days, you need not wait for a fe…
Sending a Secure fax is easy with eFax Corporate (http://www.enterprise.efax.com). First, Just open a new email message.  In the To field, type your recipient's fax number @efaxsend.com. You can even send a secure international fax — just include t…
This demo shows you how to set up the containerized NetScaler CPX with NetScaler Management and Analytics System in a non-routable Mesos/Marathon environment for use with Micro-Services applications.

743 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

15 Experts available now in Live!

Get 1:1 Help Now