Mike Taulty's Blog
Bits and Bytes from Microsoft UK
Silverlight 4 – Grabbing Emails from the Outlook Inbox

Blogs

Mike Taulty's Blog

Elsewhere

I’ve been using Twitter and one of the things that I followed recently was the Silverlight forums and that caused a question to bob up on my screen just yesterday;

image

I haven’t replied back to the original poster as I don’t imagine that I’ve got the solution to his particular problem but it occurred to me that with Silverlight 4, reaching into an application like Outlook to use a little bit of functionality is exactly the kind of scenario that you can tackle with COM interop so that sparked my interest in experimenting with it.

It feels like there’s a few possibilities around how you might do this with Silverlight 4;

  1. Staying within the sandbox you could try and do drag-and-drop from Outlook to Silverlight.
    1. I don’t think you can do a straight drag-drop because I don’t think Silverlight sees that as a file drop.
    2. I suspect you’d have to drag to desktop and then drag the resultant file to the Silverlight app.
    3. To do (2) and stay in the sandbox, you’d have to unpick the binary Outlook message format yourself which wouldn’t be much fun unless there’s some way to get Outlook to save a message as XML ( I haven’t found that yet ).
  2. Leaving the sandbox, with an out of browser “trusted” application you could;
    1. Attempt to do 1.1 and 1.2 above but ask Outlook to decipher the Outlook .msg file for you
    2. Read the email details from Outlook in the first place – that is, pop up a dialog in Silverlight which shows the user their Outlook email so that they don’t have to drag and drop.

I decided to experiment with 2.2.

I wrote a little app, it’s should be running below if I can figure out where to drop it onto my website. If you’re on the Silverlight 4 beta you can click it to install it locally ( if you’re not on the beta you’ll perhaps get a white rectangle or, hopefully, a Silverlight logo );

 
In the browser, it presents a UI;
 
image
which will change if you install it;
 
image
 
and if you run it from the desktop it presents a “business UI” which is meant to represent some made-up-view of some customer data for a “contract management system” where you have a few fields relating to each Customer;
 
  • FirstName
  • LastName
  • ContractStartDate
  • ContractDuration
  • Correspondence which is a list of Email which is
    • From
    • To
    • Subject
    • Body
 
All the data is hard-coded into the ViewModel that sits behind the View and the UI is a DataGrid;
 
image
clicking on the “email” button in the DataGrid expands out ( using the DataGrid’s RowDetailsTemplate functionality the Correspondence for that particular customer ( again, this is generated data );
 
image
and that’s just shown in another DataGrid ( yes, sorry – I put grids into grids :-) ) which is bound to the Correspondence property on the Customer.
 
Clicking on that Attach… button in the UI sparks up another view which is pulling data from Outlook. I made this into a modal dialog style interaction using the Silverlight Toolkit’s ChildWindow class and the code I wrote also seems to take a while so I used a BusyIndicator as well;
 
image
 
that pulls in emails from Outlook with just a few lines of thrown together code which is currently in the wrong place in a ViewModel;
 
    void GetEmails()
    {
      // TODO - this is ugly, especially the reach into the application for its
      // dispatcher but the Outlook code is slow for me so I feel the need to
      // move the whole thing to another thread.
      // TODO - this code needs moving into some email service outside of this VM.
      Dispatcher dispatcher = Application.Current.MainWindow.Dispatcher;

      this.Loading = true;

      ThreadPool.QueueUserWorkItem(o =>
        {
          dynamic outlook = ComAutomationFactory.CreateObject("Outlook.Application");
          dynamic inbox = outlook.GetNamespace("Mapi").GetDefaultFolder(olFolderInbox);
          int itemCount = inbox.Items.Count;

          for (int i = 1; i <= itemCount; i++)
          {
            Email newEmail = new Email()
            {
              Subject = inbox.Items[i].Subject,
              Body = inbox.Items[i].Body,
              From = inbox.Items[i].SenderName,
              To = inbox.Items[i].To
            };
            newEmail.Body = newEmail.Body.Substring(0, 
              Math.Min(30, newEmail.Body.Length));

            dispatcher.BeginInvoke(() =>
              {
                this.Emails.Add(newEmail);
              });
          }
          dispatcher.BeginInvoke(() => this.Loading = false);
        });
    }
 
where Email is my own class used throughout this “app” so, as you can see, there’s not much to the Outlook interaction here.
 
Once the emails have loaded, there are little “Attach” buttons to attach them to the current customer so if I click to attach those 3 emails ( the buttons should perhaps be CheckBoxes ) and then click the Close button as the picture suggests;
 
image
then back in the main view, the Customer now has those 3 extra emails attached and, yes, those are real emails from my Inbox but hopefully I’m not leaking very much sensitive information here;
 
image
 
In playing around with this I hit a few “interesting” areas ( for me at least ) – so just some notes I made along the way;
 
  1. How to try and deal with ChildWindow from an MVVM perspective. I jump through a hoop or two in that;
    1. I want to put up the ChildWindow and then ask it for a list of attached emails when it is dismissed.
    2. Dismissing the ChildWindow is done via the “Close” button click which is handled on the ViewModel.
    3. In order for the ViewModel to close the ChildWindow it needs to call ChildWindow.Close() but then the ViewModel doesn’t know what a ChildWindow is so it’s a bit tricky for it to do that.
    4. In the end;
      1. I defined some interface ICloseableWindow that has a Close member on it and I implemented that on my ChildWindow
      2. I passed the ChildWindow as a command parameter to the bound command on the ViewModel.
      3. In the handler on the ViewModel, I test for ICloseableWindow and ask it to Close itself.
      4. This way I felt that the ViewModel is still reasonably independent because all it knows about is ICloseableWindow.
  2. How to deal with the Outlook email enumeration code taking quite a long time.
    1. I dealt with this by moving it to another thread but that introduced a dependency for my ViewModel to get back to the UI thread.
    2. I haven’t got any IoC container in here but I could have addressed the previous point (2.1) by asking for some “IInvokeUIService” on an IoC container and then using that to get back to the UI thread rather than reaching directly into Application.Current.MainWindow as I do above.

If you want to take a look, here’s the source code for download – note that I spent a couple of hours with it so it’s not very polished but if it helps you with something you’re doing then that’s great.


Posted Wed, Dec 23 2009 5:38 PM by mtaulty
Filed under: ,

Comments

Anonymous wrote re: Silverlight 4 – Grabbing Emails from the Outlook Inbox
on Thu, Dec 24 2009 1:10 AM

Nice Post

Anonymous wrote re: Silverlight 4 – Grabbing Emails from the Outlook Inbox
on Thu, Dec 24 2009 3:01 AM

Why saying the following code is uggly :

Dispatcher dispatcher = Application.Current.MainWindow.Dispatcher;  

I do use IoC and MEF but from my point of view  the best code is the one that is the simplest and the more efficient.

Most people forgot the performance cost of using Ioc or MEF call compare to a Static call.

Container simplify some tricky pattern but using a Static singleton that is part of the SL framework should not be consider as ugly but rather as wise. Esthetic reasons with extra performance penalty is not from my point of view the only way of thinking. Don't missunderstand my words i do think Container should be used but some time things are naturally easy and efficient so why enforced Container use.

Arun Mahendrakar wrote re: Silverlight 4 – Grabbing Emails from the Outlook Inbox
on Thu, Dec 24 2009 7:38 AM

Quite interesting Mike. Thanks

progg.ru wrote Silverlight 4 : загрузка данных из почтовых ящиков Outlook
on Thu, Dec 24 2009 7:38 AM

Thank you for submitting this cool story - Trackback from progg.ru

mtaulty wrote re: Silverlight 4 – Grabbing Emails from the Outlook Inbox
on Thu, Dec 24 2009 9:33 AM

Ah - the comment about ugly code was really that I'm in some piece of code that knows nothing about UI and I suddenly reach out and grab Application.Current.MainWindow.

It feels a bit wrong.

If I was doing it for real I'd perhaps implement an interface;

IDispatchToUIThread

{

 void Dispatch(Action action);

}

or something like that and then I can provide some implementation of that to this code and it makes it a little nicer I think than what I was doing here.

Alex wrote re: Silverlight 4 – Grabbing Emails from the Outlook Inbox
on Mon, Jan 4 2010 2:57 AM

Another option was to let the ViewModel fire an event when the VieModel's Close() method is called. This way, the ChildWindow can handle the Event itself. The ChildWindow needs to know the ViewModel, but this was already the case and the ViewModel doesn't need to know the ChildWindow or any extra interface. If you think about it, all the databinding you do with the view to the viewmodel is also based on events.

I'm really interested in what you think of this approach Mike!

Greetings,

Alex

dr k wrote re: Silverlight 4 – Grabbing Emails from the Outlook Inbox
on Tue, Jan 5 2010 11:19 AM

I have this running but how can I walk the outlook interface code in vs2010 b2 ? It does not trigger the OutlookMail interface. I run it once, it triggers the load screen, but then i have to uninstall and re-install to get the outlook interface back.

I'm still a bit new to the syntax: is the {(...)} code run in

a separte com thread ? Why not make it a stand alone subroutoutine thread or am i missing a c#'ism.

I would like to walk the code but it keeps slipping past me !

dB

mtaulty wrote re: Silverlight 4 – Grabbing Emails from the Outlook Inbox
on Wed, Jan 6 2010 1:10 AM

Alex - yeah, sounds good to me.

Dr K - the {{}} code is just a way of writing an anonymous method in C# 3.0, you could write an explicit function if you want to in order to do the same thing. In this case, it is being run on a separate thread but that's because I pass that function into ThreadPool.QueueUserWorkItem. I'm not sure what's happening with your Outlook but if this code is causing you to have to install/uninstall anything then things have gone very wrong.

Mike.

dr K wrote re: Silverlight 4 – Grabbing Emails from the Outlook Inbox
on Wed, Jan 6 2010 11:35 PM

thanks for the {()};

how / which  reference to you include in your assembly ?

Defining an assembly for Silverlight seems to exclude

other assemblies, unless you put them in by explicit file reference under the 'browse' for specific .dll's ....

have you considered using outlook on the server for in browser demo's and out of browser for client email ?

For example, having tryout data on a server ?

Ultimately I would like to let clients try it out without installing,

and have it run the same way installed only on live data.

Erika wrote re: Silverlight 4 – Grabbing Emails from the Outlook Inbox
on Fri, Jan 8 2010 10:00 PM

Another interesting way to integrate Outlook email and contacts is with the RedCritter Silverlight SDK for Outlook. It makes it simple to write Silverlight Apps that work contextually within Outlook. For example your Silverlight App can respond to events when a user selects an email or contact. The service and Silverlight SDK is free at www.redcritter.com.

sacha barber wrote re: Silverlight 4 – Grabbing Emails from the Outlook Inbox
on Wed, Jan 13 2010 8:23 AM

Mike

In terms of how to do Item 1 above I have a nice SL service that will do all that for you from MVVM point of view. You can have a look at in action right here where I also include a file uploader for SL4 using a HttpHandler:

www.codeproject.com/.../SL4FileUploadAnd_SL4_MVVM.aspx