I wish to send an email, with a plain text and html version. The email needs an image to go with it (not one I can host somewhere else), it should be embedded if the client
This code snippet works in outlook 2010 and gmail. I test the plain text email by temporarily putting the plain text part last in the email, which makes gmail use that.
It also demonstrates some other cool stuff such as email templates and tag substitution.
public void SendEmailWithPicture(string email, byte[] image)
{
string filename = "AttachmentName.jpg";
LinkedResource linkedResource = new LinkedResource(new MemoryStream(image), "image/jpg");
linkedResource.ContentId = filename;
linkedResource.ContentType.Name = filename;
this.Send(
EmailTemplates.sendpicture,
this.Subjects.SendPicture,
new List() { email },
this.ReplyTo,
tagValues: new Dictionary() { { "ImageAttachmentName", "cid:" + filename } },
htmlLinkedResources: new List() { linkedResource }
);
}
private void Send(EmailTemplates template, string subject, List to, string replyTo,
Dictionary tagValues = null, List attachments = null, List htmlLinkedResources = null)
{
try
{
MailMessage mailMessage = new MailMessage();
// Set up the email header.
to.ForEach(t => mailMessage.To.Add(new MailAddress(t)));
mailMessage.ReplyToList.Add(new MailAddress(replyTo));
mailMessage.Subject = subject;
string fullTemplatePath = Path.Combine(this.TemplatePath, EMAIL_TEMPLATE_PATH);
// Load the email bodies
var htmlBody = File.ReadAllText(Path.Combine(fullTemplatePath, Path.ChangeExtension(template.ToString(), "html")));
var textBody = File.ReadAllText(Path.Combine(fullTemplatePath, Path.ChangeExtension(template.ToString(), "txt")));
// Replace the tags in the emails
if (tagValues != null)
{
foreach (var entry in tagValues)
{
string tag = "{{" + entry.Key + "}}";
htmlBody = htmlBody.Replace(tag, entry.Value);
textBody = textBody.Replace(tag, entry.Value);
}
}
// Create plain text alternative view
string baseTxtTemplate = File.ReadAllText(Path.Combine(fullTemplatePath, TXT_BASE_TEMPLATE));
textBody = baseTxtTemplate.Replace(TAG_CONTENT, textBody);
AlternateView textView = AlternateView.CreateAlternateViewFromString(textBody, new System.Net.Mime.ContentType("text/plain"));
// Create html alternative view
string baseHtmlTemplate = File.ReadAllText(Path.Combine(fullTemplatePath, HTML_BASE_TEMPLATE));
htmlBody = baseHtmlTemplate.Replace(TAG_CONTENT, htmlBody);
AlternateView htmlView = AlternateView.CreateAlternateViewFromString(htmlBody, new System.Net.Mime.ContentType("text/html"));
// Add any html linked resources
if (htmlLinkedResources != null)
{
htmlLinkedResources.ForEach(lr => htmlView.LinkedResources.Add(lr));
htmlLinkedResources.ForEach(lr => textView.LinkedResources.Add(lr));
}
// Add the two views (gmail will always display plain text version if its added last)
mailMessage.AlternateViews.Add(textView);
mailMessage.AlternateViews.Add(htmlView);
// Add any attachments
if (attachments != null)
{
attachments.ForEach(a => mailMessage.Attachments.Add(a));
}
// Send the email.
SmtpClient smtp = new SmtpClient();
smtp.Send(mailMessage);
}
catch (Exception ex)
{
throw new Exception(String.Format("Error sending email (to:{0}, replyto:{1})", String.Join(",", to), replyTo), ex);
}
}
Plain text view, is exactly that. It is plain text, it has no images visible. You can attach a picture, but you cant make them view it.
Take a look at the raw email outlook sends for example on how to show inline attachments. As an example heres some code someone else did: http://blog.devexperience.net/en/12/Send_an_Email_in_CSharp_with_Inline_attachments.aspx
-- Apparently the above link is no longer valid - a quick google provided the following example to inline a picture
string htmlBody = "<html><body><h1>Picture</h1><br><img src=\"cid:Pic1\"></body></html>";
AlternateView avHtml = AlternateView.CreateAlternateViewFromString
(htmlBody, null, MediaTypeNames.Text.Html);
// Create a LinkedResource object for each embedded image
LinkedResource pic1 = new LinkedResource("pic.jpg", MediaTypeNames.Image.Jpeg);
pic1.ContentId = "Pic1";
avHtml.LinkedResources.Add(pic1);
// Add the alternate views instead of using MailMessage.Body
MailMessage m = new MailMessage();
m.AlternateViews.Add(avHtml);
// Address and send the message
m.From = new MailAddress("email1@host.com", "From guy");
m.To.Add(new MailAddress("email2@host.com", "To guy"));
m.Subject = "A picture using alternate views";
SmtpClient client = new SmtpClient("mysmtphost.com");
client.Send(m);