Problem:
As stated in the previous article I had to write code to send bulk emails with a 6MB PDF attachments individually. The source of the email body was from a .htm template file which had references to images such as the company logo and others. This email should also have an alternate plain text format in case the recipient's email client accepted only plain text email.
Solution:
The code is pretty simple and straight forward. We will be using the following classes from .NET MailMessage, EmbeddedMailObject, MailDefinition, MailAttachment and SMTPClient.
C# Code
using System.IO;
using System.Net;
using System.Net.Mail;
using System.Web.UI.WebControls;
namespace Mail_CA01
{
class Mail
{
// folder where this console application will reside
public static string directory = @"C:\SendMail";
public static void SendMail()
{
try
{
// read all the email addresses stored in this text file one per line
string[] emails = File.ReadAllLines(directory + @"\EmailList.txt");
int totalEmails = emails.Length; // total email addresses to send
int currentEmail = 1;
Console.WriteLine("Total Emails to send " + totalEmails.ToString());
// log the time when you start sending the emails
File.AppendAllText(directory + @"\Logs\EmailLog.txt", Environment.NewLine + Environment.NewLine + "Started at " + DateTime.Now.ToString("MM/dd/yyyy HH:mm:ss")
+ Environment.NewLine + Environment.NewLine);
// create and send email to each individual from the email list
foreach (string email in emails)
{
// check to make sure there are no empty lines in between email addresses in the emailist.txt
if (!string.IsNullOrEmpty(email))
{
MailMessage mail = new MailMessage();
mail.Subject = "Welcome ....";
// you will get a notification if the server fails to deliver the email. There are other options to choose from.
mail.DeliveryNotificationOptions = DeliveryNotificationOptions.OnFailure;
// create maildefinition object to add images and html formatted email body
MailDefinition mailDefinition = new MailDefinition();
mailDefinition.IsBodyHtml = true;
mailDefinition.Subject = "Welcome ....";
mailDefinition.BodyFileName = directory + @"\newsletter_template.htm";
EmbeddedMailObject emoLogo = new EmbeddedMailObject();
emoLogo.Name = "Logo";
emoLogo.Path = directory + @"\Logo.png";
EmbeddedMailObject emoImage = new EmbeddedMailObject();
emoImage.Name = "Image.jpg";
emoImage.Path = directory + @"\Image.jpg";
EmbeddedMailObject emoSignature = new EmbeddedMailObject();
emoSignature.Name = "Signature";
emoSignature.Path = directory + @"\Signature.jpg";
mailDefinition.EmbeddedObjects.Add(emoLogo);
mailDefinition.EmbeddedObjects.Add(emoImage);
mailDefinition.EmbeddedObjects.Add(emoSignature);
// create the alternate plain text view for email clients who display/accept only plain text emails
string plainText = File.ReadAllText(directory + @"\newsletter_template.txt");
AlternateView plainView = AlternateView.CreateAlternateViewFromString(plainText, null, "text/plain");
mail.AlternateViews.Add(plainView);
// Create the html formatted email
mail = mailDefinition.CreateMailMessage(email.Trim(), null, new Literal());
// create an attachment object and add it to the mail object
Attachment pdf = new Attachment(directory + @"\brochure.pdf");
mail.Attachments.Add(pdf);
// create smtp client to send the email
SmtpClient client = new SmtpClient();
client.Send(mail);
Console.WriteLine("Sending mail " + currentEmail.ToString() + " of " + totalEmails.ToString() + " to " + email + ".");
File.AppendAllText(directory + @"\Logs\EmailLog.txt", "Sent to " + email + Environment.NewLine);
currentEmail++;
// give an interval of 10 seconds before sending the next email. Do this if you are worried about clogging up the network with too many emails and big attachments.
System.Threading.Thread.Sleep(10000);
}
}
// This is optional code
// logging the time at the end of emailing
File.AppendAllText(directory + @"\Logs\EmailLog.txt", Environment.NewLine + Environment.NewLine + "Ended at " + DateTime.Now.ToString("MM/dd/yyyy HH:mm:ss")
+ Environment.NewLine + Environment.NewLine);
// moving the email list, in case there will be a new email list to use.
File.Move(directory + @"\emails.txt", directory + @"\Email Lists\EmailList_" + DateTime.Now.ToString("MMddyy") + "_" + emails[emails.Length - 2] + ".txt");
Console.WriteLine("Done sending mails");
Console.ReadLine();
}
// log the exception details when thrown. Note this code throws an exception if the email address is not valid and stops sending the email.
//For example there is a period at the end of the email address for eg: 'austinpowers@groovybaby.com.'
catch (SmtpException smtpex)
{
File.AppendAllText(directory + @"\Logs\EmailErrorLog.txt", Environment.NewLine + Environment.NewLine + "Error " + DateTime.Now.ToString("MM/dd/yyyy HH:mm:ss")
+ Environment.NewLine + Environment.NewLine + smtpex.Message);
Console.WriteLine(smtpex.Message);
Console.ReadLine();
}
catch (Exception ex)
{
File.AppendAllText(directory + @"\Logs\EmailErrorLog.txt", Environment.NewLine + Environment.NewLine + "Error " + DateTime.Now.ToString("MM/dd/yyyy HH:mm:ss")
+ Environment.NewLine + Environment.NewLine + ex.Message);
Console.WriteLine(ex.Message);
Console.ReadLine();
}
}
}
}
You can find detailed explanation for the above steps and the objects used here.
App.Config / Web.Config Settings:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.net>
<mailSettings>
<smtp deliveryMethod="PickupDirectoryFromIis" from=""Austin Powers" <austinpowers@groovybaby.com> ">
<network userName="austinpowers" password="yourpassword" host="mail" port="25"/>
</smtp>
</mailSettings>
</system.net>
</configuration>
The SMTPClient object will look into the config file for the mail server and user details. You can also add the display name in the ‘from’ field. This is especially helpful if you are using Windows 2003 POP3 Server, since the mail boxes are attached to the local windows user accounts and the account’s name might not be displayed in the sent emails. The ‘host’ setting can have the server’s name or it’s IP address.
HTML Template:
newsletter_template.htm
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Welcome ...</title>
</head>
<body>
<a href="http://www.groovybaby.com" target="_blank">
<img src="cid:Logo" border="0" alt="Visit us at www.groovybaby.com" />
</a>
<br />
<br /><br />
<div style="font-family: Arial; font-size: small;">
Dear <br /><br />
Your Content
Sincerely,<br /><br />
<img src="cid:Signature" alt="Austin Powers" border="0" /><br />
Austin Powers
<br /><br />
<a href="http://www.groovybaby.com" target="_blank">
<img src="cid:Image" border="0" alt="Click here to view Dr. Evil's Lair." /></a><br />
<br />
</div>
<div style="font-family: Arial;">
For more information, please see the resources listed below:<br />
<br />
<br />
This is a one-time only email. You will not be contacted again unless you request
to be contacted <a href="http://www.groovybaby.com">here</a><br /><br />
</div>
</body>
</html>
Notice the img tags contain ‘cid:Logo’ for example will be replaced with the emoLogo object from the C# code above.
Now on to Part 2