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

Posted

技术标签:

【中文标题】C# 使用 SmtpClient 发送带有内联图像的邮件【英文标题】:C# sending mails with images inline using SmtpClient 【发布时间】:2010-11-15 19:38:02 【问题描述】:

SmtpClient() 允许您在邮件中添加附件,但是如果您想在邮件打开时显示图像而不是附加图像怎么办?

据我所知,大约 4 行代码就可以完成,但我不记得是怎么做的,在 MSDN 网站上也找不到。

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

【问题讨论】:

@JamesMcCormack 我一定很早就错过了。更新 查看此链接。它已准备好使用方法用于 png 文件流的多个内联附件以及 pdf/excel 文件流的一般附件。 ***.com/questions/33665280/… 【参考方案1】:

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

看看here。

【讨论】:

我仍然坚信必须将其视为一种选择。sweeting.org/mark/blog/2005/07/12/… 图像无论如何都会被base64编码,这与让它出现在html电子邮件中无关。 -1 不是来自我,但答案有点离题。 我想说的是,如果你想在 HTML 文档中嵌入图像,你可以。只需将其编码为 base64 并将生成的字符串放在 img 标签的 src 属性中。看看这里:tekasarts.com/stuff/base_64_img.html 我所做的是: - 在 photoshop 中渐变填充 gif - Convert.ToBase64String() 图像字节 - 粘贴到 HTML 文档据我所知,这可能不是首选解决方案,但它是在主题上,在某种程度上是一个很好的解决方案。 为什么这被否决了?它是正确的。您可以在数据 url 中嵌入图像。 问题是关于电子邮件,而不是 HTML。许多流行的邮件客户端(例如所有版本的 Outlook)不会显示 Base64 编码的图像。【参考方案2】:

打开邮件时在客户端显示图像的过程是客户端功能。只要客户端知道如何渲染图像并且没有阻止任何图像内容,它就会立即打开它。只要您正确指定了图像 mime 附件类型,就无需在发送电子邮件时进行任何特殊操作以使其在客户端上打开。

【讨论】:

再次阅读问题。他想附加图像并将其显示在正文中。 这确实更好地作为对已接受答案的评论。【参考方案3】:

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 +"'>" 

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

【讨论】:

这行得通,图像确实出现在邮件正文的正确位置,但我猜 OP 不希望图像也出现在附件列表中。我相信正确的答案是使用 LinkedResource - 请参阅我的答案。 什么是cid?我们是否需要在 mailmessage 对象上设置一些设置才能使用 MIME?另外,为什么您使用 100000、9999999 之间的随机数作为内容 ID?我在 powershell 中使用您的代码,但图像显示为红十字。 当您需要唯一 ID 时,不应使用随机数生成器。使用 GUID 或其他保证唯一的东西。 它不需要是全球唯一的,但这最终只是一个品味问题。这只是一个示例,不代表生产就绪代码。 如果其内容配置是“内联”而不是“附件”,它将不会显示在邮件客户端附件中(不在 Outlook 中)。【参考方案4】:

你说的4行代码,是指this吗?

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

【讨论】:

您在答案中的链接不再有效?【参考方案5】:

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

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

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);

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

【讨论】:

最佳实践是在邮件中包含 2 个 AlternateViews,第一个是包含纯文本邮件正文的“text/plain”类型。第二个视图是我上面详述的“text/html”视图。 你是一个节省者。经过2天的搜索......哦 这是一个很好的解决方案。感谢您添加它。我还建议添加如何使用 Image 元素来做到这一点。我使用带有 LinkedResource 的 MemoryStream 来管理它。效果很好,...一旦我在获得 Stream 后重置 .Position 属性! Server.MapPath -> “服务器”在哪里定义? 为了让这个工作正常进行,我必须在 LinkedResource("image/png") 的创建中包含 MIME 内容。我使用.Net 4.5【参考方案6】:

已经发布的解决方案是我找到的最好的解决方案,例如,如果您有多个图像,我将完成它。

        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);
                
            
        );

如您所见,您有一组图像名称,图像位于同一个文件夹中很重要,因为它指向同一个输出文件夹。

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

【讨论】:

以上是关于C# 使用 SmtpClient 发送带有内联图像的邮件的主要内容,如果未能解决你的问题,请参考以下文章

使用 SmtpClient 发送邮件时图像中断

使用 SmtpClient 通过 C# 发送 HTML 电子邮件

c# SmtpClient 类无法使用 gmail 发送电子邮件

如何使用 SmtpClient.SendAsync 发送带有附件的电子邮件?

当我们使用 phpMailer 发送带有动态内容的邮件时,如何在电子邮件正文中显示多个内联图像

使用 SmtpClient 时如何保存电子邮件而不是发送?