最近项目需要,要在某种情况下,给用户发送邮件,以前的做法就是把邮件内容做成模板,在使用的时候,代码里面组装成HTML格式的邮件,只能是纯文本的。现在需要给邮件加背景图片以及一些图片,找寻了很多,发现很多人在做这些事情,其中有从网上看到的,也有我自己实现的,现在汇总如下:
.NET(C#):使用SmtpClient发送带有图片和附件的电子邮件
使用SmtpClient发送邮件的步骤就不讲了,在网上你可以找到太多的资料了,这里说一些需要注意的地方:如果邮件的内容是HTML,设置MailMessage.IsBodyHtml为True,这样邮件才能够被正确以HTML形式读取。在HTML中引用资源使用cid:xxx,xxx是附件的ContentId属性。同时也可以在MailMessage中的AlternateViews中加入AlternateView来指定电子邮件内容的不同格式。通过AlternativeView的LinkedResources来加入引用文件。引用也是通过LinkedResource的ContentId来设置的。事实上这个ContentId属性是来自AttachmentBase类型,而Attachment,AlternateView和LinkedResource类型都继承与这个类.
最后某些SMTP服务器可能不支持SSL传输,因此SmtpClient的EnableSsl只能为false(否则会有异常抛出)。这种情况下,我们就需要使用下面列出的第二种方式,发送邮件。
第一种方式,使用Attachment:
//图像附件
var attach = new Attachment(@"D:\test.jpg", MediaTypeNames.Image.Jpeg);
//设置ContentId
attach.ContentId = "pic";
//ZIP附件
var attach2 = new Attachment(@"D:\test.zip", "application/x-zip-compressed");
mail.Attachments.Add(attach);
mail.Attachments.Add(attach2);
//因为默认编码是ASCII
mail.SubjectEncoding = Encoding.UTF8;
//HTML内容
mail.Body = "<img src=\"cid:pic\"/><p>设置图片。</p>";
第二种方式,使用LinkedResource,直接从绝对路径载入图片或者附件:
来源于:Using LinkedResource Class for Sending HTML E-mail in .NET 2.0
Listing 1 – Sample for HTML view
// to embed images, we need to use the prefix 'cid' in the img src value
string htmlBody = "<b>This is the embedded image file.</b><DIV> </DIV>";
htmlBody += "<img alt=\"\" hspace=0 src=\"cid:uniqueId\" align=baseline border=0 >";
htmlBody += "<DIV> </DIV><b>This is the end of Mail...</b>";
AlternateView htmlView = AlternateView.CreateAlternateViewFromString(htmlBody,
null, "text/html");
Then we need to create a LinkedResource object and add it to the AlternateView's LinkedResources Collection. Again, before adding this be sure to set the ContentId property of LinkedResource class as that unique value set in the HTML tag of AlternateView (i.e. cid). Here we need to set the TransferEncoding property of LinkedResource to Base64 which is the default for the image.
Listing 2 – Sample for Image resource
// create the image resource from image path using LinkedResource class..
LinkedResource imageResource = new LinkedResource("c:\\attachment\\image1.jpg" ,
"image/jpeg");
imageResource.ContentId = "uniqueId";
imageResource.TransferEncoding = TransferEncoding.Base64;
Here "uniqueId" is the common unique cid value. Let us add the above "imageResource" to "htmlView."
// adding the imaged linked to htmlView...
htmlView.LinkedResources.Add(imageResource);
Then we have to add this htmlView (AlternateView object) to the MailMessage object.
// add the view
mail.AlternateViews.Add(htmlView);
第三种方式,还是使用LinkedResource,不过是从stream中读出附件,然后添加进去,这个附件Build Action是Embedded Resource形式的:
MemoryStream ms = null;
strFile = "Modules.Resources.images.test.png";
using (Stream stream = asm.GetManifestResourceStream(strFile))
{
byte[] bs = new byte[stream.Length];
stream.Read(bs, 0, (int)stream.Length);
ms = new MemoryStream(bs);
}
LinkedResource lr = new LinkedResource(ms, "image/png");
其他和第二种方式类似,另外,背景图的添加类似于在代码里面加CSS style,
//NO body += "</HEAD><BODY style=\"background: url(c:\\\\tt\\\\1.jpg) no-repeat fixed center;\">";
//NO body += "</HEAD><BODY style=background-image:url(cid:backgroudpic);background-repeat:no-repeat;background-attachment:fixed;background-position:center;>";
//NO body += "</HEAD><BODY style=\"background-image:url(cid:backgroudpic) background-repeat:no-repeat;\">";
//NO body += "</HEAD><BODY style=\"background-image:url(cid:backgroudpic);background-repeat:no-repeat;\">";
//NO body += "</HEAD><BODY style=background-image:url(cid:backgroudpic);background-repeat:no-repeat;>";
//NO body += "</HEAD><BODY style=\"background-repeat:no-repeat;background-image:url(cid:backgroudpic);\">";
//NO body += "</HEAD><BODY style=\"background: no-repeat fixed center url(cid:backgroudpic);\">";
///
//OK body += "</HEAD><BODY style=background-image:url(cid:backgroudpic);><FONT face=Arial size=3>";
//OK body += "</HEAD><BODY style=\"background-image:url(cid:backgroudpic);\"><FONT face=Arial size=3>";
//OK body += "</HEAD><BODY style=\"background: url(cid:backgroudpic);\"><FONT face=Arial size=3>";
经测试,发现在C#代码中加入style,而且使用cid的形式,还不尽如人意,代码中NO的形式,是不能工作的形式,为什么不能加入no-repeat, fixed, center,原因还没找到。
使用CDO.Message发送带有图片和附件的电子邮件
CDO.Message msg = new CDO.Message();
CDO.IConfiguration configuration = msg.Configuration;
ADODB.Fields fields = configuration.Fields;
ADODB.Field field = fields["http://schemas.microsoft.com/cdo/configuration/smtpserver"];
field.Value = mailOptions.Server;
fields.Update();
msg.Send();
其中fields可以参考: http://msdn.microsoft.com/en-us/library/exchange/ms872853(v=exchg.65).aspx
网上类似的资料很多,不过都是VB的,我还没找到C#中实现的。给出一个VB实现的,Embed an image in CDO e-mail
Here’s a simple example of how to embed an image using CDO from ASP vbscript.bed an image in CDO e-mail
<%
Dim CDO, RBP
Set CDO = Server.CreateObject("CDO.Message")
CDO.MimeFormatted = True
CDO.To = "test@test.com"
CDO.From = """Test User"" test@test.com"
CDO.Subject = "E-mail with embedded image"
CDO.HTMLBody = "<html>Check this out: <img src=""cid:test.gif""></html>"
Set RBP = CDO.AddRelatedBodyPart(Server.MapPath("/images/test.gif"), "test.gif", 1)
RBP.Fields.Item("urn:schemas:mailheader:Content-ID") = "<test.gif>"
RBP.Fields.Update
CDO.Send
%>
这种我们如何用在C#中呢?
CDO.Message msg = new CDO.Message();
msg.AddAttachment(@"c:\tt\1.jpg", null, null);
msg.AddRelatedBodyPart(@"c:\tt\test.png", "uniqueId", CDO.CdoReferenceType.cdoRefTypeId, null, null);
这个是在设置完msg.HTMLBody之后,不过现在这种方式只能从绝对路径中获得文件,如何从stream中获得并发送之,一直没有找到方法?