WinForm Programming: Send Email Using Outlook Interop or System.Diagnostics.Process
Posted by Keith Elder | Posted in .Net, Programming, Smart Clients | Posted on 11-01-2007
A lot of applications generate emails to alert users or send out notifications. If you do WinForm programming the need to generate email from your application is something you will probably come across at one point or another. There are essentially two ways I use to generate emails from WinForms or Smart Clients. One is using the Outlook Interop and the other is simply starting a process using the System.Diagnostics.Process class. Each has their own merits. Depending on why you are generating an email from your application will ultimately determine which method you should use. For starters, let’s take the easy road and start with the Process class.
Using System.Diagnostics.Process To Generate Emails
If you aren’t familiar with this namespace the purpose of it is to provide the .Net developer with a means to access processes running on the local computer. It can also be used to start processes as well.
Using this class we are going to borrower something from our HTML friends. The “mailto” tag has been around forever and we can utilize this tag to start a new process. The idea is that whichever mail client is setup as the default mail client, a process will be started to create a new email message. The result is no different than clicking a mailto tag in a web browser. The code for this is simple, only a few lines. Since the process class implements IDisposable we are going to use the using construct to assist in disposing of the process once it is done. Here’s the code.
using (Process process = new Process())
{
process.StartInfo.FileName = “mailto:me@foo.com&subject=Hello”;
process.Start();
}
As you see in the above example, the “mailto” tag is used as the FileName property. A new process is going to start and launch a new email message screen for the user with the email address of me@foo.com already entered and the subject “Hello”. Here is the sample application running:
When the LinkLabel named “Send Email Without Outlook API” is clicked, it launches the default email client on our computer and enters a To and a Subject for us automatically. Nothing fancy or ground breaking but it works.
System.Diagnostics.Process vs Outlook Interop
As we see above sending emails from our WinForm application with the Process class is very simple. Why would we want to go through the trouble of using the Outlook Interop to send emails? Won’t the above example work for any Windows computer no matter which email client the user has running, so isn’t that more flexible? The answer is yes. This solution will work on any Windows computer launching whatever the configured default email client is. However, what if you need to log what the user wrote in the email? This is where System.Diagnostics.Process falls down.
Let me expand on this. Say for example you have a CRM application that needs to log emails sent by users to your clients or contacts or customers (whatever acronym you adopt). Even though your user’s will have the message saved in their Sent folder in Outlook having it just in their email client doesn’t easily give the users of your CRM a quick view of activity. You may also have auditing rules in your business requirements whereby you need to save the first 500 characters of each correspondence sent to client. Using the Process example above doesn’t allow us to intercept the message so we have access to the complete message being sent. However, using the Outlook Interop API we can keep track of everything as well as log the email to suite our business requirements.
Let me go ahead and get this out of the way. Yes this does require you to be in a controlled environment. Most corporate and enterprise networks are controlled and you’ll know if this approach will work for you in your business.
Using Outlook Interop To Generate Emails
To get started using the Outlook Interop we first need to add the required DLL to our solution. In order to do this, right click on Add References in your solution and select the COM tab. Scroll down about half way and select the Microsoft Outlook 11.0 Object Library. Add this as a reference to your project.
Once you add the required DLL to your project you are ready to start coding for the API. One of the things I like to do is create wrapper classes for these interop classes that allow me to call them when I need them with just a few lines of code. Here is an example of a wrapper class.
using System;
using System.Collections.Generic;
using System.Text;
using OutlookApp = Microsoft.Office.Interop.Outlook;
namespace Common.Outlook
{
/// <summary>
/// Provides functionality so Outlook can be used to generate Emails. Use the
/// write event to log the email.
/// <example>
/// Email outlookMsg = new Email();
/// outlookMsg.Message.Subject = “Foo bar”;
/// outlookMsg.Show();
/// </example>
/// </summary>
public class Email
{
/// <summary>
/// Gets the current instance of Outlook
/// </summary>
OutlookApp.Application _outlookInstance = new Microsoft.Office.Interop.Outlook.Application();
private OutlookApp.MailItem _message;
public OutlookApp.MailItem Message
{
get
{
return this._message;
}
set
{
this._message = value;
}
}
/// <summary>
/// Constructor, gets current outlook instance
/// and creates a blank email message
/// </summary>
public Email()
{
Initialize();
}
private void Initialize()
{
// create a blank email
_message = (OutlookApp.MailItem)_outlookInstance.CreateItem(OutlookApp.OlItemType.olMailItem);
// wire up the write event for logging
_message.Write += new Microsoft.Office.Interop.Outlook.ItemEvents_10_WriteEventHandler(Message_Write);
}
/// <summary>
/// Used for logging after the end user presses the send
/// button in Outlook. If you need to log the email that was
/// sent to a web service or something else, fill this in. This is
/// called after the email is sent via Outlook.
/// </summary>
/// <param name=”Cancel”></param>
void Message_Write(ref bool Cancel)
{
// ADD LOGGING HERE IF YOU NEED IT
}
/// <summary>
/// Displays the outlook screen and shows the email message.
/// </summary>
public void Show()
{
_message.Display(false);
}
}
}
Using the code above we can now enable the first link in our sample Email form above. To create an email with Outlook it is now a few lines of code.
Common.Outlook.Email msg = new Common.Outlook.Email();
msg.Show();
Since we have access to the Outlook message we can set the Subject, To, CC, BCC, Format and other options. We get a lot more control over our email message than with just by starting a process. Here is a more fleshed out example.
Common.Outlook.Email outlookEmail = new Common.Outlook.Email();
outlookEmail.Message.To = “me@foo.com”;
outlookEmail.Message.CC = “me2@foo.com”;
outlookEmail.Message.BodyFormat = Microsoft.Office.Interop.Outlook.OlBodyFormat.olFormatPlain;
outlookEmail.Message.Importance = Microsoft.Office.Interop.Outlook.OlImportance.olImportanceHigh;
outlookEmail.Message.Body = “I love cookies!”;
outlookEmail.Show();
Will create the following:
The other thing using the Outlook Interop allows us to do is log the messages as noted earlier. To do this we would add our business requirements into the Message_Write event. In this event we have access to lots of information including a real sent time, the complete body, what importance was set, the subject and so on. Obviously any property exposed in the API we can still reference. This gives us a way to log the information via a database, web service or other means.
try this if outlook is not running:-
try { Outlook.Application app = System.Runtime.InteropServices.Marshal.GetActiveObject(“Outlook.Application”) as Outlook.Application; } catch (System.Exception ex) { System.Diagnostics.Process.Start(“Outlook.exe”); }
Thanks,
Amit kala
This is good for open outlook message.
But This code has a problem that when I deployed this code on the server. Then Client system can not access the outlook message. Out look message always open on the Server System when client system give the command to open Outlook Message.
Does this work if outlook is not running?
I solve it 🙂 , I just add event :
_message.PropertyChange += new Microsoft.Office.Interop.Outlook.ItemEvents_10_PropertyChangeEventHandler(Message_PropertyChange);
article very helpfull , just one question (I know it’s an old post) how can I know if the message has sent or not and know if the message I put was modified or not ?
thx
Great article, one question though. This works great when I “run” my application. If I add my Application and those dependecies (Office.dll, and outlook interopt, etc) to a “setup project in vs 2008” when I click the email button on my form I get the dialog asking to install office, then a nasty error about interopt not findnig outlook? Yet, Outlook is running, and this app works in vs2008 by running it in that enviroment???
thx dude
This works like a charm on my dev laptop. However when I copy the wrapper (which I created as a class under the App_Code folder) over to the remote web site the whole website crashes. (I use ‘copy to web’ rather than ‘publish’). I suspect it is because the Outlook com object is not on the remote site. If so, how do I get it there? I know when I installed AJAX I had to copy the Bin folder over but I don’t see anything new to copy over. Help!
I answer to myself:
kure256.wordpress.com/…/sending-email-via-out…
Hello
I just want to ask how i can put a part like the part your comment on this website where users can send comment to the website without open mail system
and thanks for your reply
by the way this article is very helpfull
Cool article!! I learned something new 😉
My question is, how to assign image into the email body. Not just representative. I mean to show picture in the message body.
I’ll be pleased if anybody can help me with this.
So how can you get RichText into the body?
I have a Rich Text Box, and I want to get its contents into the body of the email.
oMessage.BodyFormat = Microsoft.Office.Interop.Outlook.OlBodyFormat.olFormatRichText
oMessage.Body = rtb1.text — will send it as plain text
oMessage.Body = rtb1.rtf — will send it as plain text but shows all the rich text control characters.
Any ideas?
I get a security error “A program is trying to access email-addresses you have stored in Outlook. Do you want to allow this?”
Any ideas?
You’ve been kicked (a good thing) – Trackback from DotNetKicks.com