Skip to content

Commit

Permalink
Add async support to mail providers
Browse files Browse the repository at this point in the history
  • Loading branch information
bdukes committed Feb 16, 2021
1 parent edb0fac commit afe0d80
Show file tree
Hide file tree
Showing 3 changed files with 325 additions and 165 deletions.
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

0 comments on commit afe0d80

Please sign in to comment.