Встраивание изображения .jpg (представление строки base64) в тело сообщения электронной почты (System.Net.Mail) - PullRequest
0 голосов
/ 24 января 2019

Я могу правильно преобразовать изображение jpg в base64String. Но у меня возникают проблемы с использованием этой преобразованной строки изображения и LinkedResource для встраивания ее в тело письма. Изображение появляется в виде значка не найденного изображения в теле письма. Любая помощь будет принята с благодарностью.

Я следовал примеру по этой ссылке: Выполните итерацию по строке html, чтобы найти все теги img и заменить значения атрибута src

Я использую HtmlAgilityPack (пакет nuget) для нацеливания на элемент img с кодом ниже.

private string embedImageInMail(string html)
       {
            HtmlAgilityPack.HtmlDocument doc = new 
HtmlAgilityPack.HtmlDocument();
            doc.LoadHtml(html);
            doc.DocumentNode.Descendants("img").Where(e =>
            {
                string src = e.GetAttributeValue("src", null) ?? "";
                return !string.IsNullOrEmpty(src) && src.StartsWith("data:image");
            })
            .ToList()
            .ForEach(x =>
            {
                string currentSrcValue = x.GetAttributeValue("src", null);
                currentSrcValue = currentSrcValue.Split(',')[1];    //Base64 part of string
                byte[] imageData = Convert.FromBase64String(currentSrcValue);
                string contentId = Guid.NewGuid().ToString();
                using (MemoryStream ms = new MemoryStream(imageData))
                {
                    LinkedResource inline = new LinkedResource(ms, "image/jpeg");
                    inline.ContentId = contentId;
                    inline.TransferEncoding = System.Net.Mime.TransferEncoding.Base64;
                    x.SetAttributeValue("src", "cid:" + inline.ContentId);
                }
            });

        return doc.DocumentNode.OuterHtml; 
    }

Параметр html, переданный функции, содержит тег img с src, равным кодировке base64 изображения. То, что возвращается из этой функции, присваивается message.body письма.

1 Ответ

0 голосов
/ 20 февраля 2019

Решено следующими решениями в других постах.Если кто-то еще попытается сделать то же самое и у меня возникнут проблемы, как я, я опубликую код ниже.

По сути, мне пришлось сохранить LinkedResource (изображения) в html в список, а затем выполнить итерацию по этому списку и добавить все изображения в AlternateView вне цикла foreach.

 // Embeds image to properly show in Email. Image element to show in html will not work in Email body. 
                        // https://stackoverflow.com/questions/39785600/iterate-through-an-html-string-to-find-all-img-tags-and-replace-the-src-attribut
                        // XmlAgilityPack gets used here to parse html string. 
                        List<LinkedResource> linkedResources = new List<LinkedResource>(); 
                        HtmlAgilityPack.HtmlDocument doc = new HtmlAgilityPack.HtmlDocument();
                        int increment = 0; 
                        doc.LoadHtml(tempMsg);
                        doc.DocumentNode.Descendants("img").Where(z =>
                            {
                                string src = z.GetAttributeValue("src", null) ?? "";
                                return !string.IsNullOrEmpty(src) && src.StartsWith("data:image");
                            })
                            .ToList()
                            .ForEach(x =>
                            {
                                string currentSrcValue = x.GetAttributeValue("src", null);
                                currentSrcValue = currentSrcValue.Split(',')[1];    //Base64 part of string
                                byte[] imageData = Convert.FromBase64String(currentSrcValue);
                                string id = Guid.NewGuid().ToString();
                                increment++;

                                LinkedResource inlineImage = new LinkedResource(new MemoryStream(imageData), System.Net.Mime.MediaTypeNames.Image.Jpeg);
                                inlineImage.ContentType.Name = "img " + increment; 
                                inlineImage.ContentId = id;
                                inlineImage.TransferEncoding = System.Net.Mime.TransferEncoding.Base64;
                                x.SetAttributeValue("src", "cid:" + inlineImage.ContentId);
                                linkedResources.Add(inlineImage);
                            });

                        // Append multiple images from template to email message.
                        // https://stackoverflow.com/questions/7048758/how-to-embed-multiple-images-in-email-body-using-net
                        // Write html to message.body 
                        AlternateView altView = AlternateView.CreateAlternateViewFromString(doc.DocumentNode.OuterHtml, null, "text/html");
                        linkedResources.ForEach(x=>altView.LinkedResources.Add(x));
                        message.AlternateViews.Add(altView);

                        String[] attachments = txtAttachFiles.Text.Split(';');
                        foreach (String filename in attachments)
                        {
                            if (File.Exists(filename))
                            {
                                Attachment attachment = new Attachment(filename);
                                message.Attachments.Add(attachment);
                            }
                        }

                        // loop is set to 1 in the app.config file so technically this for loop is not needed, but will keep this loop just in case. 
                        for (int loop = 0; loop < Convert.ToInt32(ConfigurationManager.AppSettings["loop"]); loop++)
                        {
                            SmtpClient smtp = new SmtpClient();
                            smtp.Host = ConfigurationManager.AppSettings["mailHost"];
                            smtp.Port = Int32.Parse(ConfigurationManager.AppSettings["mailPort"]);
                            smtp.UseDefaultCredentials = Convert.ToBoolean(ConfigurationManager.AppSettings["mailDefaultCredentials"]);
                            smtp.Send(message);
                        }
                    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...