Add FromName and ReplyTo properties to SmtpSettingsPart (#8420)

This commit is contained in:
Aaron Amm 2020-10-16 00:10:26 +07:00 committed by GitHub
parent 70c04a9a5f
commit 1c93e4a501
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 204 additions and 112 deletions

View File

@ -1,6 +1,5 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Web.Hosting;
using System.Web.Mvc; using System.Web.Mvc;
using Orchard.ContentManagement; using Orchard.ContentManagement;
using Orchard.Email.Models; using Orchard.Email.Models;
@ -29,8 +28,7 @@ namespace Orchard.Email.Controllers {
ILogger logger = null; ILogger logger = null;
try { try {
var fakeLogger = new FakeLogger(); var fakeLogger = new FakeLogger();
var smtpChannelComponent = _smtpChannel as Component; if (_smtpChannel is Component smtpChannelComponent) {
if (smtpChannelComponent != null) {
logger = smtpChannelComponent.Logger; logger = smtpChannelComponent.Logger;
smtpChannelComponent.Logger = fakeLogger; smtpChannelComponent.Logger = fakeLogger;
} }
@ -38,7 +36,9 @@ namespace Orchard.Email.Controllers {
// Temporarily update settings so that the test will actually use the specified host, port, etc. // Temporarily update settings so that the test will actually use the specified host, port, etc.
var smtpSettings = _orchardServices.WorkContext.CurrentSite.As<SmtpSettingsPart>(); 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.Host = testSettings.Host;
smtpSettings.Port = testSettings.Port; smtpSettings.Port = testSettings.Port;
smtpSettings.EnableSsl = testSettings.EnableSsl; smtpSettings.EnableSsl = testSettings.EnableSsl;
@ -46,6 +46,7 @@ namespace Orchard.Email.Controllers {
smtpSettings.UseDefaultCredentials = testSettings.UseDefaultCredentials; smtpSettings.UseDefaultCredentials = testSettings.UseDefaultCredentials;
smtpSettings.UserName = testSettings.UserName; smtpSettings.UserName = testSettings.UserName;
smtpSettings.Password = testSettings.Password; smtpSettings.Password = testSettings.Password;
smtpSettings.ListUnsubscribe = testSettings.ListUnsubscribe;
if (!smtpSettings.IsValid()) { if (!smtpSettings.IsValid()) {
fakeLogger.Error("Invalid settings."); fakeLogger.Error("Invalid settings.");
@ -57,7 +58,7 @@ namespace Orchard.Email.Controllers {
}); });
} }
if (!String.IsNullOrEmpty(fakeLogger.Message)) { if (!string.IsNullOrEmpty(fakeLogger.Message)) {
return Json(new { error = fakeLogger.Message }); return Json(new { error = fakeLogger.Message });
} }
@ -67,12 +68,11 @@ namespace Orchard.Email.Controllers {
return Json(new { error = e.Message }); return Json(new { error = e.Message });
} }
finally { finally {
var smtpChannelComponent = _smtpChannel as Component; if (_smtpChannel is Component smtpChannelComponent) {
if (smtpChannelComponent != null) {
smtpChannelComponent.Logger = logger; smtpChannelComponent.Logger = logger;
} }
// Undo the temporarily changed smtp settings. // Undo the temporarily changed SMTP settings.
_orchardServices.TransactionManager.Cancel(); _orchardServices.TransactionManager.Cancel();
} }
} }
@ -80,17 +80,16 @@ namespace Orchard.Email.Controllers {
private class FakeLogger : ILogger { private class FakeLogger : ILogger {
public string Message { get; set; } public string Message { get; set; }
public bool IsEnabled(LogLevel level) { public bool IsEnabled(LogLevel level) => true;
return 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; Message = exception == null ? format : exception.Message;
}
} }
public class TestSmtpSettings { 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 string Host { get; set; }
public int Port { get; set; } public int Port { get; set; }
public bool EnableSsl { get; set; } public bool EnableSsl { get; set; }
@ -99,6 +98,7 @@ namespace Orchard.Email.Controllers {
public string UserName { get; set; } public string UserName { get; set; }
public string Password { get; set; } public string Password { get; set; }
public string To { get; set; } public string To { get; set; }
public string ListUnsubscribe { get; set; }
} }
} }
} }

View File

@ -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 { namespace Orchard.Email {
public class Migrations : DataMigrationImpl { 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;
} }
} }
} }

View File

@ -6,7 +6,8 @@ namespace Orchard.Email.Models {
public string Body { get; set; } public string Body { get; set; }
public string Recipients { get; set; } public string Recipients { get; set; }
public string ReplyTo { 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 Bcc { get; set; }
public string Cc { get; set; } public string Cc { get; set; }
/// <summary> /// <summary>

View File

@ -1,72 +1,90 @@
using System.Configuration; using System.Configuration;
using System.Net.Configuration; using System.Net.Configuration;
using Orchard.ContentManagement; using Orchard.ContentManagement;
using System;
using Orchard.ContentManagement.Utilities; using Orchard.ContentManagement.Utilities;
namespace Orchard.Email.Models { namespace Orchard.Email.Models {
public class SmtpSettingsPart : ContentPart { public class SmtpSettingsPart : ContentPart {
private readonly ComputedField<string> _password = new ComputedField<string>(); private readonly ComputedField<string> _password = new ComputedField<string>();
public ComputedField<string> PasswordField { public ComputedField<string> PasswordField => _password;
get { return _password; }
public string FromAddress {
get => this.Retrieve(x => x.FromAddress);
set => this.Store(x => x.FromAddress, value);
} }
public string Address { public string FromName {
get { return this.Retrieve(x => x.Address); } get => this.Retrieve(x => x.FromName);
set { this.Store(x => x.Address, value); } set => this.Store(x => x.FromName, 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>(); private readonly LazyField<string> _addressPlaceholder = new LazyField<string>();
internal LazyField<string> AddressPlaceholderField { get { return _addressPlaceholder; } } internal LazyField<string> AddressPlaceholderField => _addressPlaceholder;
public string AddressPlaceholder { get { return _addressPlaceholder.Value; } } public string AddressPlaceholder => _addressPlaceholder.Value;
public string Host { public string Host {
get { return this.Retrieve(x => x.Host); } get => this.Retrieve(x => x.Host);
set { this.Store(x => x.Host, value); } set => this.Store(x => x.Host, value);
} }
public int Port { public int Port {
get { return this.Retrieve(x => x.Port, 25); } get => this.Retrieve(x => x.Port, 25);
set { this.Store(x => x.Port, value); } set => this.Store(x => x.Port, value);
} }
public bool EnableSsl { public bool EnableSsl {
get { return this.Retrieve(x => x.EnableSsl); } get => this.Retrieve(x => x.EnableSsl);
set { this.Store(x => x.EnableSsl, value); } set => this.Store(x => x.EnableSsl, value);
} }
public bool RequireCredentials { public bool RequireCredentials {
get { return this.Retrieve(x => x.RequireCredentials); } get => this.Retrieve(x => x.RequireCredentials);
set { this.Store(x => x.RequireCredentials, value); } set => this.Store(x => x.RequireCredentials, value);
} }
public bool UseDefaultCredentials { public bool UseDefaultCredentials {
get { return this.Retrieve(x => x.UseDefaultCredentials); } get => this.Retrieve(x => x.UseDefaultCredentials);
set { this.Store(x => x.UseDefaultCredentials, value); } set => this.Store(x => x.UseDefaultCredentials, value);
} }
public string UserName { public string UserName {
get { return this.Retrieve(x => x.UserName); } get => this.Retrieve(x => x.UserName);
set { this.Store(x => x.UserName, value); } set => this.Store(x => x.UserName, value);
} }
public string Password { public string Password {
get { return _password.Value; } get => _password.Value;
set { _password.Value = 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() { public bool IsValid() {
var section = (SmtpSection)ConfigurationManager.GetSection("system.net/mailSettings/smtp"); 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; return true;
} }
if (String.IsNullOrWhiteSpace(Address)) { if (string.IsNullOrWhiteSpace(FromAddress)) {
return false; return false;
} }
if (!String.IsNullOrWhiteSpace(Host) && Port == 0) { if (!string.IsNullOrWhiteSpace(Host) && Port == 0) {
return false; return false;
} }

View File

@ -69,6 +69,9 @@
<Private>False</Private> <Private>False</Private>
</Reference> </Reference>
<Reference Include="System.Data.DataSetExtensions" /> <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.ApplicationServices" />
<Reference Include="System.Web.DynamicData" /> <Reference Include="System.Web.DynamicData" />
<Reference Include="System.Web.Entity" /> <Reference Include="System.Web.Entity" />
@ -98,6 +101,7 @@
<HintPath>..\..\..\packages\Microsoft.AspNet.WebPages.3.2.3\lib\net45\System.Web.WebPages.Razor.dll</HintPath> <HintPath>..\..\..\packages\Microsoft.AspNet.WebPages.3.2.3\lib\net45\System.Web.WebPages.Razor.dll</HintPath>
<Private>True</Private> <Private>True</Private>
</Reference> </Reference>
<Reference Include="System.Xml" />
<Reference Include="System.Xml.Linq" /> <Reference Include="System.Xml.Linq" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

View File

@ -53,7 +53,7 @@ namespace Orchard.Email.Services {
smtpClient.EnableSsl = smtpSettings.EnableSsl; smtpClient.EnableSsl = smtpSettings.EnableSsl;
smtpClient.DeliveryMethod = SmtpDeliveryMethod.Network; 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(">"); context.MailMessage.IsBodyHtml = !String.IsNullOrWhiteSpace(context.MailMessage.Body) && context.MailMessage.Body.Contains("<") && context.MailMessage.Body.Contains(">");
try { try {

View File

@ -9,7 +9,6 @@ using Orchard.ContentManagement;
using Orchard.DisplayManagement; using Orchard.DisplayManagement;
using Orchard.Logging; using Orchard.Logging;
using Orchard.Email.Models; using Orchard.Email.Models;
using System.Linq;
using System.IO; using System.IO;
namespace Orchard.Email.Services { namespace Orchard.Email.Services {
@ -41,7 +40,6 @@ namespace Orchard.Email.Services {
} }
public void Process(IDictionary<string, object> parameters) { public void Process(IDictionary<string, object> parameters) {
if (!_smtpSettings.IsValid()) { if (!_smtpSettings.IsValid()) {
return; return;
} }
@ -51,10 +49,15 @@ namespace Orchard.Email.Services {
Subject = Read(parameters, "Subject"), Subject = Read(parameters, "Subject"),
Recipients = Read(parameters, "Recipients"), Recipients = Read(parameters, "Recipients"),
ReplyTo = Read(parameters, "ReplyTo"), ReplyTo = Read(parameters, "ReplyTo"),
From = Read(parameters, "From"), FromAddress = Read(parameters, "FromAddress"),
FromName = Read(parameters, "FromName"),
Bcc = Read(parameters, "Bcc"), Bcc = Read(parameters, "Bcc"),
Cc = Read(parameters, "CC"), Cc = Read(parameters, "CC"),
Attachments = (IEnumerable<string>)(parameters.ContainsKey("Attachments") ? parameters["Attachments"] : new List<string>()) Attachments = (IEnumerable<string>)(
parameters.ContainsKey("Attachments")
? parameters["Attachments"]
: new List<string>()
)
}; };
if (string.IsNullOrWhiteSpace(emailMessage.Recipients)) { if (string.IsNullOrWhiteSpace(emailMessage.Recipients)) {
@ -62,6 +65,18 @@ namespace Orchard.Email.Services {
return; return;
} }
var mailMessage = CreteMailMessage(parameters, emailMessage);
try {
_smtpClientField.Value.Send(mailMessage);
}
catch (Exception e) {
Logger.Error(e, "Could not send email");
}
}
private MailMessage CreteMailMessage(IDictionary<string, object> parameters, EmailMessage emailMessage) {
// Apply default Body alteration for SmtpChannel. // Apply default Body alteration for SmtpChannel.
var template = _shapeFactory.Create("Template_Smtp_Wrapper", Arguments.From(new { var template = _shapeFactory.Create("Template_Smtp_Wrapper", Arguments.From(new {
Content = new MvcHtmlString(emailMessage.Body) Content = new MvcHtmlString(emailMessage.Body)
@ -75,79 +90,88 @@ namespace Orchard.Email.Services {
if (parameters.ContainsKey("Message")) { if (parameters.ContainsKey("Message")) {
// A full message object is provided by the sender. // A full message object is provided by the sender.
var oldMessage = mailMessage; var oldMessage = mailMessage;
mailMessage = (MailMessage)parameters["Message"]; mailMessage = (MailMessage)parameters["Message"];
if (String.IsNullOrWhiteSpace(mailMessage.Subject)) if (string.IsNullOrWhiteSpace(mailMessage.Subject))
mailMessage.Subject = oldMessage.Subject; mailMessage.Subject = oldMessage.Subject;
if (String.IsNullOrWhiteSpace(mailMessage.Body)) { if (string.IsNullOrWhiteSpace(mailMessage.Body)) {
mailMessage.Body = oldMessage.Body; mailMessage.Body = oldMessage.Body;
mailMessage.IsBodyHtml = oldMessage.IsBodyHtml; mailMessage.IsBodyHtml = oldMessage.IsBodyHtml;
} }
} }
try { foreach (var recipient in ParseRecipients(emailMessage.Recipients)) {
mailMessage.To.Add(new MailAddress(recipient));
}
foreach (var recipient in ParseRecipients(emailMessage.Recipients)) { if (!string.IsNullOrWhiteSpace(emailMessage.Cc)) {
mailMessage.To.Add(new MailAddress(recipient)); foreach (var recipient in ParseRecipients(emailMessage.Cc)) {
mailMessage.CC.Add(new MailAddress(recipient));
} }
}
if (!String.IsNullOrWhiteSpace(emailMessage.Cc)) { if (!string.IsNullOrWhiteSpace(emailMessage.Bcc)) {
foreach (var recipient in ParseRecipients(emailMessage.Cc)) { foreach (var recipient in ParseRecipients(emailMessage.Bcc)) {
mailMessage.CC.Add(new MailAddress(recipient)); mailMessage.Bcc.Add(new MailAddress(recipient));
}
} }
}
if (!String.IsNullOrWhiteSpace(emailMessage.Bcc)) { var senderAddress =
foreach (var recipient in ParseRecipients(emailMessage.Bcc)) { !string.IsNullOrWhiteSpace(emailMessage.FromAddress) ? emailMessage.FromAddress :
mailMessage.Bcc.Add(new MailAddress(recipient)); !string.IsNullOrWhiteSpace(_smtpSettings.FromAddress) ? _smtpSettings.FromAddress :
} // Take 'From' address from site settings or web.config.
} ((SmtpSection)ConfigurationManager.GetSection("system.net/mailSettings/smtp")).From;
if (!String.IsNullOrWhiteSpace(emailMessage.From)) { var senderName = !string.IsNullOrWhiteSpace(emailMessage.FromName)
mailMessage.From = new MailAddress(emailMessage.From); ? emailMessage.FromName
: _smtpSettings.FromName;
var sender = (senderAddress, senderName) switch
{
(string address, string name) => new MailAddress(address, name),
(string address, null) => new MailAddress(address),
_ => throw new InvalidOperationException("No sender email address")
};
mailMessage.From = sender;
var replyTo =
!string.IsNullOrWhiteSpace(emailMessage.ReplyTo) ? ParseRecipients(emailMessage.ReplyTo) :
!string.IsNullOrWhiteSpace(_smtpSettings.ReplyTo) ? new[] { _smtpSettings.ReplyTo } :
Array.Empty<string>();
foreach (var recipient in replyTo) {
mailMessage.ReplyToList.Add(new MailAddress(recipient));
}
foreach (var attachmentPath in emailMessage.Attachments) {
if (File.Exists(attachmentPath)) {
mailMessage.Attachments.Add(new Attachment(attachmentPath));
} }
else { else {
// Take 'From' address from site settings or web.config. throw new FileNotFoundException(T("One or more attachments not found.").Text);
mailMessage.From = !String.IsNullOrWhiteSpace(_smtpSettings.Address)
? new MailAddress(_smtpSettings.Address)
: new MailAddress(((SmtpSection)ConfigurationManager.GetSection("system.net/mailSettings/smtp")).From);
} }
if (!String.IsNullOrWhiteSpace(emailMessage.ReplyTo)) {
foreach (var recipient in ParseRecipients(emailMessage.ReplyTo)) {
mailMessage.ReplyToList.Add(new MailAddress(recipient));
}
}
foreach (var attachmentPath in emailMessage.Attachments) {
if (File.Exists(attachmentPath)) {
mailMessage.Attachments.Add(new Attachment(attachmentPath));
}
else {
throw new FileNotFoundException(T("One or more attachments not found.").Text);
}
}
if (parameters.ContainsKey("NotifyReadEmail")) {
if (parameters["NotifyReadEmail"] is bool) {
if ((bool)(parameters["NotifyReadEmail"])) {
mailMessage.Headers.Add("Disposition-Notification-To", mailMessage.From.ToString());
}
}
}
_smtpClientField.Value.Send(mailMessage);
} }
catch (Exception e) {
Logger.Error(e, "Could not send email"); if (parameters.ContainsKey("NotifyReadEmail")) {
if (parameters["NotifyReadEmail"] is bool) {
if ((bool)(parameters["NotifyReadEmail"])) {
mailMessage.Headers.Add("Disposition-Notification-To", mailMessage.From.ToString());
}
}
} }
if (!string.IsNullOrWhiteSpace(_smtpSettings.ListUnsubscribe)){
mailMessage.Headers.Add("List-Unsubscribe", _smtpSettings.ListUnsubscribe);
}
return mailMessage;
} }
private SmtpClient CreateSmtpClient() { private SmtpClient CreateSmtpClient() {
// If no properties are set in the dashboard, use the web.config value. // If no properties are set in the dashboard, use the web.config value.
if (String.IsNullOrWhiteSpace(_smtpSettings.Host)) { if (string.IsNullOrWhiteSpace(_smtpSettings.Host)) {
return new SmtpClient(); return new SmtpClient();
} }
@ -155,7 +179,7 @@ namespace Orchard.Email.Services {
UseDefaultCredentials = _smtpSettings.RequireCredentials && _smtpSettings.UseDefaultCredentials UseDefaultCredentials = _smtpSettings.RequireCredentials && _smtpSettings.UseDefaultCredentials
}; };
if (!smtpClient.UseDefaultCredentials && !String.IsNullOrWhiteSpace(_smtpSettings.UserName)) { if (!smtpClient.UseDefaultCredentials && !string.IsNullOrWhiteSpace(_smtpSettings.UserName)) {
smtpClient.Credentials = new NetworkCredential(_smtpSettings.UserName, _smtpSettings.Password); smtpClient.Credentials = new NetworkCredential(_smtpSettings.UserName, _smtpSettings.Password);
} }
@ -169,12 +193,10 @@ namespace Orchard.Email.Services {
return smtpClient; return smtpClient;
} }
private string Read(IDictionary<string, object> dictionary, string key) { private string Read(IDictionary<string, object> dictionary, string key) =>
return dictionary.ContainsKey(key) ? dictionary[key] as string : null; dictionary.ContainsKey(key) ? dictionary[key] as string : null;
}
private IEnumerable<string> ParseRecipients(string recipients) { private IEnumerable<string> ParseRecipients(string recipients) =>
return recipients.Split(new[] { ',', ';' }, StringSplitOptions.RemoveEmptyEntries); recipients.Split(new[] { ',', ';' }, StringSplitOptions.RemoveEmptyEntries);
}
} }
} }

View File

@ -3,15 +3,24 @@
@{ @{
var smtpClient = new SmtpClient(); var smtpClient = new SmtpClient();
} }
<fieldset> <fieldset>
<legend>@T("Email")</legend> <legend>@T("Email")</legend>
<div> <div>
<label for="@Html.FieldIdFor(m => m.Address)">@T("Sender email address")</label> <label for="@Html.FieldIdFor(m => m.FromAddress)">@T("Sender email address")</label>
@Html.TextBoxFor(m => m.Address, new { @class = "text medium", placeholder = Model.AddressPlaceholder }) @Html.TextBoxFor(m => m.FromAddress, new { @class = "text medium", placeholder = Model.AddressPlaceholder })
@Html.ValidationMessage("Address", "*") @Html.ValidationMessage("FromAddress", "*")
<span class="hint">@T("The default email address to use as a sender.")</span> <span class="hint">@T("The default email address to use as a sender.")</span>
</div> </div>
<div>
<label for="@Html.FieldIdFor(m => m.FromName)">@T("Sender name")</label>
@Html.TextBoxFor(m => m.FromName, new { @class = "text medium" })
<span class="hint">@T("The default value to use as a sender name.")</span>
</div>
<div>
<label for="@Html.FieldIdFor(m => m.ReplyTo)">@T("Reply to address")</label>
@Html.TextBoxFor(m => m.ReplyTo, new { @class = "text medium" })
<span class="hint">@T("The default email address to use for reply to")</span>
</div>
<div> <div>
<label for="@Html.FieldIdFor(m => m.Host)">@T("Host name")</label> <label for="@Html.FieldIdFor(m => m.Host)">@T("Host name")</label>
@Html.TextBoxFor(m => m.Host, new { placeholder = smtpClient.Host, @class = "text medium" }) @Html.TextBoxFor(m => m.Host, new { placeholder = smtpClient.Host, @class = "text medium" })
@ -35,9 +44,7 @@
<label for="@Html.FieldIdFor(m => m.RequireCredentials)" class="forcheckbox">@T("Require credentials")</label> <label for="@Html.FieldIdFor(m => m.RequireCredentials)" class="forcheckbox">@T("Require credentials")</label>
@Html.ValidationMessage("RequireCredentials", "*") @Html.ValidationMessage("RequireCredentials", "*")
</div> </div>
<div data-controllerid="@Html.FieldIdFor(m => m.RequireCredentials)"> <div data-controllerid="@Html.FieldIdFor(m => m.RequireCredentials)">
<div> <div>
@Html.RadioButtonFor(m => m.UseDefaultCredentials, false, new { id = "customCredentialsOption", name = "UseDefaultCredentials" }) @Html.RadioButtonFor(m => m.UseDefaultCredentials, false, new { id = "customCredentialsOption", name = "UseDefaultCredentials" })
<label for="customCredentialsOption" class="forcheckbox">@T("Specify username/password")</label> <label for="customCredentialsOption" class="forcheckbox">@T("Specify username/password")</label>
@ -65,6 +72,11 @@
</span> </span>
</div> </div>
</div> </div>
<div>
<label for="@Html.FieldIdFor(m => m.ListUnsubscribe)">@T("List-Unsubscribe header")</label>
@Html.TextBoxFor(m => m.ListUnsubscribe, new { @class = "text medium" })
<span class="hint">@T("A mailto:link to unsubscribe a user when clicking unsubscribe option")</span>
</div>
</fieldset> </fieldset>
<fieldset> <fieldset>
<legend>@T("Test those settings:")</legend> <legend>@T("Test those settings:")</legend>
@ -84,7 +96,9 @@
var url = "@Url.Action("TestSettings", "EmailAdmin", new {area = "Orchard.Email"})", var url = "@Url.Action("TestSettings", "EmailAdmin", new {area = "Orchard.Email"})",
error = $("#emailtesterror"), error = $("#emailtesterror"),
info = $("#emailtestinfo"), info = $("#emailtestinfo"),
from = $("#@Html.FieldIdFor(m => m.Address)"), fromAddress = $("#@Html.FieldIdFor(m => m.FromAddress)"),
fromName = $("#@Html.FieldIdFor(m => m.FromName)"),
replyTo = $("#@Html.FieldIdFor(m => m.ReplyTo)"),
host = $("#@Html.FieldIdFor(m => m.Host)"), host = $("#@Html.FieldIdFor(m => m.Host)"),
port = $("#@Html.FieldIdFor(m => m.Port)"), port = $("#@Html.FieldIdFor(m => m.Port)"),
enableSsl = $("#@Html.FieldIdFor(m => m.EnableSsl)"), enableSsl = $("#@Html.FieldIdFor(m => m.EnableSsl)"),
@ -92,11 +106,14 @@
useDefaultCredentials = $("input[name='@Html.NameFor(m => m.UseDefaultCredentials)']"), useDefaultCredentials = $("input[name='@Html.NameFor(m => m.UseDefaultCredentials)']"),
userName = $("#@Html.FieldIdFor(m => m.UserName)"), userName = $("#@Html.FieldIdFor(m => m.UserName)"),
password = $("#@Html.FieldIdFor(m => m.Password)"), password = $("#@Html.FieldIdFor(m => m.Password)"),
listUnsubscribe = $("#@Html.FieldIdFor(m => m.ListUnsubscribe)"),
to = $("#emailtestto"); to = $("#emailtestto");
$("#emailtestsend").click(function () { $("#emailtestsend").click(function () {
$.post(url, { $.post(url, {
from: from.val(), fromAddress: fromAddress.val(),
fromName: fromName.val(),
replyTo: replyTo.val(),
host: host.val(), host: host.val(),
port: port.val(), port: port.val(),
enableSsl: enableSsl.prop("checked"), enableSsl: enableSsl.prop("checked"),
@ -104,6 +121,7 @@
useDefaultCredentials: useDefaultCredentials.filter(':checked').val(), useDefaultCredentials: useDefaultCredentials.filter(':checked').val(),
userName: userName.val(), userName: userName.val(),
password: password.val(), password: password.val(),
listUnsubscribe: listUnsubscribe.val(),
to: to.val(), to: to.val(),
__RequestVerificationToken: to.closest("form").find("input[name=__RequestVerificationToken]").val() __RequestVerificationToken: to.closest("form").find("input[name=__RequestVerificationToken]").val()
}) })

View File

@ -6,4 +6,5 @@
<package id="Microsoft.CodeDom.Providers.DotNetCompilerPlatform" version="2.0.1" targetFramework="net452" /> <package id="Microsoft.CodeDom.Providers.DotNetCompilerPlatform" version="2.0.1" targetFramework="net452" />
<package id="Microsoft.Web.Infrastructure" version="1.0.0.0" targetFramework="net452" /> <package id="Microsoft.Web.Infrastructure" version="1.0.0.0" targetFramework="net452" />
<package id="Newtonsoft.Json" version="12.0.2" targetFramework="net452" /> <package id="Newtonsoft.Json" version="12.0.2" targetFramework="net452" />
<package id="System.ValueTuple" version="4.5.0" targetFramework="net461" />
</packages> </packages>