Welcome

You have reached the blog of Keith Elder. Thank you for visiting! Feel free to click the twitter icon to the right and follow me on twitter.

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

14

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.

Like this story?  Then kick it on DotNetKicks.com

How To Add Feedburner FeedFlare to Your SubText Blog

Posted by Keith Elder | Posted in .Net, Blog Updates, Programming | Posted on 07-01-2007

13

I started using FeedBurner.Com to power the RSS feeds for my blog and I am quite happy in doing so.  I like the stats they provide and the guidance they provide on various tweaks to the feed without having to re-code anything.  One of the items I added to the RSS feed and to the site is FeedFlare.  FeedFlare places a simple footer at the bottom of each entry which allows people to distribute the entry to other sites or to inform other users of an entry.

Step 1:  Configure your FeedBurner account for your blog

This may seem pretty obvious, but at the risk of someone being confused in order to do this, you have to create a FeedBurner account.  The cost is free.  Once you create an account and link up your feed which points to your real RSS feed on your site, configure it.   Select your blog via the control panel and click on the Optimize tab.  In the left menu select “FeedFlare” and configure the options you want.

There are two options:  Feed and Site.  By placing a check in one column or another will determine where the FeedFlare shows up.    By choosing the “Feed” option, it will place the particular flare chosen at the bottom of your feed as seen here from RSS Bandit.

Choosing the “Site” option will display the chosen flares in your web site next to each item as seen here:

Step 2:  Add any custom flares to FeedBurner

Once you are done configuring which built-in flare options you may want to add other flares.  In the FeedBurner FeedFlare section there is documentation on how to add additional flare items so I will not cover it in detail but I will give you a quick sample on how to add a flare for http://www.dotnetkicks.com.  Essentially you create an XML file which is uploaded to a web server.  Here is the XML to add the flare as seen above for Kick It!

    1 <FeedFlareUnit>

    2     <Catalog>

    3         <Title>Kick It!</Title>

    4         <Description>Submit this post to DotNetKicks.Com</Description>

    5     </Catalog>

    6     <FeedFlare>

    7         <Text>Kick It!</Text>

    8         <Link href=”http://www.dotnetkicks.com/submit/?url=${link}”/>

    9     </FeedFlare>

   10 </FeedFlareUnit>

If you would like to use this particular one it is available here:  http://keithelder.net/feedflare/KickIt.xml

Step 3:  Modify SubText.Web.Skins.YourSkinName.Controls.Day.ascx control

I did some searching and couldn’t find any examples on where to place the script needed to insert the feed flare under each entry.  I had to dig into the code a bit to find which variable was needed to get access to the URL of each entry from within the template.  And I had to find the template.

The control we are going to modify is the Day.ascx control which is located in the Skins/YourSkinName/Controls directory.  The variable that we need to place in our user control is “FullQualifiedUrl”.  Since each item on the home page is printed using a Repeater we have to use the DataBinder.Eval to get each item’s FullyQualifiedUrl property.  Here is the sample code you need to place in your Day.ascx user control.  Don’t forget to modify the one associated with your skin and replace the word “yourname” with your appropriate FeedBurner name.

            <div>

                <script src=”http://feeds.feedburner.com/~s/yourname?i=<%# DataBinder.Eval(Container.DataItem, “FullyQualifiedUrl”) %> type=”text/javascript” charset=”utf-8″></script>

            </div>

Once you have this placed in your template where you want it, upload your newly modified template to your web site overwriting the existing one.  You only need to copy this one file.  Reload your home page and your new flare should appear. 

Securing Web Services With Username and Password

Posted by Keith Elder | Posted in .Net, Asp.Net, Programming | Posted on 06-01-2007

32

I was going through my news feeds this morning and stumbled across this article about securing web services.  The article is short and doesn’t give any examples of one of the methods I use a lot.  I thought I would elaborate on one of the topics it touches on which is securing a web service with a Username and a Password.  While there are other ways to secure web services I find this particular method works really well when dealing with internal systems that may not speak .Net.  It is also simple to implement on both sides.  These systems could be in Java, PHP or even 4GL.  If you are a .Net developer and want to secure a web service with a username, password, or even other information, here is what you need to get going.

1.  Create an object that extends SoapHeader

The first thing you need to do is create an object that extends the built-in SoapHeader object.   The object can be simple or complex. Add the tokens you want to authenticate against.  Here is a sample:

    1 /// <summary>

    2 /// Extends from SoapHeader and provides a username / password

    3 /// for web methods that need authentication.

    4 /// </summary>

    5 public class ServiceAuthHeader : SoapHeader

    6 {

    7     public string Username;

    8     public string Password;

    9 }

2.  Add a property to your service class that uses the class above

Once you’ve created your base soap header class, add it as a property to your service class.

    // SoapHeader for authentication

    public ServiceAuthHeader CustomSoapHeader;

3.  Attribute the method you want to secure

Add the SoapHeader attribute to each or certain methods you wish to secure pass in the name of the property that is defined as the SoapHeader object in step 2.

    1     [WebMethod]

    2     [SoapHeader(“CustomSoapHeader”)]

    3     public int AddTwoNumbers(int x, int y)

    4     {

    5        

    6         return x + y;

    7     }

4.  Create a method to process your SoapHeader for authentication

The last big step is to create a static method that will take in your custom soap header class and process it for validation.  The first thing we want to do is make sure that some type of credentials were passed in the SoapHeader and that the properties we are looking for are not null.  Finally we want to validate each property contains the information we are looking for. This could be read from the web.config file, database, or other places.

 

    1 public class ServiceAuthHeaderValidation

    2 {

    3     /// <summary>

    4     /// Validates the credentials of the soap header.

    5     /// </summary>

    6     /// <returns></returns>

    7     public static bool Validate(ServiceAuthHeader soapHeader)

    8     {

    9         if (soapHeader == null)

   10         {

   11             throw new NullReferenceException(“No soap header was specified.”);

   12         }

   13         if (soapHeader.Username == null)

   14         {

   15             throw new NullReferenceException(“Username was not supplied for authentication in SoapHeader.”);

   16         }

   17         if (soapHeader.Password == null)

   18         {

   19             throw new NullReferenceException(“Password was not supplied for authentication in SoapHeader.”);

   20         }

   21 

   22         if (soapHeader.Username != “myusername” || soapHeader.Password != “mypassword”)

   23         {

   24             throw new Exception(“Please pass the proper username and password for this service.”);

   25         }

   26         return true;

   27     }

   28 }

5.  Add validation to service method

 

    1     [WebMethod]

    2     [SoapHeader(“CustomSoapHeader”)]

    3     public int AddTwoNumbers(int x, int y)

    4     {

    5         // Test to see if the proper credentials were passed in.

    6         ServiceAuthHeaderValidation.Validate(CustomSoapHeader);

    7 

    8         // If we get this far the user has been validated.

    9         return x + y;

   10     }

 

That’s it. You now have all the pieces of the puzzle to process a request and validate the credentials of the calling client via a username and or password.  If we launch the solution we will see that our XML for our service has been updated and now contains an XML Node called ServiceAuthHeader which contains two sub nodes: username, password.

Passing SoapHeader Credentials To Your Service

Now that we have our service secured, we need to now call the service and pass the credentials expected from a client.  Based on the example above, once you add a web reference to the service and instantiate the service in code, the thing you want to look for is a new property of your service proxy called ServiceAuthHeader. This is converted into a property called ServiceAuthHeaderValue.  This property needs to be an instantiation of the ServiceAuthHeader class where you set the username and password properties.  Here is an example of a console application calling our service and passing the required information to authenticate.

    1 using System;

    2 using System.Collections.Generic;

    3 using System.Text;

    4 

    5 namespace ConsoleApplication1

    6 {

    7     class Program

    8     {

    9         static void Main(string[] args)

   10         {

   11             localhost.Service service = new ConsoleApplication1.localhost.Service();

   12             localhost.ServiceAuthHeader header = new ConsoleApplication1.localhost.ServiceAuthHeader();

   13             header.Username = “myusername”;

   14             header.Password = “mypassword”;

   15             service.ServiceAuthHeaderValue = header;

   16             int x = service.AddTwoNumbers(1, 1);

   17             Console.WriteLine(x);

   18             Console.ReadLine();

   19         }

   20     }

   21 }

 The return result will be 2 of course and from the client side it is rather trivial to pass the credentials as you see.   That’s it.   Happy authenticating!

[Related Link]
To take authenticating one step further with a custom SoapExtension read this follow up article.
http://keithelder.net/blog/archive/2007/01/09/Take-Securing-Web-Services-With-Username-and-Password-One-Step.aspx

 

CodeMash – See you there!

Posted by Keith Elder | Posted in .Net, Smart Clients, Speaking | Posted on 21-12-2006

0

If you are a developer you need to hurry up and get registered for CodeMash in January. What better way to spend a few winter days than at an indoor resort listening to geeks speak about PHP, Python, Java, Ruby and .Net? It is right around the corner and for this type of conference, it is pretty dang cheap. I will be speaking at the conference on Smart Clients so don’t forget your box of rotten fruit and fire away when I take the stage. Hope to see you there!

Speaking at CodeMash!

Posted by Keith Elder | Posted in .Net, Presentations, Smart Clients | Posted on 27-11-2006

0

I found out the other day that I will be speaking at CodeMash in Ohio during the warm month of January.  What am I speaking on?  I’ll give you one guess.  You guessed it, Smart Clients, ClickOnce, Web Services, SOA, etc.  It is a small world sometimes too.  The email about me speaking came from Jason Gilmore who I met while at Microsoft this past September during an ASP.Net Summit.  Jason and I talked about Media Center and tons of other stuff.  Who knew!  He was also on the bus when we got struck by some crazy chic.

 

The resort the conference is at is going to be really cool.  Not to mention the entire event is put on by the community and covers tons of technologies.  From a .Net presenter perspective these are usually tougher venues to speak at because you aren’t speaking in front of a bunch of people that swallowed the blue pill.  For me though, I don’t think that will be a problem since I can talk Linux, OS X, PHP and open source with the best of them. 

If you haven’t gotten signed up, what are you waiting for!!!!!!!!!