【问题标题】:Send html email with embedded image and plain text with same image as attachment in C#在 C# 中发送带有嵌入图像和带有与附件相同图像的纯文本的 html 电子邮件
【发布时间】:2011-09-28 06:32:02
【问题描述】:

我希望发送一封带有纯文本和 html 版本的电子邮件。电子邮件需要一张图片(不是我可以在其他地方托管的图片),如果客户以 html 格式查看它,它应该被嵌入,并附加到纯文本视图中。

这是否可能适用于所有常见的客户?

我最接近的是将图像创建为附件(而不是链接资源),然后在 html 中使用 cid:filename.jpg 引用它。但是这在 gmail 中不起作用(它不会在 html 中显示图像)。

【问题讨论】:

    标签: c# email html-email system.net.mail


    【解决方案1】:

    此代码 sn-p 适用于 Outlook 2010 和 gmail。我通过暂时将纯文本部分放在电子邮件的最后来测试纯文本电子邮件,这使得 gmail 使用它。

    它还展示了一些其他很酷的东西,例如电子邮件模板和标签替换。

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

    【讨论】:

    • 使用文件名作为 CID 是不安全的 - 例如,它可以包含空格,尤其是图像不会在 Gmail 中显示。最好的选择是 Guid.NewGuid().ToString()
    • 示例,EmailTemplates.sendpicture 的内容是什么?
    【解决方案2】:

    纯文本视图,正是如此。它是纯文本,没有可见的图像。您可以附上图片,但不能让他们查看。

    查看 Outlook 发送的原始电子邮件,例如如何显示内联附件。举个例子,这里有一些其他人做的代码:http://blog.devexperience.net/en/12/Send_an_Email_in_CSharp_with_Inline_attachments.aspx

    -- 显然上面的链接不再有效 - 一个快速的谷歌提供了以下示例来内联图片

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-04-07
      • 2012-07-29
      • 2021-10-31
      • 2011-04-16
      • 1970-01-01
      • 2015-07-29
      • 2011-12-27
      相关资源
      最近更新 更多