Embedding an Image in an Email in C#

7/29/2010

One of the things that I was tasked with this past week was creating an app to help with email marketing. And before you ask, not spam... Well sort of spam, but it's internal to the company. Anyway, the application was to send nice, HTML formatted emails. One of the things they wanted though was embedded images within the email's text. Turns out, it's incredibly simple to do:

   1: public class EmailSender : Message
   2:  
   3: {
   4:  
   5:     #region Constructors
   6:  
   7:  
   8:  
   9:     /// <summary>
  10:  
  11:     /// Default Constructor
  12:  
  13:     /// </summary>
  14:  
  15:     public EmailSender()
  16:  
  17:     {
  18:  
  19:         Attachments = new List<Attachment>();
  20:  
  21:         EmbeddedResources = new List<LinkedResource>();
  22:  
  23:         Priority = MailPriority.Normal;
  24:  
  25:     }
  26:  
  27:  
  28:  
  29:     #endregion
  30:  
  31:  
  32:  
  33:     #region Public Functions
  34:  
  35:  
  36:  
  37:     /// <summary>
  38:  
  39:     /// Sends an email
  40:  
  41:     /// </summary>
  42:  
  43:     /// <param name="Message">The body of the message</param>
  44:  
  45:     public void SendMail(string Message)
  46:  
  47:     {
  48:  
  49:         try
  50:  
  51:         {
  52:  
  53:             Body = Message;
  54:  
  55:             SendMail();
  56:  
  57:         }
  58:  
  59:         catch { throw; }
  60:  
  61:     }
  62:  
  63:  
  64:  
  65:     /// <summary>
  66:  
  67:     /// Sends a piece of mail asynchronous
  68:  
  69:     /// </summary>
  70:  
  71:     /// <param name="Message">Message to be sent</param>
  72:  
  73:     public void SendMailAsync(string Message)
  74:  
  75:     {
  76:  
  77:         try
  78:  
  79:         {
  80:  
  81:             Body = Message;
  82:  
  83:             ThreadPool.QueueUserWorkItem(delegate { SendMail(); });
  84:  
  85:         }
  86:  
  87:         catch { throw; }
  88:  
  89:     }
  90:  
  91:  
  92:  
  93:     /// <summary>
  94:  
  95:     /// Sends an email
  96:  
  97:     /// </summary>
  98:  
  99:     public void SendMail()
 100:  
 101:     {
 102:  
 103:         try
 104:  
 105:         {
 106:  
 107:             using (System.Net.Mail.MailMessage message = new System.Net.Mail.MailMessage())
 108:  
 109:             {
 110:  
 111:                 char[] Splitter = { ',' };
 112:  
 113:                 string[] AddressCollection = To.Split(Splitter);
 114:  
 115:                 for (int x = 0; x < AddressCollection.Length; ++x)
 116:  
 117:                 {
 118:  
 119:                     message.To.Add(AddressCollection[x]);
 120:  
 121:                 }
 122:  
 123:                 if (!string.IsNullOrEmpty(CC))
 124:  
 125:                 {
 126:  
 127:                     AddressCollection = CC.Split(Splitter);
 128:  
 129:                     for (int x = 0; x < AddressCollection.Length; ++x)
 130:  
 131:                     {
 132:  
 133:                         message.CC.Add(AddressCollection[x]);
 134:  
 135:                     }
 136:  
 137:                 }
 138:  
 139:                 if (!string.IsNullOrEmpty(Bcc))
 140:  
 141:                 {
 142:  
 143:                     AddressCollection = Bcc.Split(Splitter);
 144:  
 145:                     for (int x = 0; x < AddressCollection.Length; ++x)
 146:  
 147:                     {
 148:  
 149:                         message.Bcc.Add(AddressCollection[x]);
 150:  
 151:                     }
 152:  
 153:                 }
 154:  
 155:                 message.Subject = Subject;
 156:  
 157:                 message.From = new System.Net.Mail.MailAddress((From));
 158:  
 159:                 AlternateView BodyView = AlternateView.CreateAlternateViewFromString(Body, null, MediaTypeNames.Text.Html);
 160:  
 161:                 foreach (LinkedResource Resource in EmbeddedResources)
 162:  
 163:                 {
 164:  
 165:                     BodyView.LinkedResources.Add(Resource);
 166:  
 167:                 }
 168:  
 169:                 message.AlternateViews.Add(BodyView);
 170:  
 171:                 //message.Body = Body;
 172:  
 173:                 message.Priority = Priority;
 174:  
 175:                 message.SubjectEncoding = System.Text.Encoding.GetEncoding("ISO-8859-1");
 176:  
 177:                 message.BodyEncoding = System.Text.Encoding.GetEncoding("ISO-8859-1");
 178:  
 179:                 message.IsBodyHtml = true;
 180:  
 181:                 foreach (Attachment TempAttachment in Attachments)
 182:  
 183:                 {
 184:  
 185:                     message.Attachments.Add(TempAttachment);
 186:  
 187:                 }
 188:  
 189:                 System.Net.Mail.SmtpClient smtp = new System.Net.Mail.SmtpClient(Server, Port);
 190:  
 191:                 if (!string.IsNullOrEmpty(UserName) && !string.IsNullOrEmpty(Password))
 192:  
 193:                 {
 194:  
 195:                     smtp.Credentials = new System.Net.NetworkCredential(UserName, Password);
 196:  
 197:                 }
 198:  
 199:                 if (UseSSL)
 200:  
 201:                     smtp.EnableSsl = true;
 202:  
 203:                 else
 204:  
 205:                     smtp.EnableSsl = false;
 206:  
 207:                 smtp.Send(message);
 208:  
 209:             }
 210:  
 211:         }
 212:  
 213:         catch { throw; }
 214:  
 215:     }
 216:  
 217:  
 218:  
 219:     /// <summary>
 220:  
 221:     /// Sends a piece of mail asynchronous
 222:  
 223:     /// </summary>
 224:  
 225:     public void SendMailAsync()
 226:  
 227:     {
 228:  
 229:         try
 230:  
 231:         {
 232:  
 233:             ThreadPool.QueueUserWorkItem(delegate { SendMail(); });
 234:  
 235:         }
 236:  
 237:         catch { throw; }
 238:  
 239:     }
 240:  
 241:  
 242:  
 243:     #endregion
 244:  
 245:  
 246:  
 247:     #region Properties
 248:  
 249:  
 250:  
 251:     /// <summary>
 252:  
 253:     /// Any attachments that are included with this
 254:  
 255:     /// message.
 256:  
 257:     /// </summary>
 258:  
 259:     public List<Attachment> Attachments { get; set; }
 260:  
 261:  
 262:  
 263:     /// <summary>
 264:  
 265:     /// Any attachment (usually images) that need to be embedded in the message
 266:  
 267:     /// </summary>
 268:  
 269:     public List<LinkedResource> EmbeddedResources { get; set; }
 270:  
 271:  
 272:  
 273:     /// <summary>
 274:  
 275:     /// The priority of this message
 276:  
 277:     /// </summary>
 278:  
 279:     public MailPriority Priority { get; set; }
 280:  
 281:  
 282:  
 283:     /// <summary>
 284:  
 285:     /// Server Location
 286:  
 287:     /// </summary>
 288:  
 289:     public string Server { get; set; }
 290:  
 291:  
 292:  
 293:     /// <summary>
 294:  
 295:     /// User Name for the server
 296:  
 297:     /// </summary>
 298:  
 299:     public string UserName { get; set; }
 300:  
 301:  
 302:  
 303:     /// <summary>
 304:  
 305:     /// Password for the server
 306:  
 307:     /// </summary>
 308:  
 309:     public string Password { get; set; }
 310:  
 311:  
 312:  
 313:     /// <summary>
 314:  
 315:     /// Port to send the information on
 316:  
 317:     /// </summary>
 318:  
 319:     public int Port { get; set; }
 320:  
 321:  
 322:  
 323:     /// <summary>
 324:  
 325:     /// Decides whether we are using STARTTLS (SSL) or not
 326:  
 327:     /// </summary>
 328:  
 329:     public bool UseSSL { get; set; }
 330:  
 331:  
 332:  
 333:     /// <summary>
 334:  
 335:     /// Carbon copy send (seperate email addresses with a comma)
 336:  
 337:     /// </summary>
 338:  
 339:     public string CC { get; set; }
 340:  
 341:  
 342:  
 343:     /// <summary>
 344:  
 345:     /// Blind carbon copy send (seperate email addresses with a comma)
 346:  
 347:     /// </summary>
 348:  
 349:     public string Bcc { get; set; }
 350:  
 351:  
 352:  
 353:     #endregion
 354:  
 355: }

The code above is a helper class from my utility library. In it there are fields for To, From, the SMTP server location, etc. The field we're interested in is EmbeddedResources. That field is a list of LinkedResource. A LinkedResource is exactly like the name says, a linked resource. An image, etc. that is attached to the email and usable within it. In order to use it, you must first tell it where to look for the image (new LinkedResource(ImageLocation)) and then set a content ID (the ContentId property) which is just a string name. Once that is set, you can link to it from inside your email. For example, if we set the ContentId to "MyImage", we can use it like this:

   1: <html><body><img src='cid:MyImage' /></body></html>

That's it. With that set as the body of our text and the LinkedResource added to our email, we're good. It doesn't work 100% on all systems (gmail seems to fail), but for most email apps (Outlook, etc.) it works rather well. Anyway, I personally can only think of one use for this but maybe I'm wrong. Maybe you're not going to use this for "marketing" purposes (ie spam). You never know. So try it out and happy coding.



Comments