Click here to Skip to main content
15,892,059 members
Articles / Programming Languages / C#

HolidaysMailer

Rate me:
Please Sign up or sign in to vote.
3.95/5 (11 votes)
21 Sep 2011CPOL4 min read 36K   1.2K   32   15
An automated mail sending application

Introduction

I was confronted with the issue of sending an e-mail to a list of recipients, none of which being aware of the other potential receivers (if any) of the message. Concretely, I desired to send a holidays greeting message to all of my acquaintances, without manually sending individual messages.

Background

There are three standard solutions to send an e-mail to more than one recipient, none of which is satisfactory for the task I needed accomplished:

  1. Filling up the To: field of the e-mail sending form - each receiver sees all of the other recipients
  2. Putting all except one receiver into the CC: (Carbon Copy: ) box - raises again the concern from point 1.
  3. Placing all except one recipient in the BCC: (Black Carbon Copy: ) field - each receiver sees the recipient in the To: selection, but none of the others residing in the BCC: area

None of these options proves reliable when the user expects an e-mail addressed individually to him / her.

Designing the Solution

The most natural choice is to repeatedly send the e-mail to a single recipient specified in the To: field. This cannot be efficiently done manually, so an automatic solution must be devised.

A specifically-designed application (or script) should:

  • read the e-mail configuration of the mail server on which the sender's mail account dwells: SMTP (Simple Mail Transfer Protocol) host name, SMTP port and the availability of SSL (Secure Socket Layer) on the mail server
  • retrieve the name of the sender to be viewed later by the receivers, as well as its' mail account name and password
  • obtain the message subject and content to be sent
  • get the list of names and e-mail addresses to which the message must be sent
  • send the e-mails one-by-one
  • print a report on the status of the e-mail sends

A sensible option would be to read this data from a configuration file set up by the user of the application prior to running it.

Configuration File

The format the HolidaysMailer configuration file uses is XML, as shown in the subsequent EmailConfig.xml file:

XML
<?xml version="1.0" encoding="utf-8"?>

<!DOCTYPE EmailConfiguration [

<!ELEMENT EmailConfiguration (SmtpHost, SmtpPort, 
	FromAddress, FromName, Subject, Content, Addresses)>
<!ATTLIST EmailConfiguration EnableSSL (true|false) #REQUIRED>

<!ELEMENT SmtpHost (#PCDATA)>
<!ELEMENT SmtpPort (#PCDATA)>
<!ELEMENT FromAddress (#PCDATA)>
<!ELEMENT FromName (#PCDATA)>
<!ELEMENT Subject (#PCDATA)>
<!ELEMENT Content (#PCDATA)>
<!ELEMENT Addresses (Person*)>
<!ELEMENT Person (Name, Email)>
<!ELEMENT Name (#PCDATA)>
<!ELEMENT Email (#PCDATA)>

]>
XML
<EmailConfiguration EnableSSL="true">
    <SmtpHost>smtp.gmail.com</SmtpHost>
    <SmtpPort>587</SmtpPort>
    <FromAddress>mock.email@gmail.com</FromAddress>
    <FromName>Mihnea Radulescu</FromName>
    <Subject>Happy Easter</Subject>
    <Content>Happy Easter and kindest wishes to you!

Yours sincerely,
Mihnea Radulescu</Content>
    <Addresses>
        <Person>
            <Name>Mihnea Radulescu</Name>
            <Email>mock.email@gmail.com</Email>
        </Person>
    </Addresses>
</EmailConfiguration> 

The first part of the XML file contains the XML DTD schema for the configuration file that the user can guide itself by when writing the proper XML content and that provides the application a means of checking the validity of the XML document. The password for the e-mail account is not stored within the XML file for security reasons.

The second part of the XML features an example of configuration that is tailored for a Google mail account. It reads my e-mail credentials and sends the message to a single person (myself). Setting it up for Yahoo! requires the user to have a Yahoo! Mail Plus (paid) account, since an ordinary Yahoo! account does not offer SMTP functionality.

C# Implementation

.NET is endowed with classes particularly suited for e-mail-related necessities, supplied under the System.Net and System.Net.Mail namespaces. For the reading and interpreting of XML content, the System.Xml namespace is utilized.

The implementation is a Console application relying on two classes: EmailConfiguration, for the reading of the e-mail configuration from the XML file and EmailSender, for the bulk (automated) sending of e-mails.

Two relevant code samples from these classes are shown below:

C#
/* Class EmailConfiguration - parses the XML document using the 
   .NET SAX API implementation,
   retrieving the e-mail configuration data */
private void ParseXMLDocumentWorker(XmlReader xmlReader)
{
     bool validName = false, validEmail = false;
     string name = string.Empty, email = string.Empty;

     try
     {
          while (xmlReader.Read())
          {
               switch (xmlReader.NodeType)
               {
                    case XmlNodeType.Element:
                         switch (xmlReader.LocalName)
                         {
                              case "EmailConfiguration":
                                   string enableSSLString = 
				xmlReader.GetAttribute("EnableSSL");
                                   if (enableSSLString == "true")
                                        enableSSL = true;
                                   else
                                        enableSSL = false;
                                   break;
                              case "SmtpHost":
                                   smtpHost = xmlReader.ReadString();
                                   break;
                              case "SmtpPort":
                                   string smtpPortString = xmlReader.ReadString();
                                   smtpPort = int.Parse(smtpPortString);
                                   break;
                              case "FromAddress":
                                   fromAddress = xmlReader.ReadString();
                                   break;
                              case "FromName":
                                   fromName = xmlReader.ReadString();
                                   break;
                              case "Subject":
                                   subject = xmlReader.ReadString();
                                   break;
                              case "Content":
                                   content = xmlReader.ReadString();
                                   break;
                              case "Person":
                                   validName = false;
                                   validEmail = false;
                                   break;
                              case "Name":
                                   name = xmlReader.ReadString();
                                   validName = true;
                                   break;
                              case "Email":
                                   email = xmlReader.ReadString();
                                   validEmail = true;
                                   break;
                       }
                       break;

               case XmlNodeType.EndElement:
                    switch (xmlReader.LocalName)
                    {
                         case "Person":
                              if ((validName == false) || (validEmail == false))
                                   throw new XmlException
				("Invalid or incomplete person details.");
                              else
                              {
                                   string newAddress = name + " <" + email + ">";
                                   toAddresses.Add(newAddress);
                              }
                              break;
                    }
                    break;
               }
          }
     }

     catch (XmlException)
     {
          xmlIsValid = false;
          Console.Error.WriteLine("The e-mail configuration file is not a 
		well-formed XML document.");
     }
} 
C#
// Class EmailSender - sends an email to the specified address
private void SendEmail(string toAddress)
{
     try
     {
          MailAddress mailAddressFrom = new MailAddress(fromAddress, fromName);
          MailAddress mailAddressTo = new MailAddress(toAddress);
          
          MailMessage emailMessage = new MailMessage(mailAddressFrom, mailAddressTo);
          emailMessage.BodyEncoding = Encoding.UTF8;
          emailMessage.IsBodyHtml = false;
          emailMessage.Subject = subject;
          emailMessage.Body = content;

          NetworkCredential emailCredential = 
			new NetworkCredential(fromAddress, password);
          SmtpClient mailClient = new SmtpClient(smtpHost, smtpPort);
          mailClient.EnableSsl = enableSSL;
          mailClient.UseDefaultCredentials = false;
          mailClient.Credentials = emailCredential;

          mailClient.Send(emailMessage);
          Console.Out.WriteLine("E-mail to " + toAddress + " successfully sent.");
     }

     catch
     {
         errorCount++;
         Console.Error.WriteLine("Failure sending e-mail to " + toAddress + ".");
     }
}

Application Value

The application is useful for sending a message to a group of people, allowing each recipient to believe that the e-mail was sent specifically to him / her. In particular, holidays are instances when such a solution proves its' value, being required to greet a large number of acquaintances.

Source Code and Application Download

The complete source code of the HolidaysMailer application (a Google Code project) can be accessed here. If one is only interested in the binaries, they can be downloaded from this link.

I would gladly welcome contributions and feedback to this HolidaysMailer open-source (GPL v3) project.

References

  • [1] The Microsoft Developer Network (MSDN) pages

History

  • Version 0.1 - Initial submission - 01/03/2010
  • Version 0.2 - Code updates - 03/04/2010
  • Version 0.3 - Updated content, sources and binaries - 21/09/2011
  • Version 0.4 - Removed the actual e-mail address from the article and the source code to avoid spam e-mails - 21/01/2013

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



Comments and Discussions

 
QuestionGreat article Mihnea Pin
adrian.tompa10-Feb-17 3:23
adrian.tompa10-Feb-17 3:23 
Suggestion[KISS] Simple as I like it! Pin
Ladislau Radu Nagy19-Oct-12 12:04
Ladislau Radu Nagy19-Oct-12 12:04 
GeneralRe: [KISS] Simple as I like it! Pin
User 691845419-Oct-12 12:36
User 691845419-Oct-12 12:36 
GeneralMy vote of 1 Pin
ignatandrei26-Sep-11 17:34
professionalignatandrei26-Sep-11 17:34 
So basically you have another MailMerge that is available from Word. More, I do not see in the example on codeproject the templating fields like "Dear {first name} "
GeneralMy vote of 5 Pin
nofacts22-Sep-11 16:59
nofacts22-Sep-11 16:59 
Generalreading xml... Pin
VirtualVoid.NET3-Apr-10 2:12
VirtualVoid.NET3-Apr-10 2:12 
GeneralRe: reading xml... Pin
User 69184543-Apr-10 6:36
User 69184543-Apr-10 6:36 
GeneralRe: reading xml... Pin
VirtualVoid.NET4-Apr-10 1:22
VirtualVoid.NET4-Apr-10 1:22 
GeneralRe: reading xml... Pin
User 69184544-Apr-10 5:18
User 69184544-Apr-10 5:18 
GeneralMailMergeLib could be another approach... Pin
axuno2-Mar-10 10:49
axuno2-Mar-10 10:49 
GeneralRe: MailMergeLib could be another approach... Pin
User 69184543-Mar-10 1:55
User 69184543-Mar-10 1:55 
GeneralMy vote of 2 Pin
karabax1-Mar-10 11:51
karabax1-Mar-10 11:51 
GeneralRe: My vote of 2 PinPopular
Johnny J.1-Mar-10 22:03
professionalJohnny J.1-Mar-10 22:03 
GeneralRe: My vote of 2 Pin
angel 226-Sep-11 0:09
angel 226-Sep-11 0:09 
GeneralCustom configuration section Pin
Not Active1-Mar-10 4:14
mentorNot Active1-Mar-10 4:14 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.