Drag and Drop Outlook Emails onto .NET Application

I do talk a lot of trash about Microsoft on this blog, but since I work in a place which is a Windows shop I can’t really get away from it’s products. Today I dusted off my “C# Developer” hat, and started chugging away. Why .NET? Because it seemed like the right tool for the job. The task at hand was to figure out a way how someone could grab bunch of emails out of her Outlook, and then drag and drop them onto something so that:

  1. The emails get saved as .msg files in an appropriate folder on the network share
  2. Our internal intranet application becomes aware of these files, and display download links where applicable

So instead of forwarding emails to 4-5 people assigned to a given job, the scheduling person would simply put them in a central location on the server and appropriate people would see download links on their “project page” once they log into the web app. This would limit the “did you get that thing I sent you?” questions, and allow an administrator to add people to a project without the need of hunting down all the relevant emails and forwarding them to the new guy.

Communicating with the web application is not an issue – I can do that in any language. The tricky part the drag and drop functionality which is the whole point of this project. The whole exercise of saving the email as a .msg file and uploading it to the web app using a traditional HTML form was briefly considered for .5 seconds and then unanimously rejected because it would be a royal pain in the ass. On the other hand typing in a task number and then dragging/dropping relevant emails onto some sort of a form is kinda like forwarding them – only you just have to do it once.

I briefly considered Java, but the interaction between Outlook and the Java application looked like a really hairy business. On the other hand .NET seemed like a perfect choice. You’d think that Microsoft would have a relatively easy mechanism of scripting it’s flagship office product in their flagship programming environment. And it turns out that there is – it’s called MS Office Primary Interop Assemblies. These are bunch of COM objects which you can import into your Visual Studio project and they allow you to interact with Office applications at a somewhat intimate level. Unsurprisingly, they are dependent on the version of MS Office you are using (in my case Office 2003) making it hard to create a robust, catch-all solution. You can grab a distributable installer package for Office 2003 version from here.

I added the Microsoft Office 11 Core Library and Microsoft Outlook 11 Core Library as the references to my project. They automagically appeared under the COM tab of my reference dialog in Visual Studio after installing the redistributable package linked above.

Next on the menu was the Drag and Drop functionality. That was pretty easy. In fact, an article written by Tgueth on Code Project gives you a very good primer how to set things up. Just ignore his code, because it won’t work for what I’m trying to do. He was simply interested in dropping actual onto the form – so real files dragged over from Explorer, or Outlook attachments dragged from your email. The email themselves however are handled differently, and cannot be captured this way. I tried, and I failed. There is however an alternate solution using the Interop Assemblies I described above – and believe it or not, the code is actually much cleaner and more compact.

So I sat down and hacked up a quick prototype. Here is the relevant code:

namespace DragAndDrop
{
  public partial class Form1 : Form
  {
    private Microsoft.Office.Interop.Outlook.Application OL;
    private string my_dir = "C:\\";

    public Form1()
    {
      InitializeComponent();
      OL = new Microsoft.Office.Interop.Outlook.Application();
    }

    private void Form1_DragEnter(object sender, DragEventArgs e)
    {
      e.Effect = DragDropEffects.Copy;
    }

    private void Form1_DragDrop(object sender, DragEventArgs e)
    {
      for (int i = 1; i <= OL.ActiveExplorer().Selection.Count; i++)
      {
        Object temp = OL.ActiveExplorer().Selection[i];

        if (temp is Microsoft.Office.Interop.Outlook.MailItem)
        {
          Microsoft.Office.Interop.Outlook.MailItem mailitem = (temp as Microsoft.Office.Interop.Outlook.MailItem);
          string subject = mailitem.Subject.Replace(":", "");
          mailitem.SaveAs(my_dir + "\\" + subject + ".msg", Microsoft.Office.Interop.Outlook.OlSaveAsType.olMSG);
        }
      }
    }
  }
}

Let's break it down, shall we? The first method Form1_DragEnter describes what is supposed to happen when you drag an object onto your form. We simply want to change the Effect property of the event to Copy:

e.Effect = DragDropEffects.Copy;

If you don't do this, then your code will detect drop effects but that's about it - it won't know or care what was dropped. This will ensure that the target of the drop will hold on to a copy of whatever you dragged over when you drop it.

Next, we need to handle the items that were dropped in the Form1_DragDrop method. The following statement returns an array of items which are currently selected with your mouse (ie. the stuff you are dragging right now):

OL.ActiveExplorer().Selection

Since I want to allow users to drag bunch of emails at a time, I'm going to iterate over this array and then grab each item. Since potentially a user could drag over something that is not an email, I'm temporarily saving it as an Object:

Object temp = OL.ActiveExplorer().Selection[i];

If it turns out to be an Outlook email object we cast it back to Microsoft.Office.Interop.Outlook.MailItem and save it. Note that I use the subject line as the filename (an quickly sanitize it removing the illegal ":" character) and save it in the root of the C: drive for now.

The SaveAs method of the MailItem object takes two parameters: first one is the path where you want to save the item, and the other is the file type which must be a member of the OlSaveAsType Enumeration which is a part of the Interop library. I'm using olMSG since that will save as the default Outlook message format.

This code works under Office 2003 but there is one small issue. For every mail item you drop, Outlook will throw this nasty security warning message:

Outlook Security Warning

The good news is that the user has the option to disable it for up to 10 minutes. The bad news is that 10 minutes is the maximum amount of time you can choose from that drop down box. I do see why they have this warning there, I just suspect it will become really annoying unless I find out a way to disable it. I did not cross that bridge yet though. Any suggestions? So far the bare bones functionality is working and I can drag and drop email messages onto my little form, and have them saved perfectly along with attachments which is precisely what I wanted.

Next step is to figure out how to make that thing talk to a PHP + MySQL backend of our web application, but that should not be that difficult. All I need to do is to send a HTTPS POST request back to the server, and then have something on the other end process that data and dump it into a database. It doesn't really need to be much more complicated than that.

[tags].net, c#, outlook, outlook interop, drag and drop, drag and drop outlook emails[/tags]

This entry was posted in Uncategorized. Bookmark the permalink.



19 Responses to Drag and Drop Outlook Emails onto .NET Application

  1. Luke Maciak UNITED STATES Mozilla Firefox Ubuntu Linux Terminalist says:

    Yeah, I saw that. There is also this thing. I was hoping for a more elegant solution that wouldn’t require the user to run an additional POS app. But it seems that this is really the easiest way. :(

    Reply  |  Quote
  2. Mirko GERMANY Mozilla Firefox Ubuntu Linux says:

    I used WebDAV to send email through exchange server in order to bypass the dreaded “do you want to send this message” 5 sec wait message dialog. I later learned that you can control outook’s “security” ;) features via policy editor – there might be a setting for what You need.

    Reply  |  Quote
  3. Luke Maciak UNITED STATES Mozilla Firefox Windows Terminalist says:

    That’s what I thought too but I can’t find any info on disabling particular dialog. :(

    Also, I think it’s actually easier to just connect to a SMTP server directly and send an email that way rather than to proxy through Outlook due to these infernal “security” features.

    Reply  |  Quote
  4. Aramsham BELGIUM Internet Explorer Windows says:

    Hi, I actually have done the same job in a java applet but encounterd a prob : when you d&d your mail from outlook in a directory, you get a subject.msg, but the binary is not the same when I get the mail from outlook via a java/COM bridge and then invoke a SaveAs on the mailItem.

    I send the mail as a binary stream to another application (developped by another team) and they don’t use the file extension but are guessing the doctype with the binary. But as the binaries are not the same, apparently they’re not able to guess that the COM.SaveAs is a .msg file :(
    And they cannot use the extension I send them by put request because of the DB (maybe later)…

    Do anybody has an idea why? And if so, any solutions?

    Reply  |  Quote
  5. Luke Maciak UNITED STATES Mozilla Firefox Ubuntu Linux Terminalist says:

    Hmm…. Not sure but it is an interesting issue. This may be crazy talk, but could you possibly serialize the mailItem object and then send that over to the other app? It would circumvent the whole mimetype problem. Or not. I don’t know…

    How are the binaries different? Different than what? What are we comparing them to?

    Reply  |  Quote
  6. Aramsham BELGIUM Internet Explorer Windows says:

    Mmmmh, unfortunately even if I send the mailItem, there’s no “getByte” method to get the .msg as a binary file, cos it’s stored in a blob in DB2/400…

    I don’t know if there’s huge difference, all I can see in a Hexa Editor (like UltraEdit) is that the contain is not exactly the same…you can try, when you d&d from outlook to a directory, and when you do a File >>> Save As >>> *.msg, there’s at least 1Kb difference! The d&d file is about 1Kb more than the SaveAs version! Really I don’t understand…

    Reply  |  Quote
  7. Luke Maciak UNITED STATES Mozilla Firefox Ubuntu Linux Terminalist says:

    Oh wow… Weird. I really do not know why would there be a difference.

    Now when you are saying Drag & Drop do you mean drag an email from Outlook into a directory, or drag it into Java app that then saves it into a directory? If it’s the later, perhaps it has something to do with the way you are writing the file to disk. If it’s the former, then that’s just bizarre.

    Reply  |  Quote
  8. Aramsham BELGIUM Internet Explorer Windows says:

    Like you said…strange ^^

    I made both d&d, but the d&d from outlook into a directory is the only case where the binary is different. When I d&d in my applet, I take it as a COM mailItem, and then I invoke a SaveAs on it, just like if you make a File>SaveAs>*.msg from outlook…

    Bah this afternoon I’ll have a meeting with the other team to see if they can update their pattern to catch that type of binary…

    Reply  |  Quote
  9. Matt UNITED STATES Mozilla Firefox Windows says:

    It’s called Newforma and it kicks ass.
    Unfortunately it does a LOT of other things for AEC industry that many could care less about but the Microsoft method is only going to increase the madness.

    Reply  |  Quote
  10. very fine and sample solution, tanks

    Reply  |  Quote
  11. Ross Kelly AUSTRALIA Internet Explorer Windows says:

    Thanks for the artice. Well done.

    If you add a using statement as follows:

    using Outlook = Microsoft.Office.Interop.Outlook;

    you can then refer to Outlook without the whole Microsoft.Office.Interop. declaration in front of it.

    Reply  |  Quote
  12. Wow, this is very useful.. Thanks for sharing this and hoping I could implement it too.

    Reply  |  Quote
  13. alrhr GERMANY Opera Windows says:

    Nice post. Still I have a problem with your solution. When I drag some other file to my form not originating from outlook, these files should be rejected. But instead your application imports the currently selected message from outlook (as long a outlook is open of course).

    Reply  |  Quote
  14. Jake UNITED STATES Mozilla Firefox Windows says:

    Nice solution. I’ve implemented something nearly identical, however, in my case Outlook decides to delete the dragged item once it’s been dropped (or once my code is done with it possibly..dispose?)

    Have you had this problem? If so, how do I avoid it?

    Reply  |  Quote
  15. Ankit INDIA Internet Explorer Windows says:

    Hello,

    I tried to implement the same thing but i got a error message like object reference not set into following loop.

    for (int i = 1; i <= OL.ActiveExplorer().Selection.Count; i++)

    at very firts line..

    can you help me out.

    thanks,

    Reply  |  Quote
  16. Ankit INDIA Internet Explorer Windows says:

    the actual error is that…

    “Function evaluation disabled because a previous function evaluation timed out. You must continue execution to reenable function evaluation.”

    can you ppl help me out in this..

    thnks in advance.

    Reply  |  Quote
  17. Ian Reid (expanz) AUSTRALIA Mozilla Firefox Windows says:

    This is great. So simple and effective.

    Reply  |  Quote
  18. Thomas LITHUANIA Google Chrome Windows says:

    If you have something selected in Oulook but dragged something else onto the form. It saves these selected Outlook emails. How to deal with that?

    Reply  |  Quote

Leave a Reply

Your email address will not be published. Required fields are marked *