Embedded images replaced with cid linked resources. (#313)

* Added logic to replace embedded images with linked resources

* Added alt text for images and replaced NewtonSoft with Text.Json

* Fix draft mime preparation

* Fix crashes for signatures without images.

---------

Co-authored-by: Burak Kaan Köse <bkaankose@outlook.com>
This commit is contained in:
Tiktack
2024-08-11 23:58:54 +02:00
committed by GitHub
parent 983bc21448
commit 5912adff93
23 changed files with 148 additions and 253 deletions

View File

@@ -1,9 +1,12 @@
using System.IO;
using System;
using System.IO;
using System.Text;
using Google.Apis.Gmail.v1.Data;
using HtmlAgilityPack;
using MimeKit;
using MimeKit.IO;
using MimeKit.IO.Filters;
using MimeKit.Utils;
using Wino.Core.Domain;
using Wino.Core.Domain.Entities;
@@ -48,5 +51,71 @@ namespace Wino.Core.Extensions
return new AddressInformation() { Name = address.Name, Address = address.Address };
}
/// <summary>
/// Sets html body replacing base64 images with cid linked resources.
/// Updates text body based on html.
/// </summary>
/// <param name="bodyBuilder">Body builder.</param>
/// <param name="htmlContent">Html content that can have embedded images.</param>
/// <returns>Body builder with set HtmlBody.</returns>
public static BodyBuilder SetHtmlBody(this BodyBuilder bodyBuilder, string htmlContent)
{
if (string.IsNullOrEmpty(htmlContent)) return bodyBuilder;
var doc = new HtmlDocument();
doc.LoadHtml(htmlContent);
var imgNodes = doc.DocumentNode.SelectNodes("//img");
if (imgNodes != null)
{
foreach (var node in imgNodes)
{
var src = node.GetAttributeValue("src", string.Empty);
if (string.IsNullOrEmpty(src)) continue;
if (!src.StartsWith("data:image"))
{
continue;
}
var parts = src.Substring(11).Split([";base64,"], StringSplitOptions.None);
string mimeType = parts[0];
string base64Content = parts[1];
var alt = node.GetAttributeValue("alt", $"Embedded_Image.{mimeType}");
// Convert the base64 content to binary data
byte[] imageData = Convert.FromBase64String(base64Content);
// Create a new linked resource as MimePart
var image = new MimePart("image", mimeType)
{
ContentId = MimeUtils.GenerateMessageId(),
Content = new MimeContent(new MemoryStream(imageData)),
ContentDisposition = new ContentDisposition(ContentDisposition.Inline),
ContentDescription = alt.Replace(" ", "_"),
FileName = alt,
ContentTransferEncoding = ContentEncoding.Base64
};
bodyBuilder.LinkedResources.Add(image);
node.SetAttributeValue("src", $"cid:{image.ContentId}");
}
}
bodyBuilder.HtmlBody = doc.DocumentNode.InnerHtml;
if (!string.IsNullOrEmpty(bodyBuilder.HtmlBody))
{
bodyBuilder.TextBody = HtmlAgilityPackExtensions.GetPreviewText(bodyBuilder.HtmlBody);
}
return bodyBuilder;
}
}
}