diff --git a/DNN Platform/Library/Services/Mail/CoreMailProvider.cs b/DNN Platform/Library/Services/Mail/CoreMailProvider.cs
index f795021905d..b53e6a05de1 100644
--- a/DNN Platform/Library/Services/Mail/CoreMailProvider.cs
+++ b/DNN Platform/Library/Services/Mail/CoreMailProvider.cs
@@ -9,6 +9,8 @@ namespace DotNetNuke.Services.Mail
using System.Net;
using System.Net.Mail;
using System.Text.RegularExpressions;
+ using System.Threading;
+ using System.Threading.Tasks;
using DotNetNuke.Common.Utilities;
using DotNetNuke.Entities.Host;
@@ -24,24 +26,91 @@ public class CoreMailProvider : MailProvider
///
public override string SendMail(MailInfo mailInfo, SmtpInfo smtpInfo = null)
{
- // validate smtp server
- if (smtpInfo == null || string.IsNullOrEmpty(smtpInfo.Server))
+ var (host, port, errorMessage) = ParseSmtpServer(ref smtpInfo);
+ if (errorMessage != null)
{
- if (string.IsNullOrWhiteSpace(Host.SMTPServer))
+ return errorMessage;
+ }
+
+ using (var mailMessage = CreateMailMessage(mailInfo, smtpInfo))
+ {
+ try
{
- return "SMTP Server not configured";
+ using (var smtpClient = CreateSmtpClient(smtpInfo, host, port))
+ {
+ smtpClient.Send(mailMessage);
+ }
+
+ return string.Empty;
}
+ catch (Exception exc)
+ {
+ return HandleException(exc);
+ }
+ }
+ }
- smtpInfo = new SmtpInfo
+ ///
+ public override async Task SendMailAsync(MailInfo mailInfo, SmtpInfo smtpInfo = null, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ var (host, port, errorMessage) = ParseSmtpServer(ref smtpInfo);
+ if (errorMessage != null)
+ {
+ return errorMessage;
+ }
+
+ using (var mailMessage = CreateMailMessage(mailInfo, smtpInfo))
+ {
+ try
+ {
+ using (var smtpClient = CreateSmtpClient(smtpInfo, host, port))
+ {
+ await smtpClient.SendMailAsync(mailMessage);
+ }
+
+ return string.Empty;
+ }
+ catch (Exception exc)
{
- Server = Host.SMTPServer,
- Authentication = Host.SMTPAuthentication,
- Username = Host.SMTPUsername,
- Password = Host.SMTPPassword,
- EnableSSL = Host.EnableSMTPSSL,
- };
+ return HandleException(exc);
+ }
+ }
+ }
+
+ private static string ValidateSmtpInfo(SmtpInfo smtpInfo)
+ {
+ if (smtpInfo != null && !string.IsNullOrEmpty(smtpInfo.Server))
+ {
+ return null;
+ }
+
+ if (!string.IsNullOrWhiteSpace(Host.SMTPServer))
+ {
+ return null;
+ }
+
+ return "SMTP Server not configured";
+ }
+
+ private static SmtpInfo GetDefaultSmtpInfo(SmtpInfo smtpInfo)
+ {
+ if (smtpInfo != null && !string.IsNullOrEmpty(smtpInfo.Server))
+ {
+ return smtpInfo;
}
+ return new SmtpInfo
+ {
+ Server = Host.SMTPServer,
+ Authentication = Host.SMTPAuthentication,
+ Username = Host.SMTPUsername,
+ Password = Host.SMTPPassword,
+ EnableSSL = Host.EnableSMTPSSL,
+ };
+ }
+
+ private static MailMessage CreateMailMessage(MailInfo mailInfo, SmtpInfo smtpInfo)
+ {
// translate semi-colon delimiters to commas as ASP.NET 2.0 does not support semi-colons
if (!string.IsNullOrEmpty(mailInfo.To))
{
@@ -81,8 +150,9 @@ public override string SendMail(MailInfo mailInfo, SmtpInfo smtpInfo = null)
var senderAddress = mailInfo.Sender;
var senderDisplayName = mailInfo.FromName;
var needUpdateSender = false;
- if (smtpInfo.Username.Contains("@") && senderAddress == Host.HostEmail &&
- !senderAddress.Equals(smtpInfo.Username, StringComparison.InvariantCultureIgnoreCase))
+ if (smtpInfo.Username.Contains("@")
+ && senderAddress == Host.HostEmail
+ && !senderAddress.Equals(smtpInfo.Username, StringComparison.InvariantCultureIgnoreCase))
{
senderAddress = smtpInfo.Username;
needUpdateSender = true;
@@ -101,7 +171,9 @@ public override string SendMail(MailInfo mailInfo, SmtpInfo smtpInfo = null)
}
else if (smtpInfo.Username.Contains("@"))
{
- mailMessage.Sender = new MailAddress(smtpInfo.Username, Host.SMTPPortalEnabled ? PortalSettings.Current.PortalName : Host.HostTitle);
+ mailMessage.Sender = new MailAddress(
+ smtpInfo.Username,
+ Host.SMTPPortalEnabled ? PortalSettings.Current.PortalName : Host.HostTitle);
}
}
@@ -121,81 +193,107 @@ public override string SendMail(MailInfo mailInfo, SmtpInfo smtpInfo = null)
// message
mailMessage.Subject = HtmlUtils.StripWhiteSpace(mailInfo.Subject, true);
mailMessage.Body = mailInfo.Body;
+ return mailMessage;
+ }
+
+ private static (string host, int? port, string errorMessage) ParseSmtpServer(ref SmtpInfo smtpInfo)
+ {
+ var errorMessage = ValidateSmtpInfo(smtpInfo);
+ if (errorMessage != null)
+ {
+ return (null, null, errorMessage);
+ }
+
+ smtpInfo = GetDefaultSmtpInfo(smtpInfo);
+
smtpInfo.Server = smtpInfo.Server.Trim();
if (!SmtpServerRegex.IsMatch(smtpInfo.Server))
{
- return Localize.GetString("SMTPConfigurationProblem");
+ return (null, null, Localize.GetString("SMTPConfigurationProblem"));
+ }
+
+ var smtpHostParts = smtpInfo.Server.Split(':');
+ var host = smtpHostParts[0];
+ if (smtpHostParts.Length <= 1)
+ {
+ return (host, null, null);
+ }
+
+ // port is guaranteed to be of max 5 digits numeric by the RegEx check
+ var port = int.Parse(smtpHostParts[1]);
+ if (port < 1 || port > 65535)
+ {
+ return (null, null, Localize.GetString("SmtpInvalidPort"));
}
+ return (host, port, null);
+ }
+
+ private static SmtpClient CreateSmtpClient(SmtpInfo smtpInfo, string host, int? port)
+ {
+ SmtpClient client = null;
try
{
- // to workaround problem in 4.0 need to specify host name
- using (var smtpClient = new SmtpClient())
+ client = new SmtpClient();
+ client.Host = host;
+ if (port != null)
{
- var smtpHostParts = smtpInfo.Server.Split(':');
- smtpClient.Host = smtpHostParts[0];
- if (smtpHostParts.Length > 1)
- {
- // port is guaranteed to be of max 5 digits numeric by the RegEx check
- var port = int.Parse(smtpHostParts[1]);
- if (port < 1 || port > 65535)
- {
- return Localize.GetString("SmtpInvalidPort");
- }
-
- smtpClient.Port = port;
- }
+ client.Port = port.Value;
+ }
- switch (smtpInfo.Authentication)
- {
- case "":
- case "0": // anonymous
- break;
- case "1": // basic
- if (!string.IsNullOrEmpty(smtpInfo.Username)
- && !string.IsNullOrEmpty(smtpInfo.Password))
- {
- smtpClient.UseDefaultCredentials = false;
- smtpClient.Credentials = new NetworkCredential(
- smtpInfo.Username,
- smtpInfo.Password);
- }
-
- break;
- case "2": // NTLM
- smtpClient.UseDefaultCredentials = true;
- break;
- }
+ SetSmtpClientAuthentication(smtpInfo, client);
- smtpClient.EnableSsl = smtpInfo.EnableSSL;
- smtpClient.Send(mailMessage);
- smtpClient.Dispose();
- }
+ client.EnableSsl = smtpInfo.EnableSSL;
- return string.Empty;
+ var returnedClient = client;
+ client = null;
+
+ return returnedClient;
}
- catch (Exception exc)
+ finally
{
- var retValue = Localize.GetString("SMTPConfigurationProblem") + " ";
+ client?.Dispose();
+ }
+ }
- // mail configuration problem
- if (exc.InnerException != null)
- {
- retValue += string.Concat(exc.Message, Environment.NewLine, exc.InnerException.Message);
- Exceptions.Exceptions.LogException(exc.InnerException);
- }
- else
- {
- retValue += exc.Message;
- Exceptions.Exceptions.LogException(exc);
- }
+ private static void SetSmtpClientAuthentication(SmtpInfo smtpInfo, SmtpClient smtpClient)
+ {
+ switch (smtpInfo.Authentication)
+ {
+ case "":
+ case "0": // anonymous
+ break;
+ case "1": // basic
+ if (!string.IsNullOrEmpty(smtpInfo.Username) && !string.IsNullOrEmpty(smtpInfo.Password))
+ {
+ smtpClient.UseDefaultCredentials = false;
+ smtpClient.Credentials = new NetworkCredential(smtpInfo.Username, smtpInfo.Password);
+ }
- return retValue;
+ break;
+ case "2": // NTLM
+ smtpClient.UseDefaultCredentials = true;
+ break;
}
- finally
+ }
+
+ private static string HandleException(Exception exc)
+ {
+ var retValue = Localize.GetString("SMTPConfigurationProblem") + " ";
+
+ // mail configuration problem
+ if (exc.InnerException != null)
{
- mailMessage.Dispose();
+ retValue += string.Concat(exc.Message, Environment.NewLine, exc.InnerException.Message);
+ Exceptions.Exceptions.LogException(exc.InnerException);
}
+ else
+ {
+ retValue += exc.Message;
+ Exceptions.Exceptions.LogException(exc);
+ }
+
+ return retValue;
}
}
}
diff --git a/DNN Platform/Library/Services/Mail/MailKitMailProvider.cs b/DNN Platform/Library/Services/Mail/MailKitMailProvider.cs
index 644d4c0cc4d..da581c6b5be 100644
--- a/DNN Platform/Library/Services/Mail/MailKitMailProvider.cs
+++ b/DNN Platform/Library/Services/Mail/MailKitMailProvider.cs
@@ -6,6 +6,8 @@ namespace DotNetNuke.Services.Mail
using System;
using System.Linq;
using System.Text.RegularExpressions;
+ using System.Threading;
+ using System.Threading.Tasks;
using DotNetNuke.Common.Utilities;
using DotNetNuke.Entities.Host;
@@ -26,24 +28,140 @@ public class MailKitMailProvider : MailProvider
///
public override string SendMail(MailInfo mailInfo, SmtpInfo smtpInfo = null)
{
- // validate smtp server
+ try
+ {
+ var (host, port, errorMessage) = ParseSmtpServer(ref smtpInfo);
+ if (errorMessage != null)
+ {
+ return errorMessage;
+ }
+
+ var mailMessage = CreateMailMessage(mailInfo, smtpInfo);
+
+ using (var smtpClient = new SmtpClient())
+ {
+ smtpClient.Connect(host, port, SecureSocketOptions.Auto);
+
+ if (smtpInfo.Authentication == "1" && !string.IsNullOrEmpty(smtpInfo.Username) && !string.IsNullOrEmpty(smtpInfo.Password))
+ {
+ smtpClient.Authenticate(smtpInfo.Username, smtpInfo.Password);
+ }
+
+ smtpClient.Send(mailMessage);
+ smtpClient.Disconnect(true);
+ }
+
+ return string.Empty;
+ }
+ catch (Exception exc)
+ {
+ return HandleException(exc);
+ }
+ }
+
+ ///
+ public override async Task SendMailAsync(MailInfo mailInfo, SmtpInfo smtpInfo = null, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ var (host, port, errorMessage) = ParseSmtpServer(ref smtpInfo);
+ if (errorMessage != null)
+ {
+ return errorMessage;
+ }
+
+ var mailMessage = CreateMailMessage(mailInfo, smtpInfo);
+
+ try
+ {
+ using (var smtpClient = new SmtpClient())
+ {
+ await smtpClient.ConnectAsync(host, port, SecureSocketOptions.Auto, cancellationToken);
+
+ if (smtpInfo.Authentication == "1" && !string.IsNullOrEmpty(smtpInfo.Username) && !string.IsNullOrEmpty(smtpInfo.Password))
+ {
+ await smtpClient.AuthenticateAsync(smtpInfo.Username, smtpInfo.Password, cancellationToken);
+ }
+
+ await smtpClient.SendAsync(mailMessage, cancellationToken);
+ await smtpClient.DisconnectAsync(true, cancellationToken);
+ }
+
+ return string.Empty;
+ }
+ catch (Exception exc)
+ {
+ return HandleException(exc);
+ }
+ }
+
+ private static (string host, int port, string errorMessage) ParseSmtpServer(ref SmtpInfo smtpInfo)
+ {
+ var port = 25;
if (smtpInfo == null || string.IsNullOrEmpty(smtpInfo.Server))
{
if (string.IsNullOrWhiteSpace(Host.SMTPServer))
{
- return "SMTP Server not configured";
+ return (null, port, "SMTP Server not configured");
}
smtpInfo = new SmtpInfo
- {
- Server = Host.SMTPServer,
- Authentication = Host.SMTPAuthentication,
- Username = Host.SMTPUsername,
- Password = Host.SMTPPassword,
- EnableSSL = Host.EnableSMTPSSL,
- };
+ {
+ Server = Host.SMTPServer,
+ Authentication = Host.SMTPAuthentication,
+ Username = Host.SMTPUsername,
+ Password = Host.SMTPPassword,
+ EnableSSL = Host.EnableSMTPSSL,
+ };
+ }
+
+ if (smtpInfo.Authentication == "2")
+ {
+ throw new NotSupportedException("NTLM authentication is not supported by MailKit provider");
+ }
+
+ smtpInfo.Server = smtpInfo.Server.Trim();
+ if (!SmtpServerRegex.IsMatch(smtpInfo.Server))
+ {
+ return (null, port, Localize.GetString("SMTPConfigurationProblem"));
}
+ var smtpHostParts = smtpInfo.Server.Split(':');
+ var host = smtpHostParts[0];
+ if (smtpHostParts.Length <= 1)
+ {
+ return (host, port, null);
+ }
+
+ // port is guaranteed to be of max 5 digits numeric by the RegEx check
+ port = int.Parse(smtpHostParts[1]);
+ if (port < 1 || port > 65535)
+ {
+ return (host, port, Localize.GetString("SmtpInvalidPort"));
+ }
+
+ return (host, port, null);
+ }
+
+ private static string HandleException(Exception exc)
+ {
+ var retValue = Localize.GetString("SMTPConfigurationProblem") + " ";
+
+ // mail configuration problem
+ if (exc.InnerException != null)
+ {
+ retValue += string.Concat(exc.Message, Environment.NewLine, exc.InnerException.Message);
+ Exceptions.Exceptions.LogException(exc.InnerException);
+ }
+ else
+ {
+ retValue += exc.Message;
+ Exceptions.Exceptions.LogException(exc);
+ }
+
+ return retValue;
+ }
+
+ private static MimeMessage CreateMailMessage(MailInfo mailInfo, SmtpInfo smtpInfo)
+ {
var mailMessage = new MimeMessage();
mailMessage.From.Add(ParseAddressWithDisplayName(displayName: mailInfo.FromName, address: mailInfo.From));
@@ -84,8 +202,9 @@ public override string SendMail(MailInfo mailInfo, SmtpInfo smtpInfo = null)
var senderAddress = mailInfo.Sender;
var senderDisplayName = mailInfo.FromName;
var needUpdateSender = false;
- if (smtpInfo.Username.Contains("@") && senderAddress == Host.HostEmail &&
- !senderAddress.Equals(smtpInfo.Username, StringComparison.InvariantCultureIgnoreCase))
+ if (smtpInfo.Username.Contains("@")
+ && senderAddress == Host.HostEmail
+ && !senderAddress.Equals(smtpInfo.Username, StringComparison.InvariantCultureIgnoreCase))
{
senderAddress = smtpInfo.Username;
needUpdateSender = true;
@@ -99,7 +218,9 @@ public override string SendMail(MailInfo mailInfo, SmtpInfo smtpInfo = null)
if (needUpdateSender)
{
- mailMessage.Sender = ParseAddressWithDisplayName(displayName: senderDisplayName, address: senderAddress);
+ mailMessage.Sender = ParseAddressWithDisplayName(
+ displayName: senderDisplayName,
+ address: senderAddress);
}
}
else if (smtpInfo.Username.Contains("@"))
@@ -110,10 +231,7 @@ public override string SendMail(MailInfo mailInfo, SmtpInfo smtpInfo = null)
}
}
- var builder = new BodyBuilder
- {
- TextBody = Mail.ConvertToText(mailInfo.Body),
- };
+ var builder = new BodyBuilder { TextBody = Mail.ConvertToText(mailInfo.Body), };
if (mailInfo.BodyFormat == MailFormat.Html)
{
@@ -132,76 +250,7 @@ public override string SendMail(MailInfo mailInfo, SmtpInfo smtpInfo = null)
// message
mailMessage.Subject = HtmlUtils.StripWhiteSpace(mailInfo.Subject, true);
mailMessage.Body = builder.ToMessageBody();
-
- smtpInfo.Server = smtpInfo.Server.Trim();
-
- if (!SmtpServerRegex.IsMatch(smtpInfo.Server))
- {
- return Localize.GetString("SMTPConfigurationProblem");
- }
-
- try
- {
- var smtpHostParts = smtpInfo.Server.Split(':');
- var host = smtpHostParts[0];
- var port = 25;
-
- if (smtpHostParts.Length > 1)
- {
- // port is guaranteed to be of max 5 digits numeric by the RegEx check
- port = int.Parse(smtpHostParts[1]);
- if (port < 1 || port > 65535)
- {
- return Localize.GetString("SmtpInvalidPort");
- }
- }
-
- // to workaround problem in 4.0 need to specify host name
- using (var smtpClient = new SmtpClient())
- {
- smtpClient.Connect(host, port, SecureSocketOptions.Auto);
-
- switch (smtpInfo.Authentication)
- {
- case "":
- case "0": // anonymous
- break;
- case "1": // basic
- if (!string.IsNullOrEmpty(smtpInfo.Username)
- && !string.IsNullOrEmpty(smtpInfo.Password))
- {
- smtpClient.Authenticate(smtpInfo.Username, smtpInfo.Password);
- }
-
- break;
- case "2": // NTLM (Not Supported by MailKit)
- throw new NotSupportedException("NTLM authentication is not supported by MailKit provider");
- }
-
- smtpClient.Send(mailMessage);
- smtpClient.Disconnect(true);
- }
-
- return string.Empty;
- }
- catch (Exception exc)
- {
- var retValue = Localize.GetString("SMTPConfigurationProblem") + " ";
-
- // mail configuration problem
- if (exc.InnerException != null)
- {
- retValue += string.Concat(exc.Message, Environment.NewLine, exc.InnerException.Message);
- Exceptions.Exceptions.LogException(exc.InnerException);
- }
- else
- {
- retValue += exc.Message;
- Exceptions.Exceptions.LogException(exc);
- }
-
- return retValue;
- }
+ return mailMessage;
}
private static MailboxAddress ParseAddressWithDisplayName(string displayName, string address)
diff --git a/DNN Platform/Library/Services/Mail/MailProvider.cs b/DNN Platform/Library/Services/Mail/MailProvider.cs
index d3220397869..163f4334847 100644
--- a/DNN Platform/Library/Services/Mail/MailProvider.cs
+++ b/DNN Platform/Library/Services/Mail/MailProvider.cs
@@ -3,22 +3,35 @@
// See the LICENSE file in the project root for more information
namespace DotNetNuke.Services.Mail
{
+ using System.Threading;
+ using System.Threading.Tasks;
+
using DotNetNuke.ComponentModel;
/// A provider with the ability to send emails.
public abstract class MailProvider
- {
- /// Sends an email.
- /// Information about the message to send.
- /// Information about the SMTP server via which to send the message.
- /// if the message send successfully, otherwise an error message.
- public abstract string SendMail(MailInfo mailInfo, SmtpInfo smtpInfo = null);
-
- /// Gets the currently configured instance.
+ {
+ /// Gets the currently configured instance.
/// A instance.
public static MailProvider Instance()
{
return ComponentFactory.GetComponent();
}
+
+ /// Sends an email.
+ /// Information about the message to send.
+ /// Information about the SMTP server via which to send the message.
+ /// if the message send successfully, otherwise an error message.
+ public abstract string SendMail(MailInfo mailInfo, SmtpInfo smtpInfo = null);
+
+ /// Sends an email.
+ /// Information about the message to send.
+ /// Information about the SMTP server via which to send the message.
+ /// The cancellation token.
+ /// if the message send successfully, otherwise an error message.
+ public virtual async Task SendMailAsync(MailInfo mailInfo, SmtpInfo smtpInfo = null, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ return this.SendMail(mailInfo, smtpInfo);
+ }
}
}