From 1832519ba97756069f8679e6e26921c8a487c50e Mon Sep 17 00:00:00 2001 From: maliming Date: Tue, 22 Aug 2023 13:33:15 +0800 Subject: [PATCH 1/2] Support attachments and `ExtraProperties` when sending emails. --- .../Abp/Emailing/BackgroundEmailSendingJob.cs | 6 +-- .../Emailing/BackgroundEmailSendingJobArgs.cs | 6 ++- .../Volo/Abp/Emailing/EmailAttachment.cs | 11 ++++ .../Volo/Abp/Emailing/EmailSenderBase.cs | 53 +++++++++++++------ .../Volo/Abp/Emailing/IEmailSender.cs | 20 +++++-- .../Volo/Abp/Emailing/Smtp/SmtpEmailSender.cs | 2 +- .../Abp/MailKit/MailKitSmtpEmailSender.cs | 2 +- 7 files changed, 73 insertions(+), 27 deletions(-) create mode 100644 framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/EmailAttachment.cs diff --git a/framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/BackgroundEmailSendingJob.cs b/framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/BackgroundEmailSendingJob.cs index 07b4ca9bcd..f1d2812ae9 100644 --- a/framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/BackgroundEmailSendingJob.cs +++ b/framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/BackgroundEmailSendingJob.cs @@ -15,15 +15,15 @@ public class BackgroundEmailSendingJob : AsyncBackgroundJob public bool IsBodyHtml { get; set; } = true; - //TODO: Add other properties and attachments + public List? Attachments { get; set; } + + public ExtraPropertyDictionary? ExtraProperties { get; set; } } diff --git a/framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/EmailAttachment.cs b/framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/EmailAttachment.cs new file mode 100644 index 0000000000..e2fe3a3a6b --- /dev/null +++ b/framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/EmailAttachment.cs @@ -0,0 +1,11 @@ +using System; + +namespace Volo.Abp.Emailing; + +[Serializable] +public class EmailAttachment +{ + public string? Name { get; set; } + + public byte[]? File { get; set; } +} diff --git a/framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/EmailSenderBase.cs b/framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/EmailSenderBase.cs index d8a46ca4b9..8de9f4c5a1 100644 --- a/framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/EmailSenderBase.cs +++ b/framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/EmailSenderBase.cs @@ -1,8 +1,12 @@ using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; using System.Net.Mail; using System.Text; using System.Threading.Tasks; using Volo.Abp.BackgroundJobs; +using Volo.Abp.Data; namespace Volo.Abp.Emailing; @@ -24,20 +28,33 @@ public abstract class EmailSenderBase : IEmailSender BackgroundJobManager = backgroundJobManager; } - public virtual async Task SendAsync(string to, string? subject, string? body, bool isBodyHtml = true) + public virtual async Task SendAsync(string to, string? subject, string? body, bool isBodyHtml = true, List? attachments = null, ExtraPropertyDictionary? extraProperties = null) { - await SendAsync(new MailMessage - { - To = { to }, - Subject = subject, - Body = body, - IsBodyHtml = isBodyHtml - }); + await SendAsync(BuildMailMessage(null, to, subject, body, isBodyHtml, attachments, extraProperties)); } - public virtual async Task SendAsync(string from, string to, string? subject, string? body, bool isBodyHtml = true) + public virtual async Task SendAsync(string from, string to, string? subject, string? body, bool isBodyHtml = true, List? attachments = null, ExtraPropertyDictionary? extraProperties = null) { - await SendAsync(new MailMessage(from, to, subject, body) { IsBodyHtml = isBodyHtml }); + await SendAsync(BuildMailMessage(from, to, subject, body, isBodyHtml, attachments, extraProperties)); + } + + protected virtual MailMessage BuildMailMessage(string? from, string to, string? subject, string? body, bool isBodyHtml = true, List? attachments = null, ExtraPropertyDictionary? extraProperties = null) + { + var message = from == null + ? new MailMessage { To = { to }, Subject = subject, Body = body, IsBodyHtml = isBodyHtml } + : new MailMessage(from, to, subject, body) { IsBodyHtml = isBodyHtml }; + + if (attachments != null) + { + foreach (var attachment in attachments.Where(x => x.File != null)) + { + var fileStream = new MemoryStream(attachment.File!); + fileStream.Seek(0, SeekOrigin.Begin); + message.Attachments.Add(new Attachment(fileStream, attachment.Name)); + } + } + + return message; } public virtual async Task SendAsync(MailMessage mail, bool normalize = true) @@ -50,11 +67,11 @@ public abstract class EmailSenderBase : IEmailSender await SendEmailAsync(mail); } - public virtual async Task QueueAsync(string to, string subject, string body, bool isBodyHtml = true) + public virtual async Task QueueAsync(string to, string subject, string body, bool isBodyHtml = true, List? attachments = null, ExtraPropertyDictionary? extraProperties = null) { if (!BackgroundJobManager.IsAvailable()) { - await SendAsync(to, subject, body, isBodyHtml); + await SendAsync(to, subject, body, isBodyHtml, attachments, extraProperties); return; } @@ -64,16 +81,18 @@ public abstract class EmailSenderBase : IEmailSender To = to, Subject = subject, Body = body, - IsBodyHtml = isBodyHtml + IsBodyHtml = isBodyHtml, + Attachments = attachments, + ExtraProperties = extraProperties } ); } - public virtual async Task QueueAsync(string from, string to, string subject, string body, bool isBodyHtml = true) + public virtual async Task QueueAsync(string from, string to, string subject, string body, bool isBodyHtml = true, List? attachments = null, ExtraPropertyDictionary? extraProperties = null) { if (!BackgroundJobManager.IsAvailable()) { - await SendAsync(from, to, subject, body, isBodyHtml); + await SendAsync(from, to, subject, body, isBodyHtml, attachments, extraProperties); return; } @@ -84,7 +103,9 @@ public abstract class EmailSenderBase : IEmailSender To = to, Subject = subject, Body = body, - IsBodyHtml = isBodyHtml + IsBodyHtml = isBodyHtml, + Attachments = attachments, + ExtraProperties = extraProperties } ); } diff --git a/framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/IEmailSender.cs b/framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/IEmailSender.cs index 55456783c4..83e082d2a1 100644 --- a/framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/IEmailSender.cs +++ b/framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/IEmailSender.cs @@ -1,5 +1,7 @@ -using System.Net.Mail; +using System.Collections.Generic; +using System.Net.Mail; using System.Threading.Tasks; +using Volo.Abp.Data; namespace Volo.Abp.Emailing; @@ -15,7 +17,9 @@ public interface IEmailSender string to, string? subject, string? body, - bool isBodyHtml = true + bool isBodyHtml = true, + List? attachments = null, + ExtraPropertyDictionary? extraProperties = null ); /// @@ -26,7 +30,9 @@ public interface IEmailSender string to, string? subject, string? body, - bool isBodyHtml = true + bool isBodyHtml = true, + List? attachments = null, + ExtraPropertyDictionary? extraProperties = null ); /// @@ -49,7 +55,9 @@ public interface IEmailSender string to, string subject, string body, - bool isBodyHtml = true + bool isBodyHtml = true, + List? attachments = null, + ExtraPropertyDictionary? extraProperties = null ); /// @@ -60,7 +68,9 @@ public interface IEmailSender string to, string subject, string body, - bool isBodyHtml = true + bool isBodyHtml = true, + List? attachments = null, + ExtraPropertyDictionary? extraProperties = null ); //TODO: Add other Queue methods too. Problem: MailMessage is not serializable so can not be used in background jobs. diff --git a/framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Smtp/SmtpEmailSender.cs b/framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Smtp/SmtpEmailSender.cs index 99a8f2e1e7..4bf7e18158 100644 --- a/framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Smtp/SmtpEmailSender.cs +++ b/framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Smtp/SmtpEmailSender.cs @@ -67,7 +67,7 @@ public class SmtpEmailSender : EmailSenderBase, ISmtpEmailSender, ITransientDepe } } - protected override async Task SendEmailAsync(MailMessage mail) + protected async override Task SendEmailAsync(MailMessage mail) { using (var smtpClient = await BuildClientAsync()) { diff --git a/framework/src/Volo.Abp.MailKit/Volo/Abp/MailKit/MailKitSmtpEmailSender.cs b/framework/src/Volo.Abp.MailKit/Volo/Abp/MailKit/MailKitSmtpEmailSender.cs index c3523b4e1a..96e436760e 100644 --- a/framework/src/Volo.Abp.MailKit/Volo/Abp/MailKit/MailKitSmtpEmailSender.cs +++ b/framework/src/Volo.Abp.MailKit/Volo/Abp/MailKit/MailKitSmtpEmailSender.cs @@ -29,7 +29,7 @@ public class MailKitSmtpEmailSender : EmailSenderBase, IMailKitSmtpEmailSender SmtpConfiguration = smtpConfiguration; } - protected override async Task SendEmailAsync(MailMessage mail) + protected async override Task SendEmailAsync(MailMessage mail) { using (var client = await BuildClientAsync()) { From dc34d7435ac12fda30b844f63fb50832ddeabb8a Mon Sep 17 00:00:00 2001 From: maliming Date: Tue, 22 Aug 2023 14:39:02 +0800 Subject: [PATCH 2/2] Update the `Emailing.md`. --- docs/en/Emailing.md | 5 +++++ .../src/Volo.Abp.Emailing/Volo/Abp/Emailing/IEmailSender.cs | 2 -- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/docs/en/Emailing.md b/docs/en/Emailing.md index bfb3058862..fd9e696b3e 100644 --- a/docs/en/Emailing.md +++ b/docs/en/Emailing.md @@ -58,7 +58,12 @@ namespace MyProject `SendAsync` method has overloads to supply more parameters like; * **from**: You can set this as the first argument to set a sender email address. If not provided, the default sender address is used (see the email settings below). +* **to**: You can set the target email address. +* **subject**: You can set the email subject. +* **body**: You can set the email body. * **isBodyHtml**: Indicates whether the email body may contain HTML tags. **Default: true**. +* **attachments**: You can pass a list of `EmailAttachment` to add attachments to the email. +* **extraProperties**: You can pass extra properties and use these properties in your own `IEmailSender` implementation to implement more mail sending features. > `IEmailSender` is the suggested way to send emails, since it makes your code provider independent. diff --git a/framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/IEmailSender.cs b/framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/IEmailSender.cs index 83e082d2a1..d2952c2d47 100644 --- a/framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/IEmailSender.cs +++ b/framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/IEmailSender.cs @@ -72,6 +72,4 @@ public interface IEmailSender List? attachments = null, ExtraPropertyDictionary? extraProperties = null ); - - //TODO: Add other Queue methods too. Problem: MailMessage is not serializable so can not be used in background jobs. }