The SmtpMailMan
As I was browsing the classes available under the System namespace I came
across the SmtpClient class, saw its breakdown and found I could use it to send
email. For ages I've thought of having a little program that could send emails
from my desktop without much ado, well, I didn't get anything small enough. So I
decided to see what I could come up with using this SmtpClient class I just
found. I never got around to write that program because some other idea came to
me that I really had to pursue.
That idea was to write a program that could attach and send files to an email
( I wish I could put that program up in CodeProject for everyone to benefit from
- its a little handy thing). The challenges I faced while writing the program
made me decide to write an easy to use class library that is really reusable and
expandable.
SmtpMailMan, meaning Smtp Mail Manager, is a class that encompasses the
classes required for you to easily and successfully send a simple email that
contains an attachment to one, two, three ... (3 people not tested with the
class) people from within your code, and it has removed all the other classes
and stuffs you'll need to create/ initialize before you send a mail successfully
using the .NET 2.0's provided classes. Another interesting thing you might find
in the little class will be found in the source code where a string has to be
checked for its credibility of being an acceptable email address, and ...
A Peep into the Code
The SmtpMailMan library exposes two main classes; the SmtpMailMan and the
MailSentEventArgs classes. I will only discuss on the SmtpMailMan class in this
article.
Here is a list of the main classes in the .Net 2.0 that were used in
SmtpMailMan;
- SmtpClient
- MailMessage
- MailAddress
- NetworkCredential
A summarized explanation of these class and their application in the
SmtpMailMan class will be sufficient to accomplish our "peep into the code".
MailAddress
First you shouldn't worry about why this has to be the first class that I'll
explain, just follow me as I lead you onto the edge for a peep.
If you'd successfully send an email then the email must have a destination -
or you'll end up blowing it into the open air and have blown straight back into
your face. The MailMessage class needs a credible mail address for it to do its
work, credible in the sense that it only has to be an address that conforms to
the acceptable format of an email address - it doesn't have to actually exist,
though if you're serious about sending a mail you'll feed it with a valid email.
MailMessage will not take a raw string from you to use in any of its destination
fields - except you access the inner methods, what it accepts in its To, Cc and
Bcc properties is a MailAddress object. Getting the email string from the user
and then converting to the MailAddress object might be clumsy ( and it truly is
when you consider the other conversions that you'll have to make), so I decided
to beat this in my own class by doing the job for you. When you assign a string
email to the To property that I exposed in the my class (SmtpMailMan), it
immediately checks to see if the email is a credible one and then assign it to
the MailMessge object that will carry the message you intend to send.
You might want to see the code that certifies that the email string you
assigned is credible.
protected bool CertifiedEmail ( string email )
{
Regex re = new Regex(@"\w.\w@{1,1}\w[.\w]?.\w");
return re.IsMatch(email);
}
I used a regular expression now, unlike in the first case, and this is reliable, you can try it out.The usage is pretty the same, I didn't change that.
set
{
if ( CertifiedEmail( value ) )
{
to = value;
if ( value != "" )
{
mail.To.Add( value );
}
}
MailMessage
The MailMessage class is the class that handles the message that will be sent
along with its attachments. The object I created for this is the mail
object.
This class exposes properties such as; Subject, Body, Attachments, To, Cc,
Bcc. SmtpMailMan makes the job of getting all this except the Attachments done
by exposing properties that you can easily set. Just appropriate string
value to the appropriate property and you're done. The only Property of the
MailMessage that I implemented differently is the Attachments property, which I
exposed through a method. I did it this way because it is possible for you to
want to add more than a file as attachment and I really want to make everything
very simple and easy so instead of making it a property that you may not readily
understand how to use in adding up your files for attachment I decided to use a
method ( AttachFile( string path)
) that you call the number of
times you want, each time with the full path of the attachment as the only
argument - now there is an overload that handles multiple files passed to it as string array, isn't that nice.
NetworkCredential
A NetworkCredential object is required by the SmtpClient for it to know
the email account it will pass to the SmtpServer for authentication.
Authentication is required because we're connecting a server at another site for
the sending of our mail.
The NetworkCredential object contains an Account property which represents
the username part of an email address, and the Password property which must the
correct password of the user account on the server. The Account and the Password
must in turn be valid on the server. For example my email address is
laolusrael@yahoo.co.uk, and my
password is xxxxxxx (of course you don't expect me to tell you that). So, for a
NetworkCredential object the Account would be 'laolusrael' and the Password
would be set to 'xxxxxxx'.
The way I implemented this class in SmtpMailMan is such that you wouldn't
even know there was such a class as NetworkCredential, all you do is assign a
valid email address to the Account property of the SmtpMailMan and set the
Password field to the correct password of the mail account you specified in the
Account property.
SmtpClient
I would have called this the main class that made SmtpMailMan possible but
because all the classes worked together to achieve SmtpMailMan and none would
have worked successfully without the other. I created an object of the
SmtpClient class which I called smtpClient
. The smtpClient object
handles the connection to the remote SMTP Server that does the sending of the
mail, it exposes the following properties and methods;
- Host
- EnableSsl
- Port
- UseDefaultCredentials
- Credentials
- SendAsync ()
Its easy to understand, the Host property accepts a string containing the IP
or url address of the SMTP Server, the Port gets the port on which the Server
listens, EnableSsl is used to specify that whether the server uses SSL for its
authentication or not. UseDefaultCredentials also accepts true or false that
tells whether to use the system's default credentials, I read that this should
be set to false - since you would be specifying the Credentials yourself. The
Credential property is set to the NetworkCredential object explained above.
SendAsync()
method handles the sending of the mail in
asynchronous mode which is actually what you should use - there is Send()
,
this is because your UI does not freeze while the mail is being sent. The
smtpClient object exposes an event, SendCompleted()
, that gets invoked when the
mail sending is complete so you'll be able to determine whether the mail was
sent successfully or not. However, there is a threading error in this class
somewhere when objects get passed between the application threads. I think this
is more of a problem in the .Net 2.0 classes that work over the internet, while
I have not yet found a clean work around for this problem, I used the
BackgroundWorker class to suppress the Exception that often gets thrown when
moving across threads. Its only a temporary workaround and you might have faced
a similar situation as well, so you might find it 'temporarily useful' to use
the BackgroundWorker class resident in System.ComponentModel
namespace.
How to use the SmtpMailMan
Using this class is extremely easy, first you'll need to add a reference to
the SmtpMailMan.dll file you downloaded above.
The SmtpMailMan class is resident in the SOFTLib namespace, create your
SmtpMailMan object, subscribe to the OnMailSent Event and you're ready to go.
The code below shows you how to use the class in simple steps;
...
using SOFTLib.SmtpMailMan;
...
SmtpMailMan smm = new SmtpMailMan();
void InitializeAndUse()
{
smm.OnMailSent += new SmtpMailMan.MailSentEventHandler( smm_OnMailSent );
smm.To = "mymail@server.com";
smm.Subject = "My Picture";
smm.AttachFile("c:\mypic.gif");
smm.AttachFile("c:\mypic2.gif");
smm.Body = " Checkout my pix, i'm sure you'll like it";
smm.Account = "myaccount@yahoo.co.uk";
smm.SmtpHost = "smtp.mail.yahoo.com";
smm.Port = 587;
smm.Ssl = false;
smm.SendMessage ();
}
void smm_OnMailSent(object sender, MailSentEventArgs e)
{
if(e.Message==null)
{
...
}
else
{
}
}
Known Issues
There are some know issues (bug - sort of) that arise from the use of the
SmtpMailMan, I'll tell you the ones I know and the workaround for it, then I'll
update this article as soon as I have found new issues - and if you found them
let me know so I can fix them up.
Event Handler Error
<><>(This is more of a design problem form microsoft, everyone that wrote event handlers across event handlers seem to get in the same mess. I may look for alternative later, right now i don't have all the time.) >>If a mail was not sent successfully and an error message was returned in the
Message
property of the MailSentEventArgs
object e
,
the handler method gets run twice; first with the original values in the e
object, and the second time with the value of e.Message set to null which is
equivalent to the Message being sent successfully. The workaround to this is
explained in this piece of code;
bool argChecked = false;
void smm_OnMailSent(object sender, MailSentEventArgs e)
{
if(e.Message==null)
{
if(!argChecked)
{
...
argChecked = true;
}
}
else
{
...
}
}
When you use the argChecked
, you should also have a neat way of setting its value to the original false
value. Maybe you could put that after the line that sent your mail.
Okay, that is it for now. You need to let me know the issues you face so I'll
be able to do a fix for it until the whole library gets better. I want work
improving this library for the next few weeks before I resume school, but you
can still send your suggestions and stuffs even later.
Messager
Messager is the little dummy (not really dummy) applet that I decided to
include into this article as the demo. All it does is demonstrate in the
simplest way, the application of the SmptMailMan library. Download it and you
may never need to open your mailbox or open Outlook, Thunderbird ... to send
just a simple message to anyone. Its very simple, easy to use, and also very
easy to understand - if you'd love to read the source code.
Up to you
You're going to need to tell me whatever challenges you faced while using
this class. Also send me any bug fixes you made in the class. I really love it when
classes are as simple and easy to use as this. This can get better if you help
it. I hope you do great things with it.
Seun (Laolusrael) loves programming. I learnt 80% of what I know in programming all alone. I use my God-given mind to do a lot of thinking, and...
Currently Seun is a student studying software engineering, and working freelance.