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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1212838/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 11:04:38  来源:igfitidea点击:

C# sending mails with images inline using SmtpClient

c#inlinesmtpclient

提问by KdgDev

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. 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.

编辑:我没有使用网站或任何东西,甚至没有使用 IP 地址。图像位于硬盘驱动器上。发送时,它们应该是邮件的一部分。所以,我想我可能想使用一个标签......但我不太确定,因为我的电脑没有广播。

采纳答案by James McCormack

One solution that is often mentioned is to add the image as an Attachmentto the mail, and then reference it in the HTML mailbody using a cid:reference.

经常提到的一种解决方案是将图像作为 an 添加Attachment到邮件中,然后使用引用在 HTML 邮件正文中引用它cid:

However if you use the LinkedResourcescollection instead, the inline images will still appear just fine, but don't show as additional attachments to the mail. That's what we want to happen, so that's what I do here:

但是,如果您LinkedResources改为使用该集合,内嵌图像仍会显示得很好,但不会显示为邮件的附加附件。这就是我们想要发生的事情,所以这就是我在这里所做的:

using (var client = new SmtpClient())
{
    MailMessage newMail = new MailMessage();
    newMail.To.Add(new MailAddress("[email protected]"));
    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 AlternateViewto your MailMessageof type text/html. For completeness, you should also add an AlternateViewof type text/plain, containing a plain text version of the email for non-HTML mail clients.

注意:此解决方案AlternateView为您MailMessage的类型添加了text/html。为了完整起见,您还应该添加一个AlternateViewof type text/plain,其中包含用于非 HTML 邮件客户端的电子邮件的纯文本版本。

回答by ccalboni

What about converting images in Base64 strings? AFAIK this can be easily embedded within mail body.

如何转换 Base64 字符串中的图像?AFAIK 这可以很容易地嵌入到邮件正文中。

Take a look here.

看看这里

回答by msvcyc

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 附件类型,您在发送电子邮件时无需执行任何特殊操作即可在客户端上打开它。

回答by Lazarus

The HTML Email and the images are attachments so it's just a case of referring to the image(s) by their content ids, i.e.

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

这里似乎有全面的例子:Send Email with inline images

回答by Brandon

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;

回答by Nelson Parra

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.

最后,电子邮件以异步方式发送,因此用户不必等待发送。