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

Implement Email Provider #3969

Merged
merged 10 commits into from
Oct 6, 2020
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
28 changes: 15 additions & 13 deletions DNN Platform/DotNetNuke.Web/Common/DotNetNukeHttpApplication.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,14 +35,15 @@ namespace DotNetNuke.Web.Common.Internal
using DotNetNuke.Services.Search.Internals;
using DotNetNuke.Services.Sitemap;
using DotNetNuke.Services.Tokens;
using DotNetNuke.Services.Mail;
using DotNetNuke.Services.Url.FriendlyUrl;

/// <summary>
/// DotNetNuke Http Application. It will handle Start, End, BeginRequest, Error event for whole application.
/// </summary>
public class DotNetNukeHttpApplication : HttpApplication
{
private static readonly ILog Logger = LoggerSource.Instance.GetLogger(typeof (DotNetNukeHttpApplication));
{
private static readonly ILog Logger = LoggerSource.Instance.GetLogger(typeof(DotNetNukeHttpApplication));

private static readonly string[] Endings =
{
Expand Down Expand Up @@ -162,8 +163,9 @@ private void Application_Start(object sender, EventArgs eventArgs)
ComponentFactory.InstallComponents(new ProviderInstaller("htmlEditor", typeof(HtmlEditorProvider), ComponentLifeStyleType.Transient));
ComponentFactory.InstallComponents(new ProviderInstaller("navigationControl", typeof(NavigationProvider), ComponentLifeStyleType.Transient));
ComponentFactory.InstallComponents(new ProviderInstaller("clientcapability", typeof(ClientCapabilityProvider)));
ComponentFactory.InstallComponents(new ProviderInstaller("cryptography", typeof(CryptographyProvider), typeof(FipsCompilanceCryptographyProvider)));
ComponentFactory.InstallComponents(new ProviderInstaller("tokens", typeof(TokenProvider)));
ComponentFactory.InstallComponents(new ProviderInstaller("cryptography", typeof(CryptographyProvider), typeof(FipsCompilanceCryptographyProvider)));
ComponentFactory.InstallComponents(new ProviderInstaller("tokens", typeof(TokenProvider)));
ComponentFactory.InstallComponents(new ProviderInstaller("mail", typeof(MailProvider)));

Logger.InfoFormat("Application Started ({0})", Globals.ElapsedSinceAppStart); // just to start the timer
DotNetNukeShutdownOverload.InitializeFcnSettings();
Expand Down Expand Up @@ -229,17 +231,17 @@ private void Application_BeginRequest(object sender, EventArgs e)

Initialize.Init(app);
Initialize.RunSchedule(app.Request);
}

private void Application_PreSendRequestHeaders(object sender, EventArgs e)
{
if (HttpContext.Current != null && HttpContext.Current.Handler is PageBase)
{
var page = HttpContext.Current.Handler as PageBase;
page.HeaderIsWritten = true;
}
}

private void Application_PreSendRequestHeaders(object sender, EventArgs e)
{
if (HttpContext.Current != null && HttpContext.Current.Handler is PageBase)
{
var page = HttpContext.Current.Handler as PageBase;
page.HeaderIsWritten = true;
}
}

private bool IsInstallInProgress(HttpApplication app)
{
return InstallBlocker.Instance.IsInstallInProgress();
Expand Down
4 changes: 4 additions & 0 deletions DNN Platform/Library/DotNetNuke.Library.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -815,6 +815,10 @@
<Compile Include="Services\Localization\Persian\PersianCalendar.cs" />
<Compile Include="Services\Localization\Persian\PersianController.cs" />
<Compile Include="Services\Log\EventLog\ILogController.cs" />
<Compile Include="Services\Mail\CoreMailProvider.cs" />
<Compile Include="Services\Mail\MailInfo.cs" />
<Compile Include="Services\Mail\MailProvider.cs" />
<Compile Include="Services\Mail\SmtpInfo.cs" />
<Compile Include="Services\OutputCache\Providers\DatabaseProvider.cs" />
<Compile Include="Services\OutputCache\Providers\DatabaseResponseFilter.cs" />
<Compile Include="Services\OutputCache\Providers\FileProvider.cs" />
Expand Down
24 changes: 12 additions & 12 deletions DNN Platform/Library/Framework/Providers/Provider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,24 +8,24 @@ namespace DotNetNuke.Framework.Providers

public class Provider
{
private readonly NameValueCollection _ProviderAttributes = new NameValueCollection();
private readonly string _ProviderName;
private readonly string _ProviderType;
private readonly NameValueCollection providerAttributes = new NameValueCollection();
private readonly string providerName;
private readonly string providerType;

public Provider(XmlAttributeCollection Attributes)
public Provider(XmlAttributeCollection attributes)
{
// Set the name of the provider
this._ProviderName = Attributes["name"].Value;
this.providerName = attributes["name"].Value;

// Set the type of the provider
this._ProviderType = Attributes["type"].Value;
this.providerType = attributes["type"].Value;

// Store all the attributes in the attributes bucket
foreach (XmlAttribute Attribute in Attributes)
foreach (XmlAttribute attribute in attributes)
{
if (Attribute.Name != "name" && Attribute.Name != "type")
if (attribute.Name != "name" && attribute.Name != "type")
{
this._ProviderAttributes.Add(Attribute.Name, Attribute.Value);
this.providerAttributes.Add(attribute.Name, attribute.Value);
}
}
}
Expand All @@ -34,23 +34,23 @@ public string Name
{
get
{
return this._ProviderName;
return this.providerName;
}
}

public string Type
{
get
{
return this._ProviderType;
return this.providerType;
}
}

public NameValueCollection Attributes
{
get
{
return this._ProviderAttributes;
return this.providerAttributes;
}
}
}
Expand Down
15 changes: 10 additions & 5 deletions DNN Platform/Library/Framework/Providers/ProviderConfiguration.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,23 +10,28 @@ namespace DotNetNuke.Framework.Providers

public class ProviderConfiguration
{
private readonly Hashtable _Providers = new Hashtable();
private string _DefaultProvider;
private readonly Hashtable providers = new Hashtable();
private string defaultProvider;

public string DefaultProvider
{
get
{
return this._DefaultProvider;
return this.defaultProvider;
}
}

public Hashtable Providers
{
get
{
return this._Providers;
return this.providers;
}
}

public Provider GetDefaultProvider()
{
return (Provider)this.providers[this.defaultProvider];
}

public static ProviderConfiguration GetProviderConfiguration(string strProvider)
Expand All @@ -39,7 +44,7 @@ internal void LoadValuesFromConfigurationXml(XmlNode node)
XmlAttributeCollection attributeCollection = node.Attributes;

// Get the default provider
this._DefaultProvider = attributeCollection["defaultProvider"].Value;
this.defaultProvider = attributeCollection["defaultProvider"].Value;

// Read child nodes
foreach (XmlNode child in node.ChildNodes)
Expand Down
216 changes: 216 additions & 0 deletions DNN Platform/Library/Services/Mail/CoreMailProvider.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,216 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information
using DotNetNuke.Common.Utilities;
using DotNetNuke.Entities.Host;
using DotNetNuke.Entities.Portals;
using System;
using System.Net;
using System.Net.Mail;
using System.Text.RegularExpressions;
using Localize = DotNetNuke.Services.Localization.Localization;
namespace DotNetNuke.Services.Mail
{
public class CoreMailProvider : MailProvider
{
private static readonly Regex SmtpServerRegex = new Regex("^[^:]+(:[0-9]{1,5})?$", RegexOptions.Compiled);
private static string ConvertToText(string sHTML)
{
var formattedHtml = HtmlUtils.FormatText(sHTML, true);
var styleLessHtml = HtmlUtils.RemoveInlineStyle(formattedHtml);
return HtmlUtils.StripTags(styleLessHtml, true);
}
public override string SendMail(MailInfo mailInfo, SmtpInfo smtpInfo = null)
{
// validate smtp server
if (smtpInfo == null || string.IsNullOrEmpty(smtpInfo.Server))
{
if (string.IsNullOrWhiteSpace(Host.SMTPServer))
{
return "SMTP Server not configured";
}

smtpInfo = new SmtpInfo()
{
Server = Host.SMTPServer,
Authentication = Host.SMTPAuthentication,
Username = Host.SMTPUsername,
Password = Host.SMTPPassword,
EnableSSL = Host.EnableSMTPSSL,
};
}

// translate semi-colon delimiters to commas as ASP.NET 2.0 does not support semi-colons
if (!string.IsNullOrEmpty(mailInfo.To))
{
mailInfo.To = mailInfo.To.Replace(";", ",");
}

if (!string.IsNullOrEmpty(mailInfo.CC))
{
mailInfo.CC = mailInfo.CC.Replace(";", ",");
}

if (!string.IsNullOrEmpty(mailInfo.BCC))
{
mailInfo.BCC = mailInfo.BCC.Replace(";", ",");
}

string retValue = string.Empty;

MailMessage mailMessage = new MailMessage(mailInfo.From, mailInfo.To);

if (!string.IsNullOrEmpty(mailInfo.Sender))
{
mailMessage.Sender = new MailAddress(mailInfo.Sender);
}

mailMessage.Priority = (System.Net.Mail.MailPriority)mailInfo.Priority;
mailMessage.IsBodyHtml = mailInfo.BodyFormat == MailFormat.Html;

// Only modify senderAdress if smtpAuthentication is enabled
// Can be "0", empty or Null - anonymous, "1" - basic, "2" - NTLM.
if (smtpInfo.Authentication == "1" || smtpInfo.Authentication == "2")
{
// if the senderAddress is the email address of the Host then switch it smtpUsername if different
// if display name of senderAddress is empty, then use Host.HostTitle for it
if (mailMessage.Sender != 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))
{
senderAddress = smtpInfo.Username;
needUpdateSender = true;
}

if (string.IsNullOrEmpty(senderDisplayName))
{
senderDisplayName = Host.SMTPPortalEnabled ? PortalSettings.Current.PortalName : Host.HostTitle;
needUpdateSender = true;
}

if (needUpdateSender)
{
mailMessage.Sender = new MailAddress(senderAddress, senderDisplayName);
}
}
else if (smtpInfo.Username.Contains("@"))
{
mailMessage.Sender = new MailAddress(smtpInfo.Username, Host.SMTPPortalEnabled ? PortalSettings.Current.PortalName : Host.HostTitle);
}
}

//attachments
if (mailInfo.Attachments != null)
{
foreach (var attachment in mailInfo.Attachments)
{
mailMessage.Attachments.Add(attachment);
}
}

// message
mailMessage.SubjectEncoding = mailInfo.BodyEncoding;
mailMessage.Subject = HtmlUtils.StripWhiteSpace(mailInfo.Subject, true);
mailMessage.BodyEncoding = mailInfo.BodyEncoding;

// added support for multipart html messages
// add text part as alternate view
var PlainView = AlternateView.CreateAlternateViewFromString(ConvertToText(mailInfo.Body), null, "text/plain");
mailMessage.AlternateViews.Add(PlainView);
if (mailMessage.IsBodyHtml)
{
var HTMLView = AlternateView.CreateAlternateViewFromString(mailInfo.Body, null, "text/html");
mailMessage.AlternateViews.Add(HTMLView);
}

smtpInfo.Server = smtpInfo.Server.Trim();
if (SmtpServerRegex.IsMatch(smtpInfo.Server))
{
try
{
// to workaround problem in 4.0 need to specify host name
using (var smtpClient = new SmtpClient())
{
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 = Convert.ToInt32(smtpHostParts[1]);
if (port < 1 || port > 65535)
{
return Localize.GetString("SmtpInvalidPort");
}

smtpClient.Port = port;
}

// else the port defaults to 25 by .NET when not set
smtpClient.ServicePoint.MaxIdleTime = Host.SMTPMaxIdleTime;
smtpClient.ServicePoint.ConnectionLimit = Host.SMTPConnectionLimit;

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;
}

smtpClient.EnableSsl = smtpInfo.EnableSSL;
smtpClient.Send(mailMessage);
smtpClient.Dispose();
}
}
catch (Exception exc)
{
var exc2 = exc as SmtpFailedRecipientException;
if (exc2 != null)
{
retValue = string.Format(Localize.GetString("FailedRecipient"), exc2.FailedRecipient) + " ";
}
else if (exc is SmtpException)
{
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);
}
}
finally
{
mailMessage.Dispose();
}
}
else
{
retValue = Localize.GetString("SMTPConfigurationProblem");
}

return retValue;
}
}
}
Loading