From 308ae71d5012ea6affdf19d10fbc9348acc666f5 Mon Sep 17 00:00:00 2001 From: kuberto773 Date: Wed, 26 Nov 2025 16:20:42 +0100 Subject: [PATCH 1/3] chore: extended email attachment contract --- .../ByteEmailAttachment.cs | 17 ++++++++++++++++- .../FilepathEmailAttachment.cs | 17 ++++++++++++++++- .../IEmailAttachment.cs | 6 +++++- 3 files changed, 37 insertions(+), 3 deletions(-) diff --git a/src/Madev.Utils.Infrastructure.Services.Mailing/ByteEmailAttachment.cs b/src/Madev.Utils.Infrastructure.Services.Mailing/ByteEmailAttachment.cs index 1095b94..39edf30 100644 --- a/src/Madev.Utils.Infrastructure.Services.Mailing/ByteEmailAttachment.cs +++ b/src/Madev.Utils.Infrastructure.Services.Mailing/ByteEmailAttachment.cs @@ -4,13 +4,28 @@ namespace Madev.Utils.Infrastructure.Services.Mailing { public class ByteEmailAttachment : IEmailAttachment { - public ByteEmailAttachment(string filename, byte[] content) + public ByteEmailAttachment(string filename, byte[] content, bool isInline = false, string? contentId = null, string? contentType = null) { Filename = filename ?? throw new ArgumentException($"{nameof(filename)} cannot be null."); Content = content ?? throw new ArgumentException($"{nameof(content)} cannot be empty."); + IsInline = isInline; + + if(IsInline && contentId == null) + { + throw new ArgumentException("If an attachment is inline, ContentId must be defined"); + } + ContentId = contentId; + + if(contentType != null) + { + ContentType = contentType; + } } public string Filename { get; } public byte[] Content { get; } + public string? ContentId { get; set; } + public bool IsInline { get; set;} + public string? ContentType { get; set; } = "application/octet-stream"; } } \ No newline at end of file diff --git a/src/Madev.Utils.Infrastructure.Services.Mailing/FilepathEmailAttachment.cs b/src/Madev.Utils.Infrastructure.Services.Mailing/FilepathEmailAttachment.cs index 6b72566..2ff3141 100644 --- a/src/Madev.Utils.Infrastructure.Services.Mailing/FilepathEmailAttachment.cs +++ b/src/Madev.Utils.Infrastructure.Services.Mailing/FilepathEmailAttachment.cs @@ -4,11 +4,26 @@ namespace Madev.Utils.Infrastructure.Services.Mailing { public class FilepathEmailAttachment : IEmailAttachment { - public FilepathEmailAttachment(string path) + public FilepathEmailAttachment(string path, bool isInline = false, string? contentId = null, string? contentType = null) { Path = path ?? throw new ArgumentException($"{nameof(path)} cannot be empty."); + IsInline = isInline; + + if (IsInline && contentId == null) + { + throw new ArgumentException("If an attachment is inline, ContentId must be defined"); + } + ContentId = contentId; + + if(contentType != null) + { + ContentType = contentType; + } } public string Path { get; } + public string? ContentId { get; set; } + public bool IsInline { get ; set ; } + public string? ContentType { get ; set ; } = "application/octet-stream"; } } \ No newline at end of file diff --git a/src/Madev.Utils.Infrastructure.Services.Mailing/IEmailAttachment.cs b/src/Madev.Utils.Infrastructure.Services.Mailing/IEmailAttachment.cs index 973acd8..a6343e1 100644 --- a/src/Madev.Utils.Infrastructure.Services.Mailing/IEmailAttachment.cs +++ b/src/Madev.Utils.Infrastructure.Services.Mailing/IEmailAttachment.cs @@ -1,4 +1,8 @@ namespace Madev.Utils.Infrastructure.Services.Mailing { - public interface IEmailAttachment{} + public interface IEmailAttachment{ + public bool IsInline { get; set; } + public string? ContentId { get; set; } + public string? ContentType { get; set; } + } } \ No newline at end of file From 9c573c1145215aee0494d34f8b7728a7a4425b31 Mon Sep 17 00:00:00 2001 From: kuberto773 Date: Wed, 26 Nov 2025 16:21:52 +0100 Subject: [PATCH 2/3] feat: Base64 email attachment --- .../MailkitEmailSender.cs | 20 +++++++++++- .../EmailBuilder.cs | 3 +- .../Base64EmailAttachment.cs | 31 +++++++++++++++++++ 3 files changed, 52 insertions(+), 2 deletions(-) create mode 100644 src/Madev.Utils.Infrastructure.Services.Mailing/Base64EmailAttachment.cs diff --git a/src/Madev.Utils.Infrastructure.Services.Mailing.Mailkit/MailkitEmailSender.cs b/src/Madev.Utils.Infrastructure.Services.Mailing.Mailkit/MailkitEmailSender.cs index 01f996e..039992e 100644 --- a/src/Madev.Utils.Infrastructure.Services.Mailing.Mailkit/MailkitEmailSender.cs +++ b/src/Madev.Utils.Infrastructure.Services.Mailing.Mailkit/MailkitEmailSender.cs @@ -96,7 +96,25 @@ private MimeMessage ConstructMessageBody(MimeMessage message, string htmlBody, s { foreach (var attachment in attachments) { - switch (attachment) + var convertedAttachment = attachment switch + { + FilepathEmailAttachment att => builder.Attachments.Add( + Path.GetFileName(att.Path), + File.ReadAllBytes(att.Path), + ContentType.Parse(att.ContentType) + ), + ByteEmailAttachment att => builder.Attachments.Add( + att.Filename, + att.Content, + ContentType.Parse(att.ContentType) + ), + Base64EmailAttachment att => builder.Attachments.Add( + att.FileName, + Convert.FromBase64String(att.Content), + ContentType.Parse(att.ContentType) + ), + _ => throw new InvalidOperationException("Unknown attachment type.") + }; { case FilepathEmailAttachment att: var filename = Path.GetFileName(att.Path); diff --git a/src/Madev.Utils.Infrastructure.Services.Mailing.MsGraph/EmailBuilder.cs b/src/Madev.Utils.Infrastructure.Services.Mailing.MsGraph/EmailBuilder.cs index 686debb..1c05113 100644 --- a/src/Madev.Utils.Infrastructure.Services.Mailing.MsGraph/EmailBuilder.cs +++ b/src/Madev.Utils.Infrastructure.Services.Mailing.MsGraph/EmailBuilder.cs @@ -57,7 +57,7 @@ public EmailBuilder Attachments(IEnumerable attachments) private FileAttachment ConvertToFileAttachment(IEmailAttachment attachment) { - return attachment switch + var convertedAttachment = attachment switch { ByteEmailAttachment att => new FileAttachment { @@ -71,6 +71,7 @@ private FileAttachment ConvertToFileAttachment(IEmailAttachment attachment) }, _ => throw new InvalidOperationException("Unknown attachment type.") }; + return convertedAttachment; } } } \ No newline at end of file diff --git a/src/Madev.Utils.Infrastructure.Services.Mailing/Base64EmailAttachment.cs b/src/Madev.Utils.Infrastructure.Services.Mailing/Base64EmailAttachment.cs new file mode 100644 index 0000000..ef9b78f --- /dev/null +++ b/src/Madev.Utils.Infrastructure.Services.Mailing/Base64EmailAttachment.cs @@ -0,0 +1,31 @@ +using System; + +namespace Madev.Utils.Infrastructure.Services.Mailing +{ + public class Base64EmailAttachment : IEmailAttachment + { + public Base64EmailAttachment(string filename, string content, bool isInline = false, string? contentId = null, string? contentType = null) + { + FileName = filename; + Content = content; + IsInline = isInline; + + if (IsInline && contentId == null) + { + throw new ArgumentException("If an attachment is inline, ContentId must be defined"); + } + ContentId = contentId; + + if(contentType != null) + { + ContentType = contentType; + } + } + + public string FileName { get; } + public string Content { get; } + public string? ContentId { get; set; } + public bool IsInline { get; set; } + public string? ContentType { get; set; } = "application/octet-stream"; + } +} \ No newline at end of file From e14555bdf45866344174f80cb0cc72f66e9cae7c Mon Sep 17 00:00:00 2001 From: kuberto773 Date: Wed, 26 Nov 2025 16:22:07 +0100 Subject: [PATCH 3/3] feat: inline attachments support --- .../MailkitEmailSender.cs | 14 ++++---------- .../EmailBuilder.cs | 19 +++++++++++++++++-- 2 files changed, 21 insertions(+), 12 deletions(-) diff --git a/src/Madev.Utils.Infrastructure.Services.Mailing.Mailkit/MailkitEmailSender.cs b/src/Madev.Utils.Infrastructure.Services.Mailing.Mailkit/MailkitEmailSender.cs index 039992e..c862864 100644 --- a/src/Madev.Utils.Infrastructure.Services.Mailing.Mailkit/MailkitEmailSender.cs +++ b/src/Madev.Utils.Infrastructure.Services.Mailing.Mailkit/MailkitEmailSender.cs @@ -115,17 +115,11 @@ private MimeMessage ConstructMessageBody(MimeMessage message, string htmlBody, s ), _ => throw new InvalidOperationException("Unknown attachment type.") }; + + if (attachment.IsInline) { - case FilepathEmailAttachment att: - var filename = Path.GetFileName(att.Path); - var content = File.ReadAllBytes(att.Path); - builder.Attachments.Add(filename, content); - break; - case ByteEmailAttachment att: - builder.Attachments.Add(att.Filename, att.Content); - break; - default: - throw new InvalidOperationException("Unknown attachment type."); + convertedAttachment.ContentId = attachment.ContentId; + convertedAttachment.ContentDisposition = new ContentDisposition(ContentDisposition.Inline); } } } diff --git a/src/Madev.Utils.Infrastructure.Services.Mailing.MsGraph/EmailBuilder.cs b/src/Madev.Utils.Infrastructure.Services.Mailing.MsGraph/EmailBuilder.cs index 1c05113..836db9f 100644 --- a/src/Madev.Utils.Infrastructure.Services.Mailing.MsGraph/EmailBuilder.cs +++ b/src/Madev.Utils.Infrastructure.Services.Mailing.MsGraph/EmailBuilder.cs @@ -61,16 +61,31 @@ private FileAttachment ConvertToFileAttachment(IEmailAttachment attachment) { ByteEmailAttachment att => new FileAttachment { - Name = att.Filename, ContentBytes = att.Content, ContentType = "application/octet-stream" + Name = att.Filename, + ContentBytes = att.Content, + ContentType = attachment.ContentType }, FilepathEmailAttachment att => new FileAttachment { Name = Path.GetFileName(att.Path), ContentBytes = File.ReadAllBytes(att.Path), - ContentType = "application/octet-stream" + ContentType = attachment.ContentType + }, + Base64EmailAttachment att => new FileAttachment + { + Name = att.FileName, + ContentBytes = Convert.FromBase64String(att.Content), + ContentType = attachment.ContentType }, _ => throw new InvalidOperationException("Unknown attachment type.") }; + + if (attachment.IsInline) + { + convertedAttachment.IsInline = true; + convertedAttachment.ContentId = attachment.ContentId; + } + return convertedAttachment; } }