You have mail - OEAPI and COM
Written by Mike James   
Monday, 14 September 2009
Article Index
You have mail - OEAPI and COM
Wrapping the Interface
YHM application

You have mail

With the parts of the IStoreFolder interface that we need converted to usable form we can now move on to design the You Have Mail, or YHM, application.

There are many ways of implementing this action but a system tray application seems like a good idea because then it can sit unobserved until it needs to attract attention. It also turns out to be very easy to create system tray applications.

Start a new C# project called YHM and add a form called Main. Drag and drop a NotifyIcon and a ContextMenu control from the toolbox to the form. To make the two controls work together you need to set the NotifyIcon’s ContextMenuStrip property to the name of the ContextMenu that you have just placed on the form. You also have to assign an Icon to its Icon property because otherwise nothing shows in the SysTray when you run it.

If you are using C# 2005 Express the bad news is that it doesn’t come with an icon editor but there are a few available for download as freeware or shareware. The icon used here is included as part of the project in the CodeBin

 

Setting up the right click context menu couldn’t be easier. If you select the ContextMenu control then a menu appears that you can edit directly. In this case type in just one menu item “Exit”. You can add others as you develop the project. Double clicking on any of the menu items automatically generates a click event handler for it.

 

form

Setting up the main form and the context menu

 

We also need this new form to be the startup form for the project. To do this open the file Program.cs using the Solution Explorer and change the main method to read:

static void Main()
{
Application.EnableVisualStyles();
Application.Run(new Main());
}

As the Main form is intended never to appear on the screen its Constructor has to be modified to:

public Main()
{
InitializeComponent();
TopLevel = false;
}

Setting a form’s TopLevel property to false means that it is owned by a parent form. However if the form’s Parent property is null then the form just vanishes and its Paint method is never called by the system – hence it becomes invisible.

Once the form has loaded we use its Load event handler to display the icon in the system tray:

private void Main_Load(
object sender,EventArgs e)
{
notifyIcon1.Visible = true;

The only context menu event handler we need to implent is for the “exit” option. All that we have to do to remove the application from the system tray is make the icon invisible and terminate the application:

private void exitToolStripMenuItem_Click(
object sender, EventArgs e)
{
notifyIcon1.Visible = false;
Application.Exit();
}

If you don’t make the icon invisible it hangs around even after the application has finished.

From here we can start to build the code that inspects the mailstore and signals when a mail comes in. For this demonstration a form is used to display an “URGENT EMAIL” message when the email arrives. This isn’t particularly effective but you can add code to create any sort of event you care to in the same way.

Add a multi-line textbox to the original Form1 and change its declaration, which can be found at the end of Form.Designer.cs, from private to:

public System.Windows.Forms.TextBox 
textBox1;

This makes it possible to access the textbox from outside of the form. Next we create and instance of the form and make it invisible:

f=new Form1();
f.Visible=false;

This is also the place to create the OE object that we need to work with the message store. To do this we need to include the OE.c file, i.e. the one with all of the interface definitions and classes, in the project and add to the start of the Main.c file:

using OE1;

Now we can create an OE object:

oe = new OE();

We also need to record the time that YHM was started because we only want to react to emails that arrive after the start time:

StartTime = DateTime.Now;

Finally we need a mechanism to check the email store at regular intervals for new emails. This is most easily achieved by adding a Timer control to the form and setting its interval to the number of minutes that we want to leave between checking for new mail:

 timer1.Interval = 1000*60*1;
timer1.Enabled = true;
}

That concludes the form load handler but we do need to remember to add some global variables that we have used:

private OE oe;
private DateTime StartTime;
private Form1 f;

The timer

All of the real work is done in the Timer’s tick handling routine and it’s surprisingly simple.

The reason is that most of the work has been in preparing the foundations of the entire project. The first thing we need to do is disable the timer so that it doesn’t trigger again until we have finished:

private void timer1_Tick(
object sender, EventArgs e)
{
timer1.Enabled = false;

Now we use the OpenSpecialFolder method to open the inbox:

 OEFolder Folder = oe.OpenSpecialFolder(
SPECIALFOLDER.FOLDER_INBOX);

The constant FOLDER_INBOX is defined in the OE.cs file and you can use the same technique to open any of the special folders. Notice that the method returns an object of type OEFolder which represents the inbox. To discover if there are any emails to check we next need to use the Folder’s GetFolderProps method. This returns a FOLDERPROPS struct exactly like OE’s method GetNextFolder:

FOLDERPROPS fp = Folder.GetFolderProps();

In this case we also display the number of emails in the folder in the textbox on the form:

f.textBox1.Text=f.textBox1.Text+
fp.cMessage.ToString();

We can only refer to textBox1 in this way because its declaration was changed from private to public – a quick and slightly dirty way of displaying data. If there are any emails we need to find out what time they arrrived and who they are from:

if (fp.cMessage > 0)
{
UInt32 ehandle = 0;
MESSAGEPROPS mp;
do
{
mp= Folder.GetNextMessage(ref ehandle);

The GetNextMessage method simply returns a MESSAGEPROPS struct until there are no more messages. This is signalled by the fact that the entire struct is zeroed and hence the do-while loop can end when mp.MessageId is zero.

Once we have the MESSAGPROPS structure we can test the DisplayFrom and Received fields to see if the message is the one we are waiting for:

 if(mp.DisplayFrom=="mike James" &&
mp.Received > StartTime)
{
f.Visible = true;
f.textBox1.Text =
"You Have URGENT Email";
f.Refresh();
}
}

In this case a single name is checked; in a more complicated situation you could check against a list of names or against a name entered by the user. Notice that the DisplayFrom field is the name as displayed in Outlook Express, i.e. a nickname, and not the full email address.

If a new email is found from the designated user then the form is made visible, used to display a message and refreshed to make sure its display is up-to-date. It’s up to you to decide how to inform the user in a more appropirate way, e.g. SMS or automatic phone call, but the idea is the same. Finally we finish the loop and restart the timer:

  }
while(mp.MessageId>0 );
}
timer1.Enabled = true;
}

That’s all there is to it but there are some additional points worth making. First it’s important to realise that all you are doing is inspecting the Outlook Express message store. You can do this even when Outlook Express isn’t running -  but if you do so you don’t be surprised there are no new emails!

In practice you need to add some code to start Outlook Express running before you start looking for new emails. In addition there is no point in checking for changes in the mail store every minute if Outlook Express is only set to pick up mail every ten minutes. You need to match the rate that mail is collected to how often you check for changes in the message store.

Finally remember that no error handling is included in this example and errors do indeed occur if the mail store is in use by Outlook Express so you need to add some code that tests for problems and tries again in a few minutes.

All of this is fairly straightforward – to start Outlook Express you can either use Interaction.Shell method or you can implement more of the API, i.e. IOutlookExpress. You can discover or set the time interval that mail is picked up on via the registry – the key is Poll For Mail.

Once you see how easy it is to find work with the mail store and inspect what emails it contains you are sure to think of other uses. However if you want to go further you will need to complete more of the API – both the interface definitions and the classes that wrap them.

To access the code for this project then register and click on CodeBin.

<ASIN:0596527578>

<ASIN:1590599551>

<ASIN0735624305>

 



Last Updated ( Monday, 14 September 2009 )