Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add async support to mail providers #4498

Merged
merged 1 commit into from
Mar 16, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
240 changes: 169 additions & 71 deletions DNN Platform/Library/Services/Mail/CoreMailProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -24,24 +26,91 @@ public class CoreMailProvider : MailProvider
/// <inheritdoc />
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
/// <inheritdoc />
public override async Task<string> 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))
{
Expand Down Expand Up @@ -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;
Expand All @@ -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);
}
}

Expand All @@ -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;
}
}
}
Loading