From 3841681c52ccf1fa3c3eb7cd229d87c5ac5fa717 Mon Sep 17 00:00:00 2001 From: Jakub Date: Thu, 11 Jun 2026 12:50:01 +0200 Subject: [PATCH 1/4] refactor: use EmailMessage class instead of long parameters --- .../MailkitEmailSender.cs | 128 ++++++++---------- .../EmailBuilder.cs | 39 ++++++ .../MsGraphEmailSender.cs | 51 ++++--- .../EmailMessage.cs | 15 ++ .../IEmailSender.cs | 10 +- 5 files changed, 140 insertions(+), 103 deletions(-) create mode 100644 src/Madev.Utils.Infrastructure.Services.Mailing/EmailMessage.cs diff --git a/src/Madev.Utils.Infrastructure.Services.Mailing.Mailkit/MailkitEmailSender.cs b/src/Madev.Utils.Infrastructure.Services.Mailing.Mailkit/MailkitEmailSender.cs index b20c8f1..6bdbb8c 100644 --- a/src/Madev.Utils.Infrastructure.Services.Mailing.Mailkit/MailkitEmailSender.cs +++ b/src/Madev.Utils.Infrastructure.Services.Mailing.Mailkit/MailkitEmailSender.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.IO; +using System.Threading; using System.Threading.Tasks; using MailKit; using MailKit.Net.Smtp; @@ -31,106 +32,95 @@ public MailkitEmailSender(IOptions options) } } - public async Task SendTextEmailAsync(string toAddress, string subject, string body, IEnumerable attachments = null) + public async Task SendHtmlEmailAsync(EmailMessage message, CancellationToken cancellationToken = default) { - attachments ??= new List(); - await SendTextEmailAsync(new List() { toAddress }, subject, body, attachments); + var mimeMessage = ConstructHtmlMimeMessage(message); + await SendMimeMessageAsync(mimeMessage, cancellationToken); } - public async Task SendTextEmailAsync(IEnumerable toAddress, string subject, string body, IEnumerable attachments = null) + public async Task SendTextEmailAsync(EmailMessage message, CancellationToken cancellationToken = default) { - attachments ??= new List(); - var message = ConstructTextMimeMessage(toAddress, subject, body, attachments); - await SendMimeMessageAsync(message); + var mimeMessage = ConstructTextMimeMessage(message); + await SendMimeMessageAsync(mimeMessage, cancellationToken); } - public async Task SendHtmlEmailAsync(string toAddress, string subject, string body, IEnumerable attachments = null) + private MimeMessage ConstructHtmlMimeMessage(EmailMessage message) { - attachments ??= new List(); - await SendHtmlEmailAsync(new List() { toAddress }, subject, body, attachments); + var mimeMessage = new MimeMessage(); + mimeMessage = ConstructMessageHeaders(mimeMessage, message); + mimeMessage = ConstructMessageBody(mimeMessage, message.Body, null, message.Attachments); + return mimeMessage; } - public async Task SendHtmlEmailAsync(IEnumerable toAddress, string subject, string body, IEnumerable attachments = null) + private MimeMessage ConstructTextMimeMessage(EmailMessage message) { - attachments ??= new List(); - var message = ConstructHtmlMimeMessage(toAddress, subject, body, attachments); - await SendMimeMessageAsync(message); + var mimeMessage = new MimeMessage(); + mimeMessage = ConstructMessageHeaders(mimeMessage, message); + mimeMessage = ConstructMessageBody(mimeMessage, null, message.Body, message.Attachments); + return mimeMessage; } - private MimeMessage ConstructTextMimeMessage(IEnumerable toAddress, - string subject, string body, IEnumerable attachments) + private MimeMessage ConstructMessageHeaders(MimeMessage mimeMessage, EmailMessage message) { - var message = new MimeMessage(); - message = ConstructMessageHeaders(message, toAddress, subject); - message = ConstructMessageBody(message, null, body, attachments); - return message; - } - - private MimeMessage ConstructHtmlMimeMessage(IEnumerable toAddress, - string subject, string body, IEnumerable attachments) - { - var message = new MimeMessage(); - message = ConstructMessageHeaders(message, toAddress, subject); - message = ConstructMessageBody(message, body, null, attachments); - return message; - } - - private MimeMessage ConstructMessageHeaders(MimeMessage message, IEnumerable toAddress, string subject) - { - message.From.Add(MailboxAddress.Parse(_options.Sender ?? _options.Username)); - foreach (var address in toAddress) + mimeMessage.From.Add(MailboxAddress.Parse(message.From ?? _options.Sender ?? _options.Username)); + foreach (var address in message.To) { - message.To.Add(MailboxAddress.Parse(address)); + mimeMessage.To.Add(MailboxAddress.Parse(address)); } - message.Subject = subject; - return message; + foreach (var address in message.Cc) + { + mimeMessage.Cc.Add(MailboxAddress.Parse(address)); + } + foreach (var address in message.Bcc) + { + mimeMessage.Bcc.Add(MailboxAddress.Parse(address)); + } + mimeMessage.Subject = message.Subject; + return mimeMessage; } - private MimeMessage ConstructMessageBody(MimeMessage message, string htmlBody, string textBody, IEnumerable attachments) + private MimeMessage ConstructMessageBody(MimeMessage message, string? htmlBody, string? textBody, IEnumerable attachments) { var builder = new BodyBuilder(); builder.HtmlBody = htmlBody; builder.TextBody = textBody; - if (attachments != null) + foreach (var attachment in attachments) { - foreach (var attachment in attachments) + 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.") + }; + + if (attachment.IsInline) { - 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.") - }; - - if (attachment.IsInline) - { - convertedAttachment.ContentId = attachment.ContentId; - convertedAttachment.ContentDisposition = new ContentDisposition(ContentDisposition.Inline); - } + convertedAttachment.ContentId = attachment.ContentId; + convertedAttachment.ContentDisposition = new ContentDisposition(ContentDisposition.Inline); } } message.Body = builder.ToMessageBody(); return message; } - private async Task SendMimeMessageAsync(MimeMessage message) + private async Task SendMimeMessageAsync(MimeMessage message, CancellationToken cancellationToken) { try { - await _smtpClient.SendAsync(message); + await _smtpClient.SendAsync(message, cancellationToken); return; } catch (ServiceNotConnectedException) @@ -145,7 +135,7 @@ private async Task SendMimeMessageAsync(MimeMessage message) Connect(); } } - _smtpClient.Send(message); + _smtpClient.Send(message, cancellationToken); } private void Connect() diff --git a/src/Madev.Utils.Infrastructure.Services.Mailing.MsGraph/EmailBuilder.cs b/src/Madev.Utils.Infrastructure.Services.Mailing.MsGraph/EmailBuilder.cs index 836db9f..23adfc7 100644 --- a/src/Madev.Utils.Infrastructure.Services.Mailing.MsGraph/EmailBuilder.cs +++ b/src/Madev.Utils.Infrastructure.Services.Mailing.MsGraph/EmailBuilder.cs @@ -27,6 +27,45 @@ public EmailBuilder To(IEnumerable recipients) return this; } + public EmailBuilder Cc(IEnumerable recipients) + { + _email.CcRecipients = recipients.Select(x => new Recipient + { + EmailAddress = new EmailAddress + { + Address = x + } + }).ToList(); + return this; + } + + public EmailBuilder Bcc(IEnumerable recipients) + { + _email.BccRecipients = recipients.Select(x => new Recipient + { + EmailAddress = new EmailAddress + { + Address = x + } + }).ToList(); + return this; + } + + public EmailBuilder From(string? from) + { + if (from != null) + { + _email.From = new Recipient + { + EmailAddress = new EmailAddress + { + Address = from + } + }; + } + return this; + } + public EmailBuilder Subject(string subject) { _email.Subject = subject; diff --git a/src/Madev.Utils.Infrastructure.Services.Mailing.MsGraph/MsGraphEmailSender.cs b/src/Madev.Utils.Infrastructure.Services.Mailing.MsGraph/MsGraphEmailSender.cs index f3f7cea..cdf4ed5 100644 --- a/src/Madev.Utils.Infrastructure.Services.Mailing.MsGraph/MsGraphEmailSender.cs +++ b/src/Madev.Utils.Infrastructure.Services.Mailing.MsGraph/MsGraphEmailSender.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Threading; using System.Threading.Tasks; using Microsoft.Graph; using Microsoft.Graph.Models; @@ -18,44 +19,38 @@ public MsGraphEmailSender(string sender, GraphServiceClient client) _sender = sender; } - public async Task SendTextEmailAsync(string toAddress, string subject, string body, IEnumerable? attachments = null) + public async Task SendHtmlEmailAsync(EmailMessage message, CancellationToken cancellationToken = default) { - attachments ??= new List(); - await SendTextEmailAsync(new List() { toAddress }, subject, body, attachments); + await SendEmailAsync(email => email + .To(message.To) + .Cc(message.Cc) + .Bcc(message.Bcc) + .From(message.From) + .Subject(message.Subject) + .Body(message.Body, BodyType.Html) + .Attachments(message.Attachments), cancellationToken); } - public async Task SendTextEmailAsync(IEnumerable toAddress, string subject, string body, IEnumerable? attachments = null) + public async Task SendTextEmailAsync(EmailMessage message, CancellationToken cancellationToken = default) { - attachments ??= new List(); - await SendEmailAsync(email => email.To(toAddress) - .Subject(subject) - .Body(body, BodyType.Text) - .Attachments(attachments)); + await SendEmailAsync(email => email + .To(message.To) + .Cc(message.Cc) + .Bcc(message.Bcc) + .From(message.From) + .Subject(message.Subject) + .Body(message.Body, BodyType.Text) + .Attachments(message.Attachments), cancellationToken); } - public async Task SendHtmlEmailAsync(string toAddress, string subject, string body, IEnumerable? attachments = null) - { - attachments ??= new List(); - await SendHtmlEmailAsync(new List() { toAddress }, subject, body, attachments); - } - - public async Task SendHtmlEmailAsync(IEnumerable toAddress, string subject, string body, IEnumerable? attachments = null) - { - attachments ??= new List(); - await SendEmailAsync(email => email.To(toAddress) - .Subject(subject) - .Body(body, BodyType.Html) - .Attachments(attachments)); - } - - private async Task SendEmailAsync(Action builder) + private async Task SendEmailAsync(Action builder, CancellationToken cancellationToken) { var message = new Message(); builder(new EmailBuilder(message)); - await SendEmailInternalAsync(message); + await SendEmailInternalAsync(message, cancellationToken); } - private async Task SendEmailInternalAsync(Message message) + private async Task SendEmailInternalAsync(Message message, CancellationToken cancellationToken) { var requestBody = new SendMailPostRequestBody { @@ -65,7 +60,7 @@ private async Task SendEmailInternalAsync(Message message) await _client.Users[_sender] .SendMail - .PostAsync(requestBody); + .PostAsync(requestBody, cancellationToken: cancellationToken); } } } \ No newline at end of file diff --git a/src/Madev.Utils.Infrastructure.Services.Mailing/EmailMessage.cs b/src/Madev.Utils.Infrastructure.Services.Mailing/EmailMessage.cs new file mode 100644 index 0000000..10bc8cd --- /dev/null +++ b/src/Madev.Utils.Infrastructure.Services.Mailing/EmailMessage.cs @@ -0,0 +1,15 @@ +using System.Collections.Generic; + +namespace Madev.Utils.Infrastructure.Services.Mailing +{ + public class EmailMessage + { + public IEnumerable To { get; set; } = new List(); + public string Subject { get; set; } = string.Empty; + public string Body { get; set; } = string.Empty; + public string? From { get; set; } + public IEnumerable Cc { get; set; } = new List(); + public IEnumerable Bcc { get; set; } = new List(); + public IEnumerable Attachments { get; set; } = new List(); + } +} diff --git a/src/Madev.Utils.Infrastructure.Services.Mailing/IEmailSender.cs b/src/Madev.Utils.Infrastructure.Services.Mailing/IEmailSender.cs index 659ba5d..4137a60 100644 --- a/src/Madev.Utils.Infrastructure.Services.Mailing/IEmailSender.cs +++ b/src/Madev.Utils.Infrastructure.Services.Mailing/IEmailSender.cs @@ -1,13 +1,11 @@ -using System.Collections.Generic; +using System.Threading; using System.Threading.Tasks; namespace Madev.Utils.Infrastructure.Services.Mailing { public interface IEmailSender { - Task SendTextEmailAsync(string toAddress, string subject, string body, IEnumerable? attachments = null); - Task SendTextEmailAsync(IEnumerable toAddress, string subject, string body, IEnumerable? attachments = null); - Task SendHtmlEmailAsync(string toAddress, string subject, string body, IEnumerable? attachments = null); - Task SendHtmlEmailAsync(IEnumerable toAddress, string subject, string body, IEnumerable? attachments = null); + Task SendHtmlEmailAsync(EmailMessage message, CancellationToken cancellationToken = default); + Task SendTextEmailAsync(EmailMessage message, CancellationToken cancellationToken = default); } -} \ No newline at end of file +} From 60ac3c90f8e9f6ab4a0398692d8310b250639135 Mon Sep 17 00:00:00 2001 From: Jakub Date: Thu, 11 Jun 2026 12:50:13 +0200 Subject: [PATCH 2/4] feat: add support for Sendgrid --- .github/workflows/dotnet.yml | 1 + Madev.Utils.sln | 6 + .../DependencyExtensions.cs | 15 +++ ...structure.Services.Mailing.SendGrid.csproj | 25 +++++ .../SendGridEmailSender.cs | 103 ++++++++++++++++++ .../SendGridEmailSenderOptions.cs | 8 ++ 6 files changed, 158 insertions(+) create mode 100644 src/Madev.Utils.Infrastructure.Services.Mailing.SendGrid/DependencyExtensions.cs create mode 100644 src/Madev.Utils.Infrastructure.Services.Mailing.SendGrid/Madev.Utils.Infrastructure.Services.Mailing.SendGrid.csproj create mode 100644 src/Madev.Utils.Infrastructure.Services.Mailing.SendGrid/SendGridEmailSender.cs create mode 100644 src/Madev.Utils.Infrastructure.Services.Mailing.SendGrid/SendGridEmailSenderOptions.cs diff --git a/.github/workflows/dotnet.yml b/.github/workflows/dotnet.yml index d6c94a1..e373e95 100644 --- a/.github/workflows/dotnet.yml +++ b/.github/workflows/dotnet.yml @@ -19,6 +19,7 @@ jobs: - src/Madev.Utils.Infrastructure.Services.Mailing/Madev.Utils.Infrastructure.Services.Mailing.csproj - src/Madev.Utils.Infrastructure.Services.Mailing.Mailkit/Madev.Utils.Infrastructure.Services.Mailing.Mailkit.csproj - src/Madev.Utils.Infrastructure.Services.Mailing.MsGraph/Madev.Utils.Infrastructure.Services.Mailing.MsGraph.csproj + - src/Madev.Utils.Infrastructure.Services.Mailing.SendGrid/Madev.Utils.Infrastructure.Services.Mailing.SendGrid.csproj - src/Madev.Utils.Infrastructure.Hangfire/Madev.Utils.Infrastructure.Hangfire.csproj diff --git a/Madev.Utils.sln b/Madev.Utils.sln index 28f123a..9f51502 100644 --- a/Madev.Utils.sln +++ b/Madev.Utils.sln @@ -11,6 +11,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Madev.Utils.Infrastructure. EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Madev.Utils.Infrastructure.Services.Mailing.Mailkit", "src\Madev.Utils.Infrastructure.Services.Mailing.Mailkit\Madev.Utils.Infrastructure.Services.Mailing.Mailkit.csproj", "{515D375F-2A74-4DD8-B82F-DB066532B6D0}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Madev.Utils.Infrastructure.Services.Mailing.SendGrid", "src\Madev.Utils.Infrastructure.Services.Mailing.SendGrid\Madev.Utils.Infrastructure.Services.Mailing.SendGrid.csproj", "{85737F65-506C-45D9-93EF-DCC672444CD3}" +EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Madev.Utils.Infrastructure.Hangfire", "src\Madev.Utils.Infrastructure.Hangfire\Madev.Utils.Infrastructure.Hangfire.csproj", "{CD1791BD-5AC3-4039-8E59-FB64167F26CC}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Madev.Utils.Infrastructure.ApplicationInsights.AspNetCore", "src\Madev.Utils.Infrastructure.ApplicationInsights.AspNetCore\Madev.Utils.Infrastructure.ApplicationInsights.AspNetCore.csproj", "{6E266322-CCCA-4774-892B-30F1690FD734}" @@ -39,6 +41,10 @@ Global {515D375F-2A74-4DD8-B82F-DB066532B6D0}.Debug|Any CPU.Build.0 = Debug|Any CPU {515D375F-2A74-4DD8-B82F-DB066532B6D0}.Release|Any CPU.ActiveCfg = Release|Any CPU {515D375F-2A74-4DD8-B82F-DB066532B6D0}.Release|Any CPU.Build.0 = Release|Any CPU + {85737F65-506C-45D9-93EF-DCC672444CD3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {85737F65-506C-45D9-93EF-DCC672444CD3}.Debug|Any CPU.Build.0 = Debug|Any CPU + {85737F65-506C-45D9-93EF-DCC672444CD3}.Release|Any CPU.ActiveCfg = Release|Any CPU + {85737F65-506C-45D9-93EF-DCC672444CD3}.Release|Any CPU.Build.0 = Release|Any CPU {CD1791BD-5AC3-4039-8E59-FB64167F26CC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {CD1791BD-5AC3-4039-8E59-FB64167F26CC}.Debug|Any CPU.Build.0 = Debug|Any CPU {CD1791BD-5AC3-4039-8E59-FB64167F26CC}.Release|Any CPU.ActiveCfg = Release|Any CPU diff --git a/src/Madev.Utils.Infrastructure.Services.Mailing.SendGrid/DependencyExtensions.cs b/src/Madev.Utils.Infrastructure.Services.Mailing.SendGrid/DependencyExtensions.cs new file mode 100644 index 0000000..06cf41b --- /dev/null +++ b/src/Madev.Utils.Infrastructure.Services.Mailing.SendGrid/DependencyExtensions.cs @@ -0,0 +1,15 @@ +using System; +using Microsoft.Extensions.DependencyInjection; + +namespace Madev.Utils.Infrastructure.Services.Mailing.SendGrid +{ + public static class DependencyExtensions + { + public static IServiceCollection AddSendGridEmailSender(this IServiceCollection services, Action options) + { + services.AddScoped() + .Configure(options); + return services; + } + } +} diff --git a/src/Madev.Utils.Infrastructure.Services.Mailing.SendGrid/Madev.Utils.Infrastructure.Services.Mailing.SendGrid.csproj b/src/Madev.Utils.Infrastructure.Services.Mailing.SendGrid/Madev.Utils.Infrastructure.Services.Mailing.SendGrid.csproj new file mode 100644 index 0000000..67a71bf --- /dev/null +++ b/src/Madev.Utils.Infrastructure.Services.Mailing.SendGrid/Madev.Utils.Infrastructure.Services.Mailing.SendGrid.csproj @@ -0,0 +1,25 @@ + + + + netstandard2.1;net8.0;net10.0 + enable + Miroslav Adamec + Madev + Send emails using SendGrid + https://github.com/madev/Madev.Utils + https://github.com/madev/Madev.Utils + mirecad madev emails sendgrid tools utils extensions + https://madevfiles.blob.core.windows.net/$web/Madev/madev-icon.png + + + + + + + + + + + + + diff --git a/src/Madev.Utils.Infrastructure.Services.Mailing.SendGrid/SendGridEmailSender.cs b/src/Madev.Utils.Infrastructure.Services.Mailing.SendGrid/SendGridEmailSender.cs new file mode 100644 index 0000000..0273d64 --- /dev/null +++ b/src/Madev.Utils.Infrastructure.Services.Mailing.SendGrid/SendGridEmailSender.cs @@ -0,0 +1,103 @@ +using System; +using System.IO; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.Extensions.Options; +using global::SendGrid; +using global::SendGrid.Helpers.Mail; + +namespace Madev.Utils.Infrastructure.Services.Mailing.SendGrid +{ + public class SendGridEmailSender : IEmailSender + { + private readonly SendGridClient _client; + private readonly SendGridEmailSenderOptions _options; + + public SendGridEmailSender(IOptions options) + { + _options = options.Value; + _client = new SendGridClient(_options.ApiKey); + } + + public Task SendHtmlEmailAsync(EmailMessage message, CancellationToken cancellationToken = default) + => SendAsync(ConstructHtmlMessage(message), cancellationToken); + + public Task SendTextEmailAsync(EmailMessage message, CancellationToken cancellationToken = default) + => SendAsync(ConstructTextMessage(message), cancellationToken); + + private async Task SendAsync(SendGridMessage sgMessage, CancellationToken cancellationToken) + { + var response = await _client.SendEmailAsync(sgMessage, cancellationToken); + if (!response.IsSuccessStatusCode) + { + var responseBody = await response.Body.ReadAsStringAsync(); + throw new InvalidOperationException($"SendGrid returned {(int)response.StatusCode}: {responseBody}"); + } + } + + private SendGridMessage ConstructHtmlMessage(EmailMessage message) + { + var sgMessage = ConstructBaseMessage(message); + sgMessage.HtmlContent = message.Body; + return sgMessage; + } + + private SendGridMessage ConstructTextMessage(EmailMessage message) + { + var sgMessage = ConstructBaseMessage(message); + sgMessage.PlainTextContent = message.Body; + return sgMessage; + } + + private SendGridMessage ConstructBaseMessage(EmailMessage message) + { + var from = message.From ?? _options.Sender + ?? throw new InvalidOperationException("No sender specified: set EmailMessage.From or SendGridEmailSenderOptions.Sender."); + + var sgMessage = new SendGridMessage + { + From = new EmailAddress(from), + Subject = message.Subject + }; + + foreach (var to in message.To) + { + sgMessage.AddTo(new EmailAddress(to)); + } + foreach (var cc in message.Cc) + { + sgMessage.AddCc(new EmailAddress(cc)); + } + foreach (var bcc in message.Bcc) + { + sgMessage.AddBcc(new EmailAddress(bcc)); + } + + foreach (var attachment in message.Attachments) + { + AddAttachment(sgMessage, attachment); + } + + return sgMessage; + } + + private static void AddAttachment(SendGridMessage sgMessage, IEmailAttachment attachment) + { + var (name, base64Content) = attachment switch + { + ByteEmailAttachment a => (a.Filename, Convert.ToBase64String(a.Content)), + FilepathEmailAttachment a => (Path.GetFileName(a.Path), Convert.ToBase64String(File.ReadAllBytes(a.Path))), + Base64EmailAttachment a => (a.FileName, a.Content), + _ => throw new InvalidOperationException("Unknown attachment type.") + }; + + // For inline attachments the content_id must match the cid: reference in the HTML body. + sgMessage.AddAttachment( + filename: name, + base64Content: base64Content, + type: attachment.ContentType, + disposition: attachment.IsInline ? "inline" : "attachment", + content_id: attachment.IsInline ? attachment.ContentId : null); + } + } +} diff --git a/src/Madev.Utils.Infrastructure.Services.Mailing.SendGrid/SendGridEmailSenderOptions.cs b/src/Madev.Utils.Infrastructure.Services.Mailing.SendGrid/SendGridEmailSenderOptions.cs new file mode 100644 index 0000000..3dd7118 --- /dev/null +++ b/src/Madev.Utils.Infrastructure.Services.Mailing.SendGrid/SendGridEmailSenderOptions.cs @@ -0,0 +1,8 @@ +namespace Madev.Utils.Infrastructure.Services.Mailing.SendGrid +{ + public class SendGridEmailSenderOptions + { + public string ApiKey { get; set; } = null!; + public string? Sender { get; set; } + } +} From cd08cd76d14e9cdd1650795c407f395a915f472c Mon Sep 17 00:00:00 2001 From: kuberto773 Date: Thu, 11 Jun 2026 12:54:09 +0200 Subject: [PATCH 3/4] chore: use slnx instead of sln --- Madev.Utils.sln | 67 ------------------------------------------------ Madev.Utils.slnx | 10 ++++++++ 2 files changed, 10 insertions(+), 67 deletions(-) delete mode 100644 Madev.Utils.sln create mode 100644 Madev.Utils.slnx diff --git a/Madev.Utils.sln b/Madev.Utils.sln deleted file mode 100644 index 9f51502..0000000 --- a/Madev.Utils.sln +++ /dev/null @@ -1,67 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 18 -VisualStudioVersion = 18.0.11205.157 d18.0 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Madev.Utils.Infrastructure.Http", "src\Madev.Utils.Infrastructure.Http\Madev.Utils.Infrastructure.Http.csproj", "{26CD570D-534F-4D45-8832-20053201B425}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Madev.Utils.Infrastructure.Services.Mailing", "src\Madev.Utils.Infrastructure.Services.Mailing\Madev.Utils.Infrastructure.Services.Mailing.csproj", "{AB612E02-DA20-4550-B830-7A871C24EA45}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Madev.Utils.Infrastructure.Services.Mailing.MsGraph", "src\Madev.Utils.Infrastructure.Services.Mailing.MsGraph\Madev.Utils.Infrastructure.Services.Mailing.MsGraph.csproj", "{2BBB3A20-6B55-45F4-9BAD-29536B103C12}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Madev.Utils.Infrastructure.Services.Mailing.Mailkit", "src\Madev.Utils.Infrastructure.Services.Mailing.Mailkit\Madev.Utils.Infrastructure.Services.Mailing.Mailkit.csproj", "{515D375F-2A74-4DD8-B82F-DB066532B6D0}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Madev.Utils.Infrastructure.Services.Mailing.SendGrid", "src\Madev.Utils.Infrastructure.Services.Mailing.SendGrid\Madev.Utils.Infrastructure.Services.Mailing.SendGrid.csproj", "{85737F65-506C-45D9-93EF-DCC672444CD3}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Madev.Utils.Infrastructure.Hangfire", "src\Madev.Utils.Infrastructure.Hangfire\Madev.Utils.Infrastructure.Hangfire.csproj", "{CD1791BD-5AC3-4039-8E59-FB64167F26CC}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Madev.Utils.Infrastructure.ApplicationInsights.AspNetCore", "src\Madev.Utils.Infrastructure.ApplicationInsights.AspNetCore\Madev.Utils.Infrastructure.ApplicationInsights.AspNetCore.csproj", "{6E266322-CCCA-4774-892B-30F1690FD734}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Madev.Utils.Infrastructure.ApplicationInsights.WorkerService", "src\Madev.Utils.Infrastructure.ApplicationInsights.WorkerService\Madev.Utils.Infrastructure.ApplicationInsights.WorkerService.csproj", "{9C8C911F-6BCF-4027-A088-FBA9104B7F7E}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Release|Any CPU = Release|Any CPU - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {26CD570D-534F-4D45-8832-20053201B425}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {26CD570D-534F-4D45-8832-20053201B425}.Debug|Any CPU.Build.0 = Debug|Any CPU - {26CD570D-534F-4D45-8832-20053201B425}.Release|Any CPU.ActiveCfg = Release|Any CPU - {26CD570D-534F-4D45-8832-20053201B425}.Release|Any CPU.Build.0 = Release|Any CPU - {AB612E02-DA20-4550-B830-7A871C24EA45}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {AB612E02-DA20-4550-B830-7A871C24EA45}.Debug|Any CPU.Build.0 = Debug|Any CPU - {AB612E02-DA20-4550-B830-7A871C24EA45}.Release|Any CPU.ActiveCfg = Release|Any CPU - {AB612E02-DA20-4550-B830-7A871C24EA45}.Release|Any CPU.Build.0 = Release|Any CPU - {2BBB3A20-6B55-45F4-9BAD-29536B103C12}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {2BBB3A20-6B55-45F4-9BAD-29536B103C12}.Debug|Any CPU.Build.0 = Debug|Any CPU - {2BBB3A20-6B55-45F4-9BAD-29536B103C12}.Release|Any CPU.ActiveCfg = Release|Any CPU - {2BBB3A20-6B55-45F4-9BAD-29536B103C12}.Release|Any CPU.Build.0 = Release|Any CPU - {515D375F-2A74-4DD8-B82F-DB066532B6D0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {515D375F-2A74-4DD8-B82F-DB066532B6D0}.Debug|Any CPU.Build.0 = Debug|Any CPU - {515D375F-2A74-4DD8-B82F-DB066532B6D0}.Release|Any CPU.ActiveCfg = Release|Any CPU - {515D375F-2A74-4DD8-B82F-DB066532B6D0}.Release|Any CPU.Build.0 = Release|Any CPU - {85737F65-506C-45D9-93EF-DCC672444CD3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {85737F65-506C-45D9-93EF-DCC672444CD3}.Debug|Any CPU.Build.0 = Debug|Any CPU - {85737F65-506C-45D9-93EF-DCC672444CD3}.Release|Any CPU.ActiveCfg = Release|Any CPU - {85737F65-506C-45D9-93EF-DCC672444CD3}.Release|Any CPU.Build.0 = Release|Any CPU - {CD1791BD-5AC3-4039-8E59-FB64167F26CC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {CD1791BD-5AC3-4039-8E59-FB64167F26CC}.Debug|Any CPU.Build.0 = Debug|Any CPU - {CD1791BD-5AC3-4039-8E59-FB64167F26CC}.Release|Any CPU.ActiveCfg = Release|Any CPU - {CD1791BD-5AC3-4039-8E59-FB64167F26CC}.Release|Any CPU.Build.0 = Release|Any CPU - {6E266322-CCCA-4774-892B-30F1690FD734}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {6E266322-CCCA-4774-892B-30F1690FD734}.Debug|Any CPU.Build.0 = Debug|Any CPU - {6E266322-CCCA-4774-892B-30F1690FD734}.Release|Any CPU.ActiveCfg = Release|Any CPU - {6E266322-CCCA-4774-892B-30F1690FD734}.Release|Any CPU.Build.0 = Release|Any CPU - {9C8C911F-6BCF-4027-A088-FBA9104B7F7E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {9C8C911F-6BCF-4027-A088-FBA9104B7F7E}.Debug|Any CPU.Build.0 = Debug|Any CPU - {9C8C911F-6BCF-4027-A088-FBA9104B7F7E}.Release|Any CPU.ActiveCfg = Release|Any CPU - {9C8C911F-6BCF-4027-A088-FBA9104B7F7E}.Release|Any CPU.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {0F6C74EC-904C-4FC1-8BA5-97C7A78322CD} - EndGlobalSection -EndGlobal diff --git a/Madev.Utils.slnx b/Madev.Utils.slnx new file mode 100644 index 0000000..2b13d43 --- /dev/null +++ b/Madev.Utils.slnx @@ -0,0 +1,10 @@ + + + + + + + + + + From cebcdf71e4b7b8fe6e2ed6c93346ddb229ebf7bf Mon Sep 17 00:00:00 2001 From: kuberto773 Date: Thu, 11 Jun 2026 13:32:36 +0200 Subject: [PATCH 4/4] build: fix gitversion for PRs --- GitVersion.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/GitVersion.yml b/GitVersion.yml index 6993381..05c5bd0 100644 --- a/GitVersion.yml +++ b/GitVersion.yml @@ -8,6 +8,8 @@ branches: is-release-branch: true is-main-branch: true increment: Patch + pull-request: + is-main-branch: false commit-message-incrementing: Enabled ignore: sha: [] \ No newline at end of file