简体   繁体   English

C#使用SmtpClient以内联方式发送带有图像的邮件

[英]C# sending mails with images inline using SmtpClient

SmtpClient() allows you to add attachments to your mails, but what if you wanna make an image appear when the mail opens, instead of attaching it? SmtpClient()允许您在邮件中添加附件,但是如果您想在邮件打开时显示图像而不是附加它,该怎么办?

As I remember, it can be done with about 4 lines of code, but I don't remember how and I can't find it on the MSDN site. 我记得,它可以使用大约4行代码完成,但我不记得我在MSDN网站上找不到它。

EDIT: I'm not using a website or anything, not even an IP address. 编辑:我没有使用网站或任何东西,甚至没有IP地址。 The image(s) are located on a harddrive. 图像位于硬盘上。 When sent, they should be part of the mail. 发送时,它们应该是邮件的一部分。 So, I guess I might wanna use an tag... but I'm not too sure, since my computer isn't broadcasting. 所以,我想我可能想要使用标签......但我不太确定,因为我的电脑没有广播。

One solution that is often mentioned is to add the image as an Attachment to the mail, and then reference it in the HTML mailbody using a cid: reference. 经常提到的一个解决方案是将图像作为Attachment添加到邮件中,然后使用cid: reference在HTML邮件主体中引用它。

However if you use the LinkedResources collection instead, the inline images will still appear just fine, but don't show as additional attachments to the mail. 但是,如果您使用LinkedResources集合,内联图像仍然会显示正常,但不会显示为邮件的附加附件。 That's what we want to happen , so that's what I do here: 这就是我们想要发生的事情 ,所以这就是我在这里所做的:

using (var client = new SmtpClient())
{
    MailMessage newMail = new MailMessage();
    newMail.To.Add(new MailAddress("you@your.address"));
    newMail.Subject = "Test Subject";
    newMail.IsBodyHtml = true;

    var inlineLogo = new LinkedResource(Server.MapPath("~/Path/To/YourImage.png"), "image/png");
    inlineLogo.ContentId = Guid.NewGuid().ToString();

    string body = string.Format(@"
            <p>Lorum Ipsum Blah Blah</p>
            <img src=""cid:{0}"" />
            <p>Lorum Ipsum Blah Blah</p>
        ", inlineLogo.ContentId);

    var view = AlternateView.CreateAlternateViewFromString(body, null, "text/html");
    view.LinkedResources.Add(inlineLogo);
    newMail.AlternateViews.Add(view);

    client.Send(newMail);
}

NOTE: This solution adds an AlternateView to your MailMessage of type text/html . 注意:此解决方案将AlternateView添加到text/html类型的MailMessage中。 For completeness, you should also add an AlternateView of type text/plain , containing a plain text version of the email for non-HTML mail clients. 为了完整起见,还应添加text/plain类型的AlternateView ,其中包含非HTML邮件客户端的纯文本版本的电子邮件。

The HTML Email and the images are attachments so it's just a case of referring to the image(s) by their content ids, ie HTML电子邮件和图像是附件,因此它只是通过内容ID引用图像的情况,即

    Dim A As System.Net.Mail.Attachment = New System.Net.Mail.Attachment(txtImagePath.Text)
    Dim RGen As Random = New Random()
    A.ContentId = RGen.Next(100000, 9999999).ToString()
    EM.Body = "<img src='cid:" + A.ContentId +"'>" 

There seems to be comprehensive examples here: Send Email with inline images 这里似乎有全面的示例: 使用内嵌图像发送电子邮件

When you say 4 lines of code, are you referring to this ? 当你说4行代码时,你指的是这个吗?

System.Net.Mail.Attachment inline = new System.Net.Mail.Attachment(@"imagepath\filename.png");
inline.ContentDisposition.Inline = true;

What about converting images in Base64 strings? 如何在Base64字符串中转换图像? AFAIK this can be easily embedded within mail body. AFAIK可以很容易地嵌入到邮件正文中。

Take a look here . 看看这里

The solution already posted is the best I have found, I'm just going to complete it with for example if you have multiple images. 已经发布的解决方案是我发现的最好的解决方案,我只是要完成它,例如,如果你有多个图像。

        string startupPath = AppDomain.CurrentDomain.RelativeSearchPath;
        string path = Path.Combine(startupPath, "HtmlTemplates", "NotifyTemplate.html");
        string body = File.ReadAllText(path);

        //General tags replacement.
        body = body.Replace("[NOMBRE_COMPLETO]", request.ToName);
        body = body.Replace("[ASUNTO_MENSAJE]", request.Subject);

        //Image List Used to replace into the template.
        string[] imagesList = { "h1.gif", "left.gif", "right.gif", "tw.gif", "fb.gif" };

        //Here we create link resources one for each image. 
        //Also the MIME type is obtained from the image name and not hardcoded.
        List<LinkedResource> imgResourceList = new List<LinkedResource>();
        foreach (var img in imagesList)
        {
            string imagePath = Path.Combine(startupPath, "Images", img);
            var image = new LinkedResource(imagePath, "image/" + img.Split('.')[1]);
            image.ContentId = Guid.NewGuid().ToString();
            image.ContentType.Name = img;
            imgResourceList.Add(image);
            body = body.Replace("{" + Array.IndexOf(imagesList, img) + "}", image.ContentId);
        }

        //Altern view for managing images and html text is created.
        var view = AlternateView.CreateAlternateViewFromString(body, null, "text/html");
        //You need to add one by one each link resource to the created view
        foreach (var imgResorce in imgResourceList)
        {
            view.LinkedResources.Add(imgResorce);
        }

        ThreadPool.QueueUserWorkItem(o =>
        {
            using (SmtpClient smtpClient = new SmtpClient(servidor, Puerto))
            {
                smtpClient.EnableSsl = true;
                smtpClient.DeliveryMethod = SmtpDeliveryMethod.Network;
                smtpClient.Timeout = 50000;
                smtpClient.UseDefaultCredentials = false;
                smtpClient.Credentials = new System.Net.NetworkCredential()
                {
                    UserName = UMail,
                    Password = password
                };
                using (MailMessage mailMessage = new MailMessage())
                {
                    mailMessage.IsBodyHtml = true;
                    mailMessage.From = new MailAddress(UMail);
                    mailMessage.To.Add(request.ToEmail);
                    mailMessage.Subject = "[NAPNYL] " + request.Subject;
                    mailMessage.AlternateViews.Add(view);
                    smtpClient.Send(mailMessage);
                }
            }
        });

As you can see you have an array of image names, it is important that the images are in the same folder because it is pointing to the same output folder. 正如您所看到的,您有一系列图像名称,因此图像位于同一文件夹中非常重要,因为它指向同一个输出文件夹。

Finally the email is sent as async so the user doesn't have to wait for it to be sent. 最后,电子邮件将作为异步发送,因此用户无需等待其发送。

The process of making an image appear on the client when the mail is opened is a client function. 打开邮件时,在客户端上显示图像的过程是客户端功能。 As long as the client knows how to render the image & has not blocked any image content it will open it right away. 只要客户端知道如何渲染图像并且没有阻止任何图像内容,它就会立即打开它。 You do not have to do anything special while sending the email to make it open on the client as long as you have correctly specified the image mime attachment type. 只要您正确指定了图像mime附件类型,在发送电子邮件以使其在客户端上打开时,您不必执行任何特殊操作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM