Using Outlook as a Print Server


Introduction

My wife is constantly asking me to print documents because she doesn't want to use the ink from her expensive printer.  I can't say I blame her, since I have a cheap low end inkjet.  The printer doesn't have a network port, and I've been told by our tech guy that if we use a print server, it would screw up the scanning on the printer.  I decided to come up with a cheap solution and let Microsoft Outlook do the work for me.  

Setting up the Project

Visual Studio 2010 has several project templates for Office, even templates for applications that are less widely used, such as Visio.  We'll pick the Outlook project and get started.  Click the New -> Project and select the Office tab.  Then choose the Outlook Add-In.  I picked Outlook 2007, because that is what I have on my machine.

1.gif

Figure 1 - Creating the Outlook Add - In

This will create two method event handlers where we can kick off our code and clean up our code.

private void ThisAddIn_Startup(object sender, System.EventArgs e)
{
}

private void ThisAddIn_Shutdown(object sender, System.EventArgs e)
{
}

The Requirements

Our print server will trigger on any new messages coming into Outlook.  We don't want to print out all messages being received, so we will only print out those messages with the subject printit.  We don't want to wait for outlook to decide when to receive messages, so will force the receive on a timer every 20 seconds.

The Tasks

There are 3 parts to the code:  1)  an event that triggers an event handler every time a new message a received.  2)  A timer that periodically forces send receive from outlook  3)  the checking of the subject and  printing of the message that meets our subject condition.

Hooking up the Event Handler and Timer

We can use the Session in outlook to get at the Inbox Folder to set up our event.  The COM Items object in the Inbox has an event on it called ItemAdd.  This event will be triggered when a new item comes into the Inbox.  Note, that it was important to declare items as a class member rather than a variable inside the method, otherwise the event handler would have been garbage collected at some point and we would stop receiving events.  

Listing 1 - setting up the timer and hooking up the mail item event handler

Timer timer = null;
Outlook.Items items = null;  // items in the inbox folder
private void ThisAddIn_Startup(object sender, System.EventArgs e)
{
    // start the timer and have it poll every 20 seconds to force a receive
    timer = new Timer(SendReceiveAllAccounts, null, 0, 20000);
    //  set up the event handler on any items added to the inbox
    HookupItemReceivedEventHandler();
}
private void HookupItemReceivedEventHandler()
{
    var objNS = Application.Session;
    var defaultFolder = objNS.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderInbox);
    items = defaultFolder.Items;
    items.ItemAdd +=new Outlook.ItemsEvents_ItemAddEventHandler(Items_ItemAdd);
}

The timer is a simple thread timer which we set to call an event handler every 20 seconds.  The event handler will force outlook to send and receive messages in the inbox.  Send and Receive also uses the Items member in the inbox folder through the Session.  I'm not sure the logon to the session is required, but we add it here anyway.

Listing 2 - Forces a send receive inside of outlook

// force a send receive
private void SendReceiveAllAccounts(object state)
{
     var objNS = Application.Session;
     Outlook.MAPIFolder defaultFolder = objNS.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderInbox);
     Outlook.NameSpace session = defaultFolder.Items.Session;
     session.Logon("", "", false, false);
     session.SendAndReceive(false);
     session.Logoff();
     session = null;
}

Should we receive a message in outlook, it will fire the ItemAdd event, which will in turn go to our event handler.  In the event handler we check the last message and see if it has a printit in the subject.  If it does,  we call the PrintOut method on the item.

Listing 3 - Event Handler that prints when a 'printit'  Item is added to the Inbox. 

void Items_ItemAdd(object Item)
{
    var objNS = Application.Session;
    Outlook.MailItem item = Item as Outlook.MailItem;
    if (item.Subject == "printit")
    {
        item.PrintOut();  // print the mail item here
    }
}

Deploying and Managing the Outlook Add-In

If you have outlook on your machine and you download this sample, you should be able to run the project in Visual Studio to see how it works.  If you Publish the project by right clicking on Solution explorer, it will install the add-in on your machine in the registry and it will be a part of outlook.  If you want to disable the add-in, go to Tools -> Trust Center inside of Outlook 2007.  This will give you a place to manage your new add-in if you wish to enable or disable it:

2.gif

Figure 2 - Add-In Management in Outlook 2007

Strategy for Printing Attachments

Some of you may be curious about how you might print an attachment to a mail message.  I think the approach here is to save the attachment to a file on your hard drive and then use one of the other office applications to print it out (if it can read it).

For Example, using Word, you could print out a word readable document after you saved the attachment to a known location:

Listing 4 - Printing an E-mail Attachment using Word

var filePath = pathOnHardDrive + item.Attachments[0].FileName;
item.Attachments[0].SaveAsFile(filePath);
Microsoft.Office.Interop.Word.Document doc = Microsoft.Office.Interop.Word.Application.Documents.Open(filePath);
doc.PrintOut();

Conclusion

If you don't have a print server, the outlook print server may be enough to handle some of your printing needs from another machine.  Because it works off of e-mail, you could send the print command from anywhere in the world.  Just tell your friends not to put printit in their subject line if they are not planning on printing.  You can limit the printing access further by checking the from field of the message.

if (item.Subject == "printit" && item.SenderEmailAddress == "[email protected]")
{
    item.PrintOut();
}

Anyway, have fun with the print server, it will give you a new outlook on how to perform remote printing using C# and .NET.


Similar Articles