mirror of
https://github.com/OrchardCMS/Orchard.git
synced 2025-08-20 09:06:40 +08:00
Add FromName and ReplyTo properties to SmtpSettingsPart (#8420)
This commit is contained in:
parent
70c04a9a5f
commit
1c93e4a501
@ -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; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -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>
|
||||||
|
|||||||
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -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>
|
||||||
|
|||||||
@ -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 {
|
||||||
|
|||||||
@ -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);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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()
|
||||||
})
|
})
|
||||||
|
|||||||
@ -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>
|
||||||
Loading…
Reference in New Issue
Block a user