diff --git a/src/Volo.Abp.Emailing/Volo.Abp.Emailing.csproj b/src/Volo.Abp.Emailing/Volo.Abp.Emailing.csproj
index 3c848d99bf..9aacc1cb1b 100644
--- a/src/Volo.Abp.Emailing/Volo.Abp.Emailing.csproj
+++ b/src/Volo.Abp.Emailing/Volo.Abp.Emailing.csproj
@@ -15,6 +15,7 @@
+
diff --git a/src/Volo.Abp.Emailing/Volo/Abp/Emailing/AbpEmailingModule.cs b/src/Volo.Abp.Emailing/Volo/Abp/Emailing/AbpEmailingModule.cs
index 5f7d5a3370..0ddd337d1a 100644
--- a/src/Volo.Abp.Emailing/Volo/Abp/Emailing/AbpEmailingModule.cs
+++ b/src/Volo.Abp.Emailing/Volo/Abp/Emailing/AbpEmailingModule.cs
@@ -1,5 +1,6 @@
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.Modularity;
+using Volo.Abp.Settings;
namespace Volo.Abp.Emailing
{
@@ -7,6 +8,11 @@ namespace Volo.Abp.Emailing
{
public override void ConfigureServices(IServiceCollection services)
{
+ services.Configure(options =>
+ {
+ options.DefinitionProviders.Add();
+ });
+
services.AddAssemblyOf();
}
}
diff --git a/src/Volo.Abp.Emailing/Volo/Abp/Emailing/EmailSenderBase.cs b/src/Volo.Abp.Emailing/Volo/Abp/Emailing/EmailSenderBase.cs
new file mode 100644
index 0000000000..59d2b7af72
--- /dev/null
+++ b/src/Volo.Abp.Emailing/Volo/Abp/Emailing/EmailSenderBase.cs
@@ -0,0 +1,121 @@
+using System;
+using System.Net.Mail;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Volo.Abp.Emailing
+{
+ ///
+ /// This class can be used as base to implement .
+ ///
+ public abstract class EmailSenderBase : IEmailSender
+ {
+ public IEmailSenderConfiguration Configuration { get; }
+
+ ///
+ /// Constructor.
+ ///
+ /// Configuration
+ protected EmailSenderBase(IEmailSenderConfiguration configuration)
+ {
+ Configuration = configuration;
+ }
+
+ public virtual async Task SendAsync(string to, string subject, string body, bool isBodyHtml = true)
+ {
+ await SendAsync(new MailMessage
+ {
+ To = { to },
+ Subject = subject,
+ Body = body,
+ IsBodyHtml = isBodyHtml
+ });
+ }
+
+ public virtual void Send(string to, string subject, string body, bool isBodyHtml = true)
+ {
+ Send(new MailMessage
+ {
+ To = { to },
+ Subject = subject,
+ Body = body,
+ IsBodyHtml = isBodyHtml
+ });
+ }
+
+ public virtual async Task SendAsync(string from, string to, string subject, string body, bool isBodyHtml = true)
+ {
+ await SendAsync(new MailMessage(from, to, subject, body) { IsBodyHtml = isBodyHtml });
+ }
+
+ public virtual void Send(string from, string to, string subject, string body, bool isBodyHtml = true)
+ {
+ Send(new MailMessage(from, to, subject, body) { IsBodyHtml = isBodyHtml });
+ }
+
+ public virtual async Task SendAsync(MailMessage mail, bool normalize = true)
+ {
+ if (normalize)
+ {
+ NormalizeMail(mail);
+ }
+
+ await SendEmailAsync(mail);
+ }
+
+ public virtual void Send(MailMessage mail, bool normalize = true)
+ {
+ if (normalize)
+ {
+ NormalizeMail(mail);
+ }
+
+ SendEmail(mail);
+ }
+
+ ///
+ /// Should implement this method to send email in derived classes.
+ ///
+ /// Mail to be sent
+ protected abstract Task SendEmailAsync(MailMessage mail);
+
+ ///
+ /// Should implement this method to send email in derived classes.
+ ///
+ /// Mail to be sent
+ protected abstract void SendEmail(MailMessage mail);
+
+ ///
+ /// Normalizes given email.
+ /// Fills if it's not filled before.
+ /// Sets encodings to UTF8 if they are not set before.
+ ///
+ /// Mail to be normalized
+ protected virtual void NormalizeMail(MailMessage mail)
+ {
+ if (mail.From == null || mail.From.Address.IsNullOrEmpty())
+ {
+ mail.From = new MailAddress(
+ Configuration.DefaultFromAddress,
+ Configuration.DefaultFromDisplayName,
+ Encoding.UTF8
+ );
+ }
+
+ if (mail.HeadersEncoding == null)
+ {
+ mail.HeadersEncoding = Encoding.UTF8;
+ }
+
+ if (mail.SubjectEncoding == null)
+ {
+ mail.SubjectEncoding = Encoding.UTF8;
+ }
+
+ if (mail.BodyEncoding == null)
+ {
+ mail.BodyEncoding = Encoding.UTF8;
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Volo.Abp.Emailing/Volo/Abp/Emailing/EmailSenderConfiguration.cs b/src/Volo.Abp.Emailing/Volo/Abp/Emailing/EmailSenderConfiguration.cs
new file mode 100644
index 0000000000..3293692cfb
--- /dev/null
+++ b/src/Volo.Abp.Emailing/Volo/Abp/Emailing/EmailSenderConfiguration.cs
@@ -0,0 +1,43 @@
+using System;
+using Volo.Abp.Settings;
+
+namespace Volo.Abp.Emailing
+{
+ ///
+ /// Implementation of that reads settings
+ /// from .
+ ///
+ public abstract class EmailSenderConfiguration : IEmailSenderConfiguration
+ {
+ public virtual string DefaultFromAddress => GetNotEmptySettingValue(EmailSettingNames.DefaultFromAddress);
+
+ public virtual string DefaultFromDisplayName => SettingManager.GetOrNull(EmailSettingNames.DefaultFromDisplayName);
+
+ protected readonly ISettingManager SettingManager;
+
+ ///
+ /// Creates a new .
+ ///
+ protected EmailSenderConfiguration(ISettingManager settingManager)
+ {
+ SettingManager = settingManager;
+ }
+
+ ///
+ /// Gets a setting value by checking. Throws if it's null or empty.
+ ///
+ /// Name of the setting
+ /// Value of the setting
+ protected string GetNotEmptySettingValue(string name)
+ {
+ var value = SettingManager.GetOrNull(name);
+
+ if (value.IsNullOrEmpty())
+ {
+ throw new AbpException($"Setting value for '{name}' is null or empty!");
+ }
+
+ return value;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Volo.Abp.Emailing/Volo/Abp/Emailing/EmailSettingNames.cs b/src/Volo.Abp.Emailing/Volo/Abp/Emailing/EmailSettingNames.cs
new file mode 100644
index 0000000000..b8be36af0d
--- /dev/null
+++ b/src/Volo.Abp.Emailing/Volo/Abp/Emailing/EmailSettingNames.cs
@@ -0,0 +1,59 @@
+namespace Volo.Abp.Emailing
+{
+ ///
+ /// Declares names of the settings defined by .
+ ///
+ public static class EmailSettingNames
+ {
+ ///
+ /// Abp.Net.Mail.DefaultFromAddress
+ ///
+ public const string DefaultFromAddress = "Abp.Net.Mail.DefaultFromAddress";
+
+ ///
+ /// Abp.Net.Mail.DefaultFromDisplayName
+ ///
+ public const string DefaultFromDisplayName = "Abp.Net.Mail.DefaultFromDisplayName";
+
+ ///
+ /// SMTP related email settings.
+ ///
+ public static class Smtp
+ {
+ ///
+ /// Abp.Net.Mail.Smtp.Host
+ ///
+ public const string Host = "Abp.Net.Mail.Smtp.Host";
+
+ ///
+ /// Abp.Net.Mail.Smtp.Port
+ ///
+ public const string Port = "Abp.Net.Mail.Smtp.Port";
+
+ ///
+ /// Abp.Net.Mail.Smtp.UserName
+ ///
+ public const string UserName = "Abp.Net.Mail.Smtp.UserName";
+
+ ///
+ /// Abp.Net.Mail.Smtp.Password
+ ///
+ public const string Password = "Abp.Net.Mail.Smtp.Password";
+
+ ///
+ /// Abp.Net.Mail.Smtp.Domain
+ ///
+ public const string Domain = "Abp.Net.Mail.Smtp.Domain";
+
+ ///
+ /// Abp.Net.Mail.Smtp.EnableSsl
+ ///
+ public const string EnableSsl = "Abp.Net.Mail.Smtp.EnableSsl";
+
+ ///
+ /// Abp.Net.Mail.Smtp.UseDefaultCredentials
+ ///
+ public const string UseDefaultCredentials = "Abp.Net.Mail.Smtp.UseDefaultCredentials";
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Volo.Abp.Emailing/Volo/Abp/Emailing/EmailSettingProvider.cs b/src/Volo.Abp.Emailing/Volo/Abp/Emailing/EmailSettingProvider.cs
new file mode 100644
index 0000000000..97be614a03
--- /dev/null
+++ b/src/Volo.Abp.Emailing/Volo/Abp/Emailing/EmailSettingProvider.cs
@@ -0,0 +1,26 @@
+using Volo.Abp.Settings;
+
+namespace Volo.Abp.Emailing
+{
+ ///
+ /// Defines settings to send emails.
+ /// for all available configurations.
+ ///
+ internal class EmailSettingProvider : SettingDefinitionProvider
+ {
+ public override void Define(ISettingDefinitionContext context)
+ {
+ context.Add(
+ new SettingDefinition(EmailSettingNames.Smtp.Host, "127.0.0.1"),
+ new SettingDefinition(EmailSettingNames.Smtp.Port, "25"),
+ new SettingDefinition(EmailSettingNames.Smtp.UserName),
+ new SettingDefinition(EmailSettingNames.Smtp.Password),
+ new SettingDefinition(EmailSettingNames.Smtp.Domain),
+ new SettingDefinition(EmailSettingNames.Smtp.EnableSsl, "false"),
+ new SettingDefinition(EmailSettingNames.Smtp.UseDefaultCredentials, "true"),
+ new SettingDefinition(EmailSettingNames.DefaultFromAddress),
+ new SettingDefinition(EmailSettingNames.DefaultFromDisplayName)
+ );
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Volo.Abp.Emailing/Volo/Abp/Emailing/IEmailSender.cs b/src/Volo.Abp.Emailing/Volo/Abp/Emailing/IEmailSender.cs
new file mode 100644
index 0000000000..8c4b87428a
--- /dev/null
+++ b/src/Volo.Abp.Emailing/Volo/Abp/Emailing/IEmailSender.cs
@@ -0,0 +1,51 @@
+using System.Net.Mail;
+using System.Threading.Tasks;
+
+namespace Volo.Abp.Emailing
+{
+ ///
+ /// This service can be used simply sending emails.
+ ///
+ public interface IEmailSender
+ {
+ ///
+ /// Sends an email.
+ ///
+ Task SendAsync(string to, string subject, string body, bool isBodyHtml = true);
+
+ ///
+ /// Sends an email.
+ ///
+ void Send(string to, string subject, string body, bool isBodyHtml = true);
+
+ ///
+ /// Sends an email.
+ ///
+ Task SendAsync(string from, string to, string subject, string body, bool isBodyHtml = true);
+
+ ///
+ /// Sends an email.
+ ///
+ void Send(string from, string to, string subject, string body, bool isBodyHtml = true);
+
+ ///
+ /// Sends an email.
+ ///
+ /// Mail to be sent
+ ///
+ /// Should normalize email?
+ /// If true, it sets sender address/name if it's not set before and makes mail encoding UTF-8.
+ ///
+ void Send(MailMessage mail, bool normalize = true);
+
+ ///
+ /// Sends an email.
+ ///
+ /// Mail to be sent
+ ///
+ /// Should normalize email?
+ /// If true, it sets sender address/name if it's not set before and makes mail encoding UTF-8.
+ ///
+ Task SendAsync(MailMessage mail, bool normalize = true);
+ }
+}
diff --git a/src/Volo.Abp.Emailing/Volo/Abp/Emailing/IEmailSenderConfiguration.cs b/src/Volo.Abp.Emailing/Volo/Abp/Emailing/IEmailSenderConfiguration.cs
new file mode 100644
index 0000000000..fc997af1ce
--- /dev/null
+++ b/src/Volo.Abp.Emailing/Volo/Abp/Emailing/IEmailSenderConfiguration.cs
@@ -0,0 +1,18 @@
+namespace Volo.Abp.Emailing
+{
+ ///
+ /// Defines configurations used while sending emails.
+ ///
+ public interface IEmailSenderConfiguration
+ {
+ ///
+ /// Default from address.
+ ///
+ string DefaultFromAddress { get; }
+
+ ///
+ /// Default display name.
+ ///
+ string DefaultFromDisplayName { get; }
+ }
+}
\ No newline at end of file
diff --git a/src/Volo.Abp.Emailing/Volo/Abp/Emailing/NullEmailSender.cs b/src/Volo.Abp.Emailing/Volo/Abp/Emailing/NullEmailSender.cs
new file mode 100644
index 0000000000..baf9440e3f
--- /dev/null
+++ b/src/Volo.Abp.Emailing/Volo/Abp/Emailing/NullEmailSender.cs
@@ -0,0 +1,49 @@
+using System.Net.Mail;
+using System.Threading.Tasks;
+using Microsoft.Extensions.Logging;
+using Microsoft.Extensions.Logging.Abstractions;
+
+namespace Volo.Abp.Emailing
+{
+ ///
+ /// This class is an implementation of as similar to null pattern.
+ /// It does not send emails but logs them.
+ ///
+ public class NullEmailSender : EmailSenderBase
+ {
+ public ILogger Logger { get; set; }
+
+ ///
+ /// Creates a new object.
+ ///
+ /// Configuration
+ public NullEmailSender(IEmailSenderConfiguration configuration)
+ : base(configuration)
+ {
+ Logger = NullLogger.Instance;
+ }
+
+ protected override Task SendEmailAsync(MailMessage mail)
+ {
+ Logger.LogWarning("USING NullEmailSender!");
+ Logger.LogDebug("SendEmailAsync:");
+ LogEmail(mail);
+ return Task.FromResult(0);
+ }
+
+ protected override void SendEmail(MailMessage mail)
+ {
+ Logger.LogWarning("USING NullEmailSender!");
+ Logger.LogWarning("SendEmail:");
+ LogEmail(mail);
+ }
+
+ private void LogEmail(MailMessage mail)
+ {
+ Logger.LogDebug(mail.To.ToString());
+ Logger.LogDebug(mail.CC.ToString());
+ Logger.LogDebug(mail.Subject);
+ Logger.LogDebug(mail.Body);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Smtp/ISmtpEmailSender.cs b/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Smtp/ISmtpEmailSender.cs
new file mode 100644
index 0000000000..989ae6e372
--- /dev/null
+++ b/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Smtp/ISmtpEmailSender.cs
@@ -0,0 +1,18 @@
+using System.Net.Mail;
+
+namespace Volo.Abp.Emailing.Smtp
+{
+ ///
+ /// Used to send emails over SMTP.
+ ///
+ public interface ISmtpEmailSender : IEmailSender
+ {
+ ///
+ /// Creates and configures new object to send emails.
+ ///
+ ///
+ /// An object that is ready to send emails.
+ ///
+ SmtpClient BuildClient();
+ }
+}
\ No newline at end of file
diff --git a/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Smtp/ISmtpEmailSenderConfiguration.cs b/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Smtp/ISmtpEmailSenderConfiguration.cs
new file mode 100644
index 0000000000..b6abce9249
--- /dev/null
+++ b/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Smtp/ISmtpEmailSenderConfiguration.cs
@@ -0,0 +1,43 @@
+namespace Volo.Abp.Emailing.Smtp
+{
+ ///
+ /// Defines configurations to used by SmtpClient object.
+ ///
+ public interface ISmtpEmailSenderConfiguration : IEmailSenderConfiguration
+ {
+ ///
+ /// SMTP Host name/IP.
+ ///
+ string Host { get; }
+
+ ///
+ /// SMTP Port.
+ ///
+ int Port { get; }
+
+ ///
+ /// User name to login to SMTP server.
+ ///
+ string UserName { get; }
+
+ ///
+ /// Password to login to SMTP server.
+ ///
+ string Password { get; }
+
+ ///
+ /// Domain name to login to SMTP server.
+ ///
+ string Domain { get; }
+
+ ///
+ /// Is SSL enabled?
+ ///
+ bool EnableSsl { get; }
+
+ ///
+ /// Use default credentials?
+ ///
+ bool UseDefaultCredentials { get; }
+ }
+}
\ No newline at end of file
diff --git a/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Smtp/SmtpEmailSender.cs b/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Smtp/SmtpEmailSender.cs
new file mode 100644
index 0000000000..3b45ab13ee
--- /dev/null
+++ b/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Smtp/SmtpEmailSender.cs
@@ -0,0 +1,83 @@
+using System;
+using System.Net;
+using System.Net.Mail;
+using System.Threading.Tasks;
+using Volo.Abp.DependencyInjection;
+
+namespace Volo.Abp.Emailing.Smtp
+{
+ ///
+ /// Used to send emails over SMTP.
+ ///
+ public class SmtpEmailSender : EmailSenderBase, ISmtpEmailSender, ITransientDependency
+ {
+ private readonly ISmtpEmailSenderConfiguration _configuration;
+
+ ///
+ /// Creates a new .
+ ///
+ /// Configuration
+ public SmtpEmailSender(ISmtpEmailSenderConfiguration configuration)
+ : base(configuration)
+ {
+ _configuration = configuration;
+ }
+
+ public SmtpClient BuildClient()
+ {
+ var host = _configuration.Host;
+ var port = _configuration.Port;
+
+ var smtpClient = new SmtpClient(host, port);
+ try
+ {
+ if (_configuration.EnableSsl)
+ {
+ smtpClient.EnableSsl = true;
+ }
+
+ if (_configuration.UseDefaultCredentials)
+ {
+ smtpClient.UseDefaultCredentials = true;
+ }
+ else
+ {
+ smtpClient.UseDefaultCredentials = false;
+
+ var userName = _configuration.UserName;
+ if (!userName.IsNullOrEmpty())
+ {
+ var password = _configuration.Password;
+ var domain = _configuration.Domain;
+ smtpClient.Credentials = !domain.IsNullOrEmpty()
+ ? new NetworkCredential(userName, password, domain)
+ : new NetworkCredential(userName, password);
+ }
+ }
+
+ return smtpClient;
+ }
+ catch
+ {
+ smtpClient.Dispose();
+ throw;
+ }
+ }
+
+ protected override async Task SendEmailAsync(MailMessage mail)
+ {
+ using (var smtpClient = BuildClient())
+ {
+ await smtpClient.SendMailAsync(mail);
+ }
+ }
+
+ protected override void SendEmail(MailMessage mail)
+ {
+ using (var smtpClient = BuildClient())
+ {
+ smtpClient.Send(mail);
+ }
+ }
+ }
+}
diff --git a/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Smtp/SmtpEmailSenderConfiguration.cs b/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Smtp/SmtpEmailSenderConfiguration.cs
new file mode 100644
index 0000000000..b114cc43dd
--- /dev/null
+++ b/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Smtp/SmtpEmailSenderConfiguration.cs
@@ -0,0 +1,33 @@
+using System;
+using Volo.Abp.DependencyInjection;
+using Volo.Abp.Settings;
+
+namespace Volo.Abp.Emailing.Smtp
+{
+ ///
+ /// Implementation of that reads settings
+ /// from .
+ ///
+ public class SmtpEmailSenderConfiguration : EmailSenderConfiguration, ISmtpEmailSenderConfiguration, ITransientDependency
+ {
+ public virtual string Host => GetNotEmptySettingValue(EmailSettingNames.Smtp.Host);
+
+ public virtual int Port => GetNotEmptySettingValue(EmailSettingNames.Smtp.Port).To();
+
+ public virtual string UserName => GetNotEmptySettingValue(EmailSettingNames.Smtp.UserName);
+
+ public virtual string Password => GetNotEmptySettingValue(EmailSettingNames.Smtp.Password);
+
+ public virtual string Domain => SettingManager.GetOrNull(EmailSettingNames.Smtp.Domain);
+
+ public virtual bool EnableSsl => SettingManager.GetOrNull(EmailSettingNames.Smtp.EnableSsl).To();
+
+ public virtual bool UseDefaultCredentials => SettingManager.GetOrNull(EmailSettingNames.Smtp.UseDefaultCredentials).To();
+
+ public SmtpEmailSenderConfiguration(ISettingManager settingManager)
+ : base(settingManager)
+ {
+
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Volo.Abp.Settings/Volo/Abp/Settings/SettingManagerSyncExtensions.cs b/src/Volo.Abp.Settings/Volo/Abp/Settings/SettingManagerSyncExtensions.cs
index f9fa53ea4c..da45dd2c1e 100644
--- a/src/Volo.Abp.Settings/Volo/Abp/Settings/SettingManagerSyncExtensions.cs
+++ b/src/Volo.Abp.Settings/Volo/Abp/Settings/SettingManagerSyncExtensions.cs
@@ -1,8 +1,23 @@
-namespace Volo.Abp.Settings
+using System.Collections.Generic;
+using JetBrains.Annotations;
+using Volo.Abp.Threading;
+
+namespace Volo.Abp.Settings
{
public static class SettingManagerSyncExtensions
{
- //TODO: Add sync extension methods for all setting manager methods.
- //TODO: Also add sync extension methods for all value provider extensions (like GlobalSettingManagerExtensions).
+ public static string GetOrNull([NotNull] this ISettingManager settingManager, [NotNull] string name)
+ {
+ Check.NotNull(settingManager, nameof(settingManager));
+
+ return AsyncHelper.RunSync(() => settingManager.GetOrNullAsync(name));
+ }
+
+ public static List GetAll([NotNull] this ISettingManager settingManager)
+ {
+ Check.NotNull(settingManager, nameof(settingManager));
+
+ return AsyncHelper.RunSync(settingManager.GetAllAsync);
+ }
}
}