Skip to content

Commit

Permalink
Add FromName and ReplyTo properties to SmtpSettingsPart (#8420)
Browse files Browse the repository at this point in the history
  • Loading branch information
aaronamm authored Oct 15, 2020
1 parent 70c04a9 commit 1c93e4a
Show file tree
Hide file tree
Showing 9 changed files with 201 additions and 109 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
using System;
using System.Collections.Generic;
using System.Web.Hosting;
using System.Web.Mvc;
using Orchard.ContentManagement;
using Orchard.Email.Models;
Expand Down Expand Up @@ -29,23 +28,25 @@ public ActionResult TestSettings(TestSmtpSettings testSettings) {
ILogger logger = null;
try {
var fakeLogger = new FakeLogger();
var smtpChannelComponent = _smtpChannel as Component;
if (smtpChannelComponent != null) {
if (_smtpChannel is Component smtpChannelComponent) {
logger = smtpChannelComponent.Logger;
smtpChannelComponent.Logger = fakeLogger;
}

// Temporarily update settings so that the test will actually use the specified host, port, etc.
var smtpSettings = _orchardServices.WorkContext.CurrentSite.As<SmtpSettingsPart>();

smtpSettings.Address = testSettings.From;
smtpSettings.FromAddress = testSettings.FromAddress;
smtpSettings.FromName = testSettings.FromName;
smtpSettings.ReplyTo = testSettings.ReplyTo;
smtpSettings.Host = testSettings.Host;
smtpSettings.Port = testSettings.Port;
smtpSettings.EnableSsl = testSettings.EnableSsl;
smtpSettings.RequireCredentials = testSettings.RequireCredentials;
smtpSettings.UseDefaultCredentials = testSettings.UseDefaultCredentials;
smtpSettings.UserName = testSettings.UserName;
smtpSettings.Password = testSettings.Password;
smtpSettings.ListUnsubscribe = testSettings.ListUnsubscribe;

if (!smtpSettings.IsValid()) {
fakeLogger.Error("Invalid settings.");
Expand All @@ -57,7 +58,7 @@ public ActionResult TestSettings(TestSmtpSettings testSettings) {
});
}

if (!String.IsNullOrEmpty(fakeLogger.Message)) {
if (!string.IsNullOrEmpty(fakeLogger.Message)) {
return Json(new { error = fakeLogger.Message });
}

Expand All @@ -67,30 +68,28 @@ public ActionResult TestSettings(TestSmtpSettings testSettings) {
return Json(new { error = e.Message });
}
finally {
var smtpChannelComponent = _smtpChannel as Component;
if (smtpChannelComponent != null) {
if (_smtpChannel is Component smtpChannelComponent) {
smtpChannelComponent.Logger = logger;
}

// Undo the temporarily changed smtp settings.
// Undo the temporarily changed SMTP settings.
_orchardServices.TransactionManager.Cancel();
}
}

private class FakeLogger : ILogger {
public string Message { get; set; }

public bool IsEnabled(LogLevel level) {
return true;
}
public bool IsEnabled(LogLevel level) => true;

public void Log(LogLevel level, Exception exception, string format, params object[] args) {
public void Log(LogLevel level, Exception exception, string format, params object[] args) =>
Message = exception == null ? format : exception.Message;
}
}

public class TestSmtpSettings {
public string From { get; set; }
public string FromAddress { get; set; }
public string FromName { get; set; }
public string ReplyTo { get; set; }
public string Host { get; set; }
public int Port { get; set; }
public bool EnableSsl { get; set; }
Expand All @@ -99,6 +98,7 @@ public class TestSmtpSettings {
public string UserName { get; set; }
public string Password { get; set; }
public string To { get; set; }
public string ListUnsubscribe { get; set; }
}
}
}
36 changes: 32 additions & 4 deletions src/Orchard.Web/Modules/Orchard.Email/Migrations.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,39 @@
using Orchard.Data.Migration;
using System.Linq;
using System.Xml;
using Orchard.ContentManagement;
using Orchard.Data.Migration;
using Orchard.Email.Models;

namespace Orchard.Email {
public class Migrations : DataMigrationImpl {
private readonly IContentManager _contentManager;

public int Create() {
public Migrations(IContentManager contentManager) => _contentManager = contentManager;

return 1;
// The first migration without any content should not exist but it has been deployed so we need to keep it.
public int Create() => 1;

public int UpdateFrom1() {
// Migrate existing SmtpSettingPart.Address because we rename it to FromAddress.
var siteSettingsItem = _contentManager.Query(contentTypeNames: "Site")
.Slice(1)
.SingleOrDefault();

var siteSettingsRecord = siteSettingsItem?.Record;

if (siteSettingsRecord != null) {
var xmlDoc = new XmlDocument();
xmlDoc.LoadXml(siteSettingsRecord.Data);

var smtpSettingNode = xmlDoc.SelectSingleNode("//SmtpSettingsPart");
if (smtpSettingNode != null) {
var smtpSettingsPart = siteSettingsItem.As<SmtpSettingsPart>();
smtpSettingsPart.FromAddress = smtpSettingNode.Attributes["Address"]?.Value;
}
}

return 2;
}
}
}
}

3 changes: 2 additions & 1 deletion src/Orchard.Web/Modules/Orchard.Email/Models/EmailMessage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ public class EmailMessage {
public string Body { get; set; }
public string Recipients { get; set; }
public string ReplyTo { get; set; }
public string From { get; set; }
public string FromAddress { get; set; }
public string FromName { get; set; }
public string Bcc { get; set; }
public string Cc { get; set; }
/// <summary>
Expand Down
68 changes: 43 additions & 25 deletions src/Orchard.Web/Modules/Orchard.Email/Models/SmtpSettingsPart.cs
Original file line number Diff line number Diff line change
@@ -1,72 +1,90 @@
using System.Configuration;
using System.Net.Configuration;
using Orchard.ContentManagement;
using System;
using Orchard.ContentManagement.Utilities;

namespace Orchard.Email.Models {
public class SmtpSettingsPart : ContentPart {
private readonly ComputedField<string> _password = new ComputedField<string>();

public ComputedField<string> PasswordField {
get { return _password; }
public ComputedField<string> PasswordField => _password;

public string FromAddress {
get => this.Retrieve(x => x.FromAddress);
set => this.Store(x => x.FromAddress, value);
}

public string FromName {
get => this.Retrieve(x => x.FromName);
set => this.Store(x => x.FromName, value);
}

public string Address {
get { return this.Retrieve(x => x.Address); }
set { this.Store(x => x.Address, value); }
public string ReplyTo {
get => this.Retrieve(x => x.ReplyTo);
set => this.Store(x => x.ReplyTo, value);
}

private readonly LazyField<string> _addressPlaceholder = new LazyField<string>();
internal LazyField<string> AddressPlaceholderField { get { return _addressPlaceholder; } }
public string AddressPlaceholder { get { return _addressPlaceholder.Value; } }
internal LazyField<string> AddressPlaceholderField => _addressPlaceholder;
public string AddressPlaceholder => _addressPlaceholder.Value;

public string Host {
get { return this.Retrieve(x => x.Host); }
set { this.Store(x => x.Host, value); }
get => this.Retrieve(x => x.Host);
set => this.Store(x => x.Host, value);
}

public int Port {
get { return this.Retrieve(x => x.Port, 25); }
set { this.Store(x => x.Port, value); }
get => this.Retrieve(x => x.Port, 25);
set => this.Store(x => x.Port, value);
}

public bool EnableSsl {
get { return this.Retrieve(x => x.EnableSsl); }
set { this.Store(x => x.EnableSsl, value); }
get => this.Retrieve(x => x.EnableSsl);
set => this.Store(x => x.EnableSsl, value);
}

public bool RequireCredentials {
get { return this.Retrieve(x => x.RequireCredentials); }
set { this.Store(x => x.RequireCredentials, value); }
get => this.Retrieve(x => x.RequireCredentials);
set => this.Store(x => x.RequireCredentials, value);
}

public bool UseDefaultCredentials {
get { return this.Retrieve(x => x.UseDefaultCredentials); }
set { this.Store(x => x.UseDefaultCredentials, value); }
get => this.Retrieve(x => x.UseDefaultCredentials);
set => this.Store(x => x.UseDefaultCredentials, value);
}

public string UserName {
get { return this.Retrieve(x => x.UserName); }
set { this.Store(x => x.UserName, value); }
get => this.Retrieve(x => x.UserName);
set => this.Store(x => x.UserName, value);
}

public string Password {
get { return _password.Value; }
set { _password.Value = value; }
get => _password.Value;
set => _password.Value = value;
}

// Hotmail only supports the mailto:link. When a user clicks on the 'unsubscribe' option in Hotmail.
// Hotmail tries to read the mailto:link in the List-Unsubscribe header.
// If the mailto:link is missing, it moves all the messages to the Junk folder.
// The mailto:link is supported by Gmail, Hotmail, Yahoo, AOL, ATT, Time Warner and Comcast;
// European ISPs such as GMX, Libero, Ziggo, Orange, BTInternet; Russian ISPs such as mail.ru and Yandex;
// and the Chinese domains qq.com, naver.com etc. So most ISPs support (and prefer) mailto:link.
public string ListUnsubscribe {
get => this.Retrieve(x => x.ListUnsubscribe);
set => this.Store(x => x.ListUnsubscribe, value);
}

public bool IsValid() {
var section = (SmtpSection)ConfigurationManager.GetSection("system.net/mailSettings/smtp");
if (section != null && !String.IsNullOrWhiteSpace(section.Network.Host)) {
if (section != null && !string.IsNullOrWhiteSpace(section.Network.Host)) {
return true;
}

if (String.IsNullOrWhiteSpace(Address)) {
if (string.IsNullOrWhiteSpace(FromAddress)) {
return false;
}

if (!String.IsNullOrWhiteSpace(Host) && Port == 0) {
if (!string.IsNullOrWhiteSpace(Host) && Port == 0) {
return false;
}

Expand Down
4 changes: 4 additions & 0 deletions src/Orchard.Web/Modules/Orchard.Email/Orchard.Email.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,9 @@
<Private>False</Private>
</Reference>
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="System.ValueTuple, Version=4.0.3.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\..\..\packages\System.ValueTuple.4.5.0\lib\net461\System.ValueTuple.dll</HintPath>
</Reference>
<Reference Include="System.Web.ApplicationServices" />
<Reference Include="System.Web.DynamicData" />
<Reference Include="System.Web.Entity" />
Expand Down Expand Up @@ -98,6 +101,7 @@
<HintPath>..\..\..\packages\Microsoft.AspNet.WebPages.3.2.3\lib\net45\System.Web.WebPages.Razor.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System.Xml" />
<Reference Include="System.Xml.Linq" />
</ItemGroup>
<ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ public void SendMessage(MessageContext context) {
smtpClient.EnableSsl = smtpSettings.EnableSsl;
smtpClient.DeliveryMethod = SmtpDeliveryMethod.Network;

context.MailMessage.From = new MailAddress(smtpSettings.Address);
context.MailMessage.From = new MailAddress(smtpSettings.FromAddress);
context.MailMessage.IsBodyHtml = !String.IsNullOrWhiteSpace(context.MailMessage.Body) && context.MailMessage.Body.Contains("<") && context.MailMessage.Body.Contains(">");

try {
Expand Down
Loading

0 comments on commit 1c93e4a

Please sign in to comment.