Solved

Outlook plug-in Save Email to hard drive

Posted on 2006-06-13
10
376 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
3 Use Cases for Connected Systems

Our Dev teams are like yours. They’re continually cranking out code for new features/bugs fixes, testing, deploying, testing some more, responding to production monitoring events and more. It’s complex. So, we thought you’d like to see what’s working for us.

 

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
 

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

PRTG Network Monitor: Intuitive Network Monitoring

Network Monitoring is essential to ensure that computer systems and network devices are running. Use PRTG to monitor LANs, servers, websites, applications and devices, bandwidth, virtual environments, remote systems, IoT, and many more. PRTG is easy to set up & use.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
About delegates in c sharp 3 47
2 questions 10 25
VB.NET (2008) - Refactoring Question 2 21
C# Object Reference is Required for the non-static field, method, or property 10 34
Entity Framework is a powerful tool to help you interact with the DataBase but still doesn't help much when we have a Stored Procedure that returns more than one resultset. The solution takes some of out-of-the-box thinking; read on!
The article shows the basic steps of integrating an HTML theme template into an ASP.NET MVC project
This video shows how to quickly and easily add an email signature for all users on Exchange 2016. The resulting signature is applied on a server level by Exchange Online. The email signature template has been downloaded from: www.mail-signatures…
The Email Laundry PDF encryption service allows companies to send confidential encrypted  emails to anybody. The PDF document can also contain attachments that are embedded in the encrypted PDF. The password is randomly generated by The Email Laundr…

777 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