Solved

Outlook plug-in Save Email to hard drive

Posted on 2006-06-13
10
372 Views
Last Modified: 2008-03-10
Very important to my company.  I need to have a plug-in that saves a specific outgoing email based on recipient to a text file on the hard drive before it is sent.  It could be saved while it is being sent also.

What would be great if I can also get an example of the same but for incoming from a certain recipient.  I would like code instead of using the Rules Wizard.  I'm using POP and not Exchange.
0
Comment
Question by:famoso
  • 5
  • 4
10 Comments
 
LVL 14

Expert Comment

by:existenz2
ID: 16894273
You could use VSTO (Visual Studio Tools for Office) or Information Worker to solve your problem. If you are using Office 2003 a final solution would be creating an application which uses the .NET Office 2003 library (Default installed with Office 2003 Prof.), but I would suggest VSTO or IW.
0
 
LVL 2

Expert Comment

by:bdsmithback
ID: 16900015
You're probably going to want to create an add-in for Outlook.  

Here's a place to start with Office Add-ins: http://support.microsoft.com/?kbid=302901

Here's some specific information on Oultook: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dv_vstechart/html/ol03csharp.asp

Once you have an add-in for Outlook, the code is pretty straightforward.  Capture the ItemSend event in the Application class and save the messages.  Here's an incomplete example - but it should get the job done.

void Connect_ItemSend(object Item, ref bool Cancel)
{
      try
      {
            ((Outlook.MailItem)Item).SaveAs("c:\\somepath\\somefile.msg", (object)Outlook.OlSaveAsType.olMSG);
      }
      catch { }
}

One final thought.  If this is going to be distributed to a lot of people - you may want to consider using a shim for your COM addin.  Office doesn't play well with managed code and a shim can help with that.

Good luck!

0
 

Author Comment

by:famoso
ID: 16901644
I just found what I was looking for ... almost.  The problem is I don't want the code exposed if an error appears and also it should be easily maintained (as in one DLL) so I can make just one change and not many changes if for example I need the email changed to something else.

-------------------------------------------------------------------------------
Private Sub Application_ItemSend(ByVal Item As Object, Cancel As Boolean)
On Error GoTo End_Application_ItemSend

If Item.Recipients(1).Address = "email@email.com" Then
Open "c:\system.txt" For Append As #1
    Print #1, Now
    Print #1, "Subject: " & Item.Subject
    Print #1, "Body: " & Item.Body
Close #1
End If

End_Application_ItemSend:
Exit Sub

End Sub
-------------------------------------------------------------------------------

The problem is I want the business part to be in a DLL and referenced something like:

Private Sub Application_ItemSend(ByVal Item As Object, Cancel As Boolean)
On Error GoTo End_Application_ItemSend

    dim x as object
    x=createobject("somedll.dll")  ' The DLL can be in VB or C# but probably a COM, right?
    x.somefunction(Item)

End_Application_ItemSend:
Exit Sub

End Sub

Is a plug-in still what I want?  I don't want a menu added to the Outlook IDE I just want my 'DLL' to run when this event is fired.
0
 

Author Comment

by:famoso
ID: 16901655
BTW I'm using Outlook 2000
0
 
LVL 2

Expert Comment

by:bdsmithback
ID: 16902650
It's arguable - but I still think a plugin is the way to go.  In Outlook 2002 and up, the Outlook Object Model is protected from programs doing what you're trying to do.  When you capture the ItemSend event from an application running outside of outlook, it pops up a security warning stating that a program is trying to access your e-mail.  If you plan on ever upgrading to 2002 or 2003, a plugin is probably the best way to go.

The other issue is that you will attach to an instance of Oulook.  If that instance is closed and a new one reopened, your event is no going to fire.  There are ways around this, but a plugin solves the problem because it launches with each instance of Outlook.  

From there, you can load an external assembly so it's easy to change.  Here is some info on doing that: http://msdn2.microsoft.com/en-us/library/ky3942xh.aspx

Cheers,
Beau
0
Highfive Gives IT Their Time Back

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

 

Author Comment

by:famoso
ID: 16903772
Can I still, through a plug-in, hijack the Application_ItemSend event or similar???
0
 

Author Comment

by:famoso
ID: 16903855
I'm feeling stupid.  Heres my initial addin code from the wizard ...
Where do I put the code I want to execute?

namespace OutlookPlugin
{
      using System;
      using Microsoft.Office.Core;
      using Extensibility;
      using System.Runtime.InteropServices;
      

      #region Read me for Add-in installation and setup information.
      // When run, the Add-in wizard prepared the registry for the Add-in.
      // At a later time, if the Add-in becomes unavailable for reasons such as:
      //   1) You moved this project to a computer other than which is was originally created on.
      //   2) You chose 'Yes' when presented with a message asking if you wish to remove the Add-in.
      //   3) Registry corruption.
      // you will need to re-register the Add-in by building the MyAddin21Setup project
      // by right clicking the project in the Solution Explorer, then choosing install.
      #endregion
      
      /// <summary>
      ///   The object for implementing an Add-in.
      /// </summary>
      /// <seealso class='IDTExtensibility2' />
      [GuidAttribute("AFE16BFD-BC11-4263-A437-CD70EBDC5CC0"), ProgId("OutlookPlugin.Connect")]
      public class Connect : Object, Extensibility.IDTExtensibility2
      {
            /// <summary>
            ///            Implements the constructor for the Add-in object.
            ///            Place your initialization code within this method.
            /// </summary>
            public Connect()
            {
            }

            /// <summary>
            ///      Implements the OnConnection method of the IDTExtensibility2 interface.
            ///      Receives notification that the Add-in is being loaded.
            /// </summary>
            /// <param term='application'>
            ///      Root object of the host application.
            /// </param>
            /// <param term='connectMode'>
            ///      Describes how the Add-in is being loaded.
            /// </param>
            /// <param term='addInInst'>
            ///      Object representing this Add-in.
            /// </param>
            /// <seealso class='IDTExtensibility2' />
            public void OnConnection(object application, Extensibility.ext_ConnectMode connectMode, object addInInst, ref System.Array custom)
            {
                  
                  
                  applicationObject = application;
                  addInInstance = addInInst;
            }

            /// <summary>
            ///     Implements the OnDisconnection method of the IDTExtensibility2 interface.
            ///     Receives notification that the Add-in is being unloaded.
            /// </summary>
            /// <param term='disconnectMode'>
            ///      Describes how the Add-in is being unloaded.
            /// </param>
            /// <param term='custom'>
            ///      Array of parameters that are host application specific.
            /// </param>
            /// <seealso class='IDTExtensibility2' />
            public void OnDisconnection(Extensibility.ext_DisconnectMode disconnectMode, ref System.Array custom)
            {
            }

            /// <summary>
            ///      Implements the OnAddInsUpdate method of the IDTExtensibility2 interface.
            ///      Receives notification that the collection of Add-ins has changed.
            /// </summary>
            /// <param term='custom'>
            ///      Array of parameters that are host application specific.
            /// </param>
            /// <seealso class='IDTExtensibility2' />
            public void OnAddInsUpdate(ref System.Array custom)
            {
            }

            /// <summary>
            ///      Implements the OnStartupComplete method of the IDTExtensibility2 interface.
            ///      Receives notification that the host application has completed loading.
            /// </summary>
            /// <param term='custom'>
            ///      Array of parameters that are host application specific.
            /// </param>
            /// <seealso class='IDTExtensibility2' />
            public void OnStartupComplete(ref System.Array custom)
            {
            }

            /// <summary>
            ///      Implements the OnBeginShutdown method of the IDTExtensibility2 interface.
            ///      Receives notification that the host application is being unloaded.
            /// </summary>
            /// <param term='custom'>
            ///      Array of parameters that are host application specific.
            /// </param>
            /// <seealso class='IDTExtensibility2' />
            public void OnBeginShutdown(ref System.Array custom)
            {
            }
            
            
            private object applicationObject;
            private object addInInstance;
      }
}
0
 
LVL 2

Accepted Solution

by:
bdsmithback earned 500 total points
ID: 16907715
Sorry for the delay famoso - I've been in meetings all day.  Don't feel stupid - this is not all that intuitive...

Here is the code I think you're looking for.  You're going to want to place the code to capture the ItemSend event in the connect class as that loads when outlook is loading.


//I've changed the type of applicationObject form object to Outlook.Application for ease since this is an outlook only app.
private Outlook.Application applicationObject;

private object addInInstance;
public void OnConnection(object application, Extensibility.ext_ConnectMode connectMode, object addInInst, ref System.Array custom)
{
      applicationObject = (Outlook.Application)application;  //Cast application and Outlook.Application to handle the change from object
      addInInstance = addInInst;

      //Add this event handler
      applicationObject.ItemSend += new Outlook.ApplicationEvents_ItemSendEventHandler(applicationObject_ItemSend);
}

//this handes the ItemSend event
void applicationObject_ItemSend(object Item, ref bool Cancel)
{
      //Add your code here to write the info to the file.
      //I've added some code to access the common fields of the mail item.
      try
      {
            Outlook.MailItem mi = (Outlook.MailItem)Item;
            string subject = mi.Subject;
            string body = mi.Body;
            string to = mi.To;
      }
      catch { }
}

So - to recap: You're adding an event handler on the OnConnection method for Outlook.Application.ItemSend.  You're then adding the code to save the e-mail's content to a file in the application_ItemSend event handler method.  You might also be able to use System.Relfection.Assembly.Load to load another DLL like you talked about, but I've not done this from an addin so I can't promise results.  My guess is that it will work - but I'm not sure how the object model security of outlook will see that...

I hope this helps!

Beau
0
 

Author Comment

by:famoso
ID: 16911193
I'll try that but I definatly understand it better.

So basically in thoughts of defining an event handler, placing applicationObject_ItemSend() in a module in VBA and defining applicationObject_ItemSend() as an event handler in a plugin is the same thing?
0
 
LVL 2

Expert Comment

by:bdsmithback
ID: 16912993
Yes - you can think of it in those terms.  Thanks famoso!
0

Featured Post

Find Ransomware Secrets With All-Source Analysis

Ransomware has become a major concern for organizations; its prevalence has grown due to past successes achieved by threat actors. While each ransomware variant is different, we’ve seen some common tactics and trends used among the authors of the malware.

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…
Extention Methods in C# 3.0 by Ivo Stoykov C# 3.0 offers extension methods. They allow extending existing classes without changing the class's source code or relying on inheritance. These are static methods invoked as instance method. This…
This video gives you a great overview about bandwidth monitoring with SNMP and WMI with our network monitoring solution PRTG Network Monitor (https://www.paessler.com/prtg). If you're looking for how to monitor bandwidth using netflow or packet s…
In this tutorial you'll learn about bandwidth monitoring with flows and packet sniffing with our network monitoring solution PRTG Network Monitor (https://www.paessler.com/prtg). If you're interested in additional methods for monitoring bandwidt…

760 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

23 Experts available now in Live!

Get 1:1 Help Now