mirror of
				https://github.com/OrchardCMS/Orchard.git
				synced 2025-10-26 20:16:15 +08:00 
			
		
		
		
	Using MailKit instead of SmtpClient (ORCH-267) (#8707)
* Using MailKit instead of SmtpClient * Removing 2 more references to System.Net.Http that we hopefully don't need at all anymore * Attempting to fix Razor compilation warning about Orchard.Email's reference to System.Net.Http * Improving SmtpSettings.cshtml a bit (port number restrictions, user name box width) * Fixing encription method is not persisted * Adding migration step to migrate from EnableSsl to EncryptionMethod in SmtpSettingsPart * Code styling/simplifications * Using infoset default values instead of Migrations to keep SSL settings when upgrading to MailKit --------- Co-authored-by: Lombiq <github@lombiq.com> Co-authored-by: Benedek Farkas <benedek.farkas@lombiq.com>
This commit is contained in:
		| @@ -133,7 +133,6 @@ | ||||
|       <HintPath>..\..\lib\sqlce\System.Data.SqlServerCe.dll</HintPath> | ||||
|       <Private>True</Private> | ||||
|     </Reference> | ||||
|     <Reference Include="System.Net.Http, Version=4.2.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" /> | ||||
|     <Reference Include="System.Net.Http.Formatting, Version=5.2.7.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"> | ||||
|       <HintPath>..\packages\Microsoft.AspNet.WebApi.Client.5.2.7\lib\net45\System.Net.Http.Formatting.dll</HintPath> | ||||
|     </Reference> | ||||
|   | ||||
| @@ -40,9 +40,9 @@ namespace Orchard.Email.Controllers { | ||||
|                 smtpSettings.Address = testSettings.From; | ||||
|                 smtpSettings.Host = testSettings.Host; | ||||
|                 smtpSettings.Port = testSettings.Port; | ||||
|                 smtpSettings.EnableSsl = testSettings.EnableSsl; | ||||
|                 smtpSettings.AutoSelectEncryption = testSettings.AutoSelectEncryption; | ||||
|                 smtpSettings.EncryptionMethod = testSettings.EncryptionMethod; | ||||
|                 smtpSettings.RequireCredentials = testSettings.RequireCredentials; | ||||
|                 smtpSettings.UseDefaultCredentials = testSettings.UseDefaultCredentials; | ||||
|                 smtpSettings.UserName = testSettings.UserName; | ||||
|                 smtpSettings.Password = testSettings.Password; | ||||
|  | ||||
| @@ -64,10 +64,10 @@ namespace Orchard.Email.Controllers { | ||||
|                     return Json(new { error = fakeLogger.Message }); | ||||
|                 } | ||||
|  | ||||
|                 return Json(new {status = T("Message sent.").Text}); | ||||
|                 return Json(new { status = T("Message sent.").Text }); | ||||
|             } | ||||
|             catch (Exception e) { | ||||
|                 return Json(new {error = e.Message}); | ||||
|                 return Json(new { error = e.Message }); | ||||
|             } | ||||
|             finally { | ||||
|                 var smtpChannelComponent = _smtpChannel as Component; | ||||
| @@ -97,9 +97,9 @@ namespace Orchard.Email.Controllers { | ||||
|             public string ReplyTo { get; set; } | ||||
|             public string Host { get; set; } | ||||
|             public int Port { get; set; } | ||||
|             public bool EnableSsl { get; set; } | ||||
|             public SmtpEncryptionMethod EncryptionMethod { get; set; } | ||||
|             public bool AutoSelectEncryption { get; set; } | ||||
|             public bool RequireCredentials { get; set; } | ||||
|             public bool UseDefaultCredentials { get; set; } | ||||
|             public string UserName { get; set; } | ||||
|             public string Password { get; set; } | ||||
|             public string To { get; set; } | ||||
|   | ||||
| @@ -1,12 +1,12 @@ | ||||
| using System; | ||||
| using System.Configuration; | ||||
| using System.Text; | ||||
| using Orchard.ContentManagement; | ||||
| using Orchard.Email.Models; | ||||
| using Orchard.ContentManagement.Handlers; | ||||
| using Orchard.Email.Models; | ||||
| using Orchard.Localization; | ||||
| using Orchard.Logging; | ||||
| using Orchard.Security; | ||||
| using System.Configuration; | ||||
|  | ||||
| namespace Orchard.Email.Handlers { | ||||
|     public class SmtpSettingsPartHandler : ContentHandler { | ||||
| @@ -24,7 +24,8 @@ namespace Orchard.Email.Handlers { | ||||
|             OnInitializing<SmtpSettingsPart>((context, part) => { | ||||
|                 part.Port = 25; | ||||
|                 part.RequireCredentials = false; | ||||
|                 part.EnableSsl = false; | ||||
|                 part.AutoSelectEncryption = true; | ||||
|                 part.EncryptionMethod = SmtpEncryptionMethod.None; | ||||
|             }); | ||||
|         } | ||||
|  | ||||
|   | ||||
| @@ -2,10 +2,6 @@ | ||||
|  | ||||
| namespace Orchard.Email { | ||||
|     public class Migrations : DataMigrationImpl { | ||||
|  | ||||
|         public int Create() { | ||||
|  | ||||
|             return 1; | ||||
|         } | ||||
|         public int Create() => 1; | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,10 @@ | ||||
| namespace Orchard.Email.Models { | ||||
|     /// <summary> | ||||
|     /// Represents an enumeration for mail encryption methods. | ||||
|     /// </summary> | ||||
|     public enum SmtpEncryptionMethod { | ||||
|         None = 0, | ||||
|         SslTls = 1, | ||||
|         StartTls = 2 | ||||
|     } | ||||
| } | ||||
| @@ -1,7 +1,7 @@ | ||||
| using System.Configuration; | ||||
| using System; | ||||
| using System.Configuration; | ||||
| using System.Net.Configuration; | ||||
| using Orchard.ContentManagement; | ||||
| using System; | ||||
| using Orchard.ContentManagement.Utilities; | ||||
|  | ||||
| namespace Orchard.Email.Models { | ||||
| @@ -31,9 +31,23 @@ namespace Orchard.Email.Models { | ||||
|             set { this.Store(x => x.Port, value); } | ||||
|         } | ||||
|  | ||||
|         public bool EnableSsl { | ||||
|             get { return this.Retrieve(x => x.EnableSsl); } | ||||
|             set { this.Store(x => x.EnableSsl, value); } | ||||
|         [Obsolete($"Use {nameof(AutoSelectEncryption)} and/or {nameof(EncryptionMethod)} instead.")] | ||||
|         public bool EnableSsl => this.Retrieve(x => x.EnableSsl); | ||||
|  | ||||
|         public SmtpEncryptionMethod EncryptionMethod { | ||||
| #pragma warning disable CS0618 // Type or member is obsolete | ||||
|             // Reading EnableSsl is necessary to keep the correct settings during the upgrade to MailKit. | ||||
|             get { return this.Retrieve(x => x.EncryptionMethod, EnableSsl ? SmtpEncryptionMethod.SslTls : SmtpEncryptionMethod.None); } | ||||
| #pragma warning restore CS0618 // Type or member is obsolete | ||||
|             set { this.Store(x => x.EncryptionMethod, value); } | ||||
|         } | ||||
|  | ||||
|         public bool AutoSelectEncryption { | ||||
| #pragma warning disable CS0618 // Type or member is obsolete | ||||
|             // Reading EnableSsl is necessary to keep the correct settings during the upgrade to MailKit. | ||||
|             get { return this.Retrieve(x => x.AutoSelectEncryption, !EnableSsl); } | ||||
| #pragma warning restore CS0618 // Type or member is obsolete | ||||
|             set { this.Store(x => x.AutoSelectEncryption, value); } | ||||
|         } | ||||
|  | ||||
|         public bool RequireCredentials { | ||||
| @@ -41,11 +55,6 @@ namespace Orchard.Email.Models { | ||||
|             set { this.Store(x => x.RequireCredentials, value); } | ||||
|         } | ||||
|  | ||||
|         public bool UseDefaultCredentials { | ||||
|             get { return 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); } | ||||
|   | ||||
| @@ -55,6 +55,12 @@ | ||||
|     <Prefer32Bit>false</Prefer32Bit> | ||||
|   </PropertyGroup> | ||||
|   <ItemGroup> | ||||
|     <Reference Include="BouncyCastle.Crypto, Version=1.9.0.0, Culture=neutral, PublicKeyToken=0e99375e54769942, processorArchitecture=MSIL"> | ||||
|       <HintPath>..\..\..\packages\Portable.BouncyCastle.1.9.0\lib\net40\BouncyCastle.Crypto.dll</HintPath> | ||||
|     </Reference> | ||||
|     <Reference Include="MailKit, Version=3.1.0.0, Culture=neutral, PublicKeyToken=4e064fe7c44a8f1b, processorArchitecture=MSIL"> | ||||
|       <HintPath>..\..\..\packages\MailKit.3.1.1\lib\net48\MailKit.dll</HintPath> | ||||
|     </Reference> | ||||
|     <Reference Include="Microsoft.CodeDom.Providers.DotNetCompilerPlatform, Version=2.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"> | ||||
|       <HintPath>..\..\..\packages\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.2.0.1\lib\net45\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.dll</HintPath> | ||||
|     </Reference> | ||||
| @@ -62,14 +68,23 @@ | ||||
|     <Reference Include="Microsoft.Web.Infrastructure, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"> | ||||
|       <HintPath>..\..\..\packages\Microsoft.Web.Infrastructure.1.0.0.0\lib\net40\Microsoft.Web.Infrastructure.dll</HintPath> | ||||
|     </Reference> | ||||
|     <Reference Include="MimeKit, Version=3.1.0.0, Culture=neutral, PublicKeyToken=bede1c8a46c66814, processorArchitecture=MSIL"> | ||||
|       <HintPath>..\..\..\packages\MimeKit.3.1.1\lib\net48\MimeKit.dll</HintPath> | ||||
|     </Reference> | ||||
|     <Reference Include="Newtonsoft.Json, Version=12.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL"> | ||||
|       <HintPath>..\..\..\packages\Newtonsoft.Json.12.0.3\lib\net45\Newtonsoft.Json.dll</HintPath> | ||||
|     </Reference> | ||||
|     <Reference Include="System" /> | ||||
|     <Reference Include="System.Buffers, Version=4.0.3.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL"> | ||||
|       <HintPath>..\..\..\packages\System.Buffers.4.5.1\lib\net461\System.Buffers.dll</HintPath> | ||||
|     </Reference> | ||||
|     <Reference Include="System.Configuration"> | ||||
|       <Private>False</Private> | ||||
|     </Reference> | ||||
|     <Reference Include="System.Data" /> | ||||
|     <Reference Include="System.Data.DataSetExtensions" /> | ||||
|     <Reference Include="System.Net.Http, Version=4.2.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" /> | ||||
|     <Reference Include="System.Security" /> | ||||
|     <Reference Include="System.Web.ApplicationServices" /> | ||||
|     <Reference Include="System.Web.DynamicData" /> | ||||
|     <Reference Include="System.Web.Entity" /> | ||||
| @@ -104,6 +119,7 @@ | ||||
|     <Compile Include="Drivers\SmtpSettingsPartDriver.cs" /> | ||||
|     <Compile Include="Handlers\SmtpSettingsPartHandler.cs" /> | ||||
|     <Compile Include="Models\EmailMessage.cs" /> | ||||
|     <Compile Include="Models\SmtpEncryptionMethod.cs" /> | ||||
|     <Compile Include="Models\SmtpSettingsPart.cs" /> | ||||
|     <Compile Include="Properties\AssemblyInfo.cs" /> | ||||
|     <Compile Include="Rules\MailActions.cs" /> | ||||
| @@ -218,4 +234,4 @@ | ||||
|     </PropertyGroup> | ||||
|     <Error Condition="!Exists('..\..\..\packages\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.2.0.1\build\net46\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.2.0.1\build\net46\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.props'))" /> | ||||
|   </Target> | ||||
| </Project> | ||||
| </Project> | ||||
| @@ -1,5 +1,4 @@ | ||||
| using System.Collections.Generic; | ||||
| using System.Net.Mail; | ||||
| using System.Web.Mvc; | ||||
| using Orchard.ContentManagement; | ||||
| using Orchard.Email.Models; | ||||
| @@ -24,8 +23,8 @@ namespace Orchard.Email.Services { | ||||
|  | ||||
|             if (smtpSettings == null || !smtpSettings.IsValid()) { | ||||
|                 var urlHelper = new UrlHelper(workContext.HttpContext.Request.RequestContext); | ||||
|                 var url = urlHelper.Action("Email", "Admin", new {Area = "Settings"}); | ||||
|                 yield return new NotifyEntry {Message = T("The <a href=\"{0}\">SMTP settings</a> need to be configured.", url), Type = NotifyType.Warning}; | ||||
|                 var url = urlHelper.Action("Email", "Admin", new { Area = "Settings" }); | ||||
|                 yield return new NotifyEntry { Message = T("The <a href=\"{0}\">SMTP settings</a> need to be configured.", url), Type = NotifyType.Warning }; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|   | ||||
| @@ -1,14 +1,17 @@ | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.Configuration; | ||||
| using System.Net; | ||||
| using System.Linq; | ||||
| using System.Net.Configuration; | ||||
| using System.Net.Mail; | ||||
| using System.Web.Mvc; | ||||
| using MailKit.Security; | ||||
| using MimeKit; | ||||
| using Orchard.ContentManagement; | ||||
| using Orchard.DisplayManagement; | ||||
| using Orchard.Logging; | ||||
| using Orchard.Email.Models; | ||||
| using Orchard.Logging; | ||||
| using SmtpClient = MailKit.Net.Smtp.SmtpClient; | ||||
|  | ||||
| namespace Orchard.Email.Services { | ||||
|     public class SmtpMessageChannel : Component, ISmtpChannel, IDisposable { | ||||
| @@ -64,67 +67,55 @@ namespace Orchard.Email.Services { | ||||
|                 Content = new MvcHtmlString(emailMessage.Body) | ||||
|             })); | ||||
|  | ||||
|             var mailMessage = new MailMessage { | ||||
|             var mailMessage = new MimeMessage { | ||||
|                 Subject = emailMessage.Subject, | ||||
|                 Body = _shapeDisplay.Display(template), | ||||
|                 IsBodyHtml = true | ||||
|             }; | ||||
|             var mailBodyBuilder = new BodyBuilder { | ||||
|                 HtmlBody = _shapeDisplay.Display(template), | ||||
|             }; | ||||
|  | ||||
|             if (parameters.ContainsKey("Message")) { | ||||
|             if (parameters.TryGetValue("Message", out var possiblyMailMessage) && possiblyMailMessage is MailMessage legacyMessage) { | ||||
|                 // A full message object is provided by the sender. | ||||
|                 if (!String.IsNullOrWhiteSpace(legacyMessage.Subject)) { | ||||
|                     mailMessage.Subject = legacyMessage.Subject; | ||||
|                 } | ||||
|  | ||||
|                 var oldMessage = mailMessage; | ||||
|                 mailMessage = (MailMessage)parameters["Message"]; | ||||
|  | ||||
|                 if (String.IsNullOrWhiteSpace(mailMessage.Subject)) | ||||
|                     mailMessage.Subject = oldMessage.Subject; | ||||
|  | ||||
|                 if (String.IsNullOrWhiteSpace(mailMessage.Body)) { | ||||
|                     mailMessage.Body = oldMessage.Body; | ||||
|                     mailMessage.IsBodyHtml = oldMessage.IsBodyHtml; | ||||
|                 if (!String.IsNullOrWhiteSpace(legacyMessage.Body)) { | ||||
|                     mailBodyBuilder.TextBody = legacyMessage.IsBodyHtml ? null : legacyMessage.Body; | ||||
|                     mailBodyBuilder.HtmlBody = legacyMessage.IsBodyHtml ? legacyMessage.Body : null; | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             try { | ||||
|             mailMessage.Body = mailBodyBuilder.ToMessageBody(); | ||||
|  | ||||
|                 foreach (var recipient in ParseRecipients(emailMessage.Recipients)) { | ||||
|                     mailMessage.To.Add(new MailAddress(recipient)); | ||||
|                 } | ||||
|             try { | ||||
|                 mailMessage.To.AddRange(ParseRecipients(emailMessage.Recipients)); | ||||
|  | ||||
|                 if (!String.IsNullOrWhiteSpace(emailMessage.Cc)) { | ||||
|                     foreach (var recipient in ParseRecipients(emailMessage.Cc)) { | ||||
|                         mailMessage.CC.Add(new MailAddress(recipient)); | ||||
|                     } | ||||
|                     mailMessage.Cc.AddRange(ParseRecipients(emailMessage.Cc)); | ||||
|                 } | ||||
|  | ||||
|                 if (!String.IsNullOrWhiteSpace(emailMessage.Bcc)) { | ||||
|                     foreach (var recipient in ParseRecipients(emailMessage.Bcc)) { | ||||
|                         mailMessage.Bcc.Add(new MailAddress(recipient)); | ||||
|                     } | ||||
|                     mailMessage.Bcc.AddRange(ParseRecipients(emailMessage.Bcc)); | ||||
|                 } | ||||
|  | ||||
|                 var fromAddress = default(MailboxAddress); | ||||
|                 if (!String.IsNullOrWhiteSpace(emailMessage.From)) { | ||||
|                     mailMessage.From = new MailAddress(emailMessage.From); | ||||
|                     fromAddress = MailboxAddress.Parse(emailMessage.From); | ||||
|                 } | ||||
|                 else { | ||||
|                     // Take 'From' address from site settings or web.config. | ||||
|                     mailMessage.From = !String.IsNullOrWhiteSpace(_smtpSettings.Address) | ||||
|                         ? new MailAddress(_smtpSettings.Address) | ||||
|                         : new MailAddress(((SmtpSection)ConfigurationManager.GetSection("system.net/mailSettings/smtp")).From); | ||||
|                     fromAddress = !String.IsNullOrWhiteSpace(_smtpSettings.Address) | ||||
|                         ? MailboxAddress.Parse(_smtpSettings.Address) | ||||
|                         : MailboxAddress.Parse(((SmtpSection)ConfigurationManager.GetSection("system.net/mailSettings/smtp")).From); | ||||
|                 } | ||||
|  | ||||
|                 mailMessage.From.Add(fromAddress); | ||||
|  | ||||
|                 if (!String.IsNullOrWhiteSpace(emailMessage.ReplyTo)) { | ||||
|                     foreach (var recipient in ParseRecipients(emailMessage.ReplyTo)) { | ||||
|                         mailMessage.ReplyToList.Add(new MailAddress(recipient)); | ||||
|                     } | ||||
|                 } | ||||
|                 if (parameters.ContainsKey("NotifyReadEmail")) { | ||||
|                     if (parameters["NotifyReadEmail"] is bool) { | ||||
|                         if ((bool)(parameters["NotifyReadEmail"])) { | ||||
|                             mailMessage.Headers.Add("Disposition-Notification-To", mailMessage.From.ToString()); | ||||
|                         } | ||||
|                     } | ||||
|                     mailMessage.ReplyTo.AddRange(ParseRecipients(emailMessage.ReplyTo)); | ||||
|                 } | ||||
|  | ||||
|                 _smtpClientField.Value.Send(mailMessage); | ||||
|             } | ||||
|             catch (Exception e) { | ||||
| @@ -133,26 +124,51 @@ namespace Orchard.Email.Services { | ||||
|         } | ||||
|  | ||||
|         private SmtpClient CreateSmtpClient() { | ||||
|             var smtpConfiguration = new { | ||||
|                 _smtpSettings.Host, | ||||
|                 _smtpSettings.Port, | ||||
|                 _smtpSettings.EncryptionMethod, | ||||
|                 _smtpSettings.AutoSelectEncryption, | ||||
|                 _smtpSettings.RequireCredentials, | ||||
|                 _smtpSettings.UserName, | ||||
|                 _smtpSettings.Password, | ||||
|             }; | ||||
|             // If no properties are set in the dashboard, use the web.config value. | ||||
|             if (String.IsNullOrWhiteSpace(_smtpSettings.Host)) { | ||||
|                 return new SmtpClient();  | ||||
|                 var smtpSection = (SmtpSection)ConfigurationManager.GetSection("system.net/mailSettings/smtp"); | ||||
|                 if (smtpSection.DeliveryMethod != SmtpDeliveryMethod.Network) { | ||||
|                     throw new NotSupportedException($"Only the {SmtpDeliveryMethod.Network} delivery method is supported, but " | ||||
|                         + $"{smtpSection.DeliveryMethod} delivery method is configured. Please check your Web.config."); | ||||
|                 } | ||||
|  | ||||
|                 smtpConfiguration = new { | ||||
|                     smtpSection.Network.Host, | ||||
|                     smtpSection.Network.Port, | ||||
|                     EncryptionMethod = smtpSection.Network.EnableSsl ? SmtpEncryptionMethod.SslTls : SmtpEncryptionMethod.None, | ||||
|                     AutoSelectEncryption = !smtpSection.Network.EnableSsl, | ||||
|                     RequireCredentials = smtpSection.Network.DefaultCredentials || !String.IsNullOrWhiteSpace(smtpSection.Network.UserName), | ||||
|                     smtpSection.Network.UserName, | ||||
|                     smtpSection.Network.Password, | ||||
|                 }; | ||||
|             } | ||||
|  | ||||
|             var smtpClient = new SmtpClient { | ||||
|                 UseDefaultCredentials = _smtpSettings.RequireCredentials && _smtpSettings.UseDefaultCredentials | ||||
|             }; | ||||
|  | ||||
|             if (!smtpClient.UseDefaultCredentials && !String.IsNullOrWhiteSpace(_smtpSettings.UserName)) { | ||||
|                 smtpClient.Credentials = new NetworkCredential(_smtpSettings.UserName, _smtpSettings.Password); | ||||
|             var secureSocketOptions = SecureSocketOptions.Auto; | ||||
|             if (!smtpConfiguration.AutoSelectEncryption) { | ||||
|                 secureSocketOptions = smtpConfiguration.EncryptionMethod switch { | ||||
|                     SmtpEncryptionMethod.None => SecureSocketOptions.None, | ||||
|                     SmtpEncryptionMethod.SslTls => SecureSocketOptions.SslOnConnect, | ||||
|                     SmtpEncryptionMethod.StartTls => SecureSocketOptions.StartTls, | ||||
|                     _ => SecureSocketOptions.None, | ||||
|                 }; | ||||
|             } | ||||
|  | ||||
|             if (_smtpSettings.Host != null) { | ||||
|                 smtpClient.Host = _smtpSettings.Host; | ||||
|             var smtpClient = new SmtpClient(); | ||||
|             smtpClient.Connect(smtpConfiguration.Host, smtpConfiguration.Port, secureSocketOptions); | ||||
|  | ||||
|             if (smtpConfiguration.RequireCredentials) { | ||||
|                 smtpClient.Authenticate(smtpConfiguration.UserName, smtpConfiguration.Password); | ||||
|             } | ||||
|  | ||||
|             smtpClient.Port = _smtpSettings.Port; | ||||
|             smtpClient.EnableSsl = _smtpSettings.EnableSsl; | ||||
|             smtpClient.DeliveryMethod = SmtpDeliveryMethod.Network; | ||||
|             return smtpClient; | ||||
|         } | ||||
|  | ||||
| @@ -160,8 +176,16 @@ namespace Orchard.Email.Services { | ||||
|             return dictionary.ContainsKey(key) ? dictionary[key] as string : null; | ||||
|         } | ||||
|  | ||||
|         private IEnumerable<string> ParseRecipients(string recipients) { | ||||
|             return recipients.Split(new[] {',', ';'}, StringSplitOptions.RemoveEmptyEntries); | ||||
|         private IEnumerable<MailboxAddress> ParseRecipients(string recipients) { | ||||
|             return recipients.Split(new[] { ',', ';' }, StringSplitOptions.RemoveEmptyEntries) | ||||
|                 .SelectMany(address => { | ||||
|                     if (MailboxAddress.TryParse(address, out var mailboxAddress)) { | ||||
|                         return new[] { mailboxAddress }; | ||||
|                     } | ||||
|  | ||||
|                     Logger.Error("Invalid email address: {0}", address); | ||||
|                     return Enumerable.Empty<MailboxAddress>(); | ||||
|                 }); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| } | ||||
|   | ||||
| @@ -1,4 +1,5 @@ | ||||
| @using System.Net.Mail | ||||
| @using Orchard.Email.Models | ||||
| @using System.Net.Mail | ||||
| @model Orchard.Email.Models.SmtpSettingsPart | ||||
| @{ | ||||
|     var smtpClient = new SmtpClient(); | ||||
| @@ -20,15 +21,37 @@ | ||||
|     </div> | ||||
|     <div> | ||||
|         <label for="@Html.FieldIdFor(m => m.Port)">@T("Port number")</label> | ||||
|         @Html.TextBoxFor(m => m.Port, new { placeholder = smtpClient.Port, @class = "text small" }) | ||||
|         @Html.TextBoxFor(m => m.Port, new { type = "number", placeholder = smtpClient.Port, min = 1, max = 65535 }) | ||||
|         @Html.ValidationMessage("Port", "*") | ||||
|         <span class="hint">@T("The SMTP server port, usually 25.")</span> | ||||
|     </div> | ||||
|     <div> | ||||
|         @Html.EditorFor(m => m.EnableSsl) | ||||
|         <label for="@Html.FieldIdFor(m => m.EnableSsl)" class="forcheckbox">@T("Enable SSL communications")</label> | ||||
|         @Html.ValidationMessage("EnableSsl", "*") | ||||
|         <span class="hint">@T("Check if the SMTP server requires SSL communications.")</span> | ||||
|         <label for="@Html.FieldIdFor(m => m.EncryptionMethod)">@T("Encryption method to use")</label> | ||||
|         <select for="@Html.FieldIdFor(m => m.EncryptionMethod)" | ||||
|                 id="@Html.FieldIdFor(m => m.EncryptionMethod)" | ||||
|                 name="@Html.FieldNameFor(m => m.EncryptionMethod)" | ||||
|                 disabled="@Model.AutoSelectEncryption"> | ||||
|             @Html.SelectOption( | ||||
|                 Model.EncryptionMethod, | ||||
|                 SmtpEncryptionMethod.None, | ||||
|                 String.Join(String.Empty, T("None").ToString(), " - ", T("Connect to server using insecure connection.").ToString())) | ||||
|             @Html.SelectOption( | ||||
|                 Model.EncryptionMethod, | ||||
|                 SmtpEncryptionMethod.SslTls, | ||||
|                 String.Join(String.Empty, T("SSL/TLS").ToString(), " - ", T("Connect to server using SSL/TSL secure connection.").ToString())) | ||||
|             @Html.SelectOption( | ||||
|                 Model.EncryptionMethod, | ||||
|                 SmtpEncryptionMethod.StartTls, | ||||
|                 String.Join(String.Empty, T("STARTTLS").ToString(), " - ", T("Connect to server using insecure connection and upgrade to secure using SSL/TLS.").ToString())) | ||||
|         </select> | ||||
|         @Html.ValidationMessage("EncryptionMethod", "*") | ||||
|         <span class="hint">@T("The encryption method used when connecting to mail server.")</span> | ||||
|     </div> | ||||
|     <div> | ||||
|         @Html.EditorFor(m => m.AutoSelectEncryption) | ||||
|         <label for="@Html.FieldIdFor(m => m.AutoSelectEncryption)" class="forcheckbox">@T("Auto Select Encryption method")</label> | ||||
|         @Html.ValidationMessage("AutoSelectEncryption", "*") | ||||
|         <span class="hint">@T("Check to let the system select the encryption method based on port.")</span> | ||||
|     </div> | ||||
|     <div> | ||||
|         @Html.EditorFor(m => m.RequireCredentials) | ||||
| @@ -37,32 +60,17 @@ | ||||
|     </div> | ||||
|  | ||||
|     <div data-controllerid="@Html.FieldIdFor(m => m.RequireCredentials)"> | ||||
|  | ||||
|         <div> | ||||
|             @Html.RadioButtonFor(m => m.UseDefaultCredentials, false, new { id = "customCredentialsOption", name = "UseDefaultCredentials" }) | ||||
|             <label for="customCredentialsOption" class="forcheckbox">@T("Specify username/password")</label> | ||||
|             @Html.ValidationMessage("UseDefaultCredentials", "*") | ||||
|             <label for="@Html.FieldIdFor(m => m.UserName)">@T("User name")</label> | ||||
|             @Html.TextBoxFor(m => m.UserName, new { @class = "text medium" }) | ||||
|             @Html.ValidationMessage("UserName", "*") | ||||
|             <span class="hint">@T("The username for authentication.")</span> | ||||
|         </div> | ||||
|  | ||||
|         <div> | ||||
|             @Html.RadioButtonFor(m => m.UseDefaultCredentials, true, new { id = "defaultCredentialsOptions", name = "UseDefaultCredentials" }) | ||||
|             <label for="defaultCredentialsOptions" class="forcheckbox">@T("Use Windows authentication")</label> | ||||
|             @Html.ValidationMessage("UseDefaultCredentials", "*") | ||||
|             <span class="hint">@T("When this option is selected, the aplication pool or host-process identity is used to authenticate with the mail server. ")</span> | ||||
|         </div> | ||||
|         <div class="options"> | ||||
|             <span data-controllerid="customCredentialsOption"> | ||||
|                 <label for="@Html.FieldIdFor(m => m.UserName)">@T("User name")</label> | ||||
|                 @Html.TextBoxFor(m => m.UserName, new { @class = "text" }) | ||||
|                 @Html.ValidationMessage("UserName", "*") | ||||
|                 <span class="hint">@T("The username for authentication.")</span> | ||||
|             </span> | ||||
|             <span data-controllerid="customCredentialsOption"> | ||||
|                 <label for="@Html.FieldIdFor(m => m.Password)">@T("Password")</label> | ||||
|                 @Html.TextBoxFor(m => m.Password, new { type = "password", @class = "text medium" }) | ||||
|                 @Html.ValidationMessage("Password", "*") | ||||
|                 <span class="hint">@T("The password for authentication.")</span> | ||||
|             </span> | ||||
|             <label for="@Html.FieldIdFor(m => m.Password)">@T("Password")</label> | ||||
|             @Html.TextBoxFor(m => m.Password, new { type = "password", @class = "text medium" }) | ||||
|             @Html.ValidationMessage("Password", "*") | ||||
|             <span class="hint">@T("The password for authentication.")</span> | ||||
|         </div> | ||||
|     </div> | ||||
| </fieldset> | ||||
| @@ -106,9 +114,9 @@ | ||||
|                     from = $("#@Html.FieldIdFor(m => m.Address)"), | ||||
|                     host = $("#@Html.FieldIdFor(m => m.Host)"), | ||||
|                     port = $("#@Html.FieldIdFor(m => m.Port)"), | ||||
|                     enableSsl = $("#@Html.FieldIdFor(m => m.EnableSsl)"), | ||||
|                     encryptionMethod = $("#@Html.FieldIdFor(m => m.EncryptionMethod)"), | ||||
|                     autoSelectEncryption = $("#@Html.FieldIdFor(m => m.AutoSelectEncryption)"), | ||||
|                     requireCredentials = $("#@Html.FieldIdFor(m => m.RequireCredentials)"), | ||||
|                     useDefaultCredentials = $("input[name='@Html.NameFor(m => m.UseDefaultCredentials)']"), | ||||
|                     userName = $("#@Html.FieldIdFor(m => m.UserName)"), | ||||
|                     password = $("#@Html.FieldIdFor(m => m.Password)"), | ||||
|                     to = $("#emailtestto"), | ||||
| @@ -123,9 +131,9 @@ | ||||
|                         from: from.val(), | ||||
|                         host: host.val(), | ||||
|                         port: port.val(), | ||||
|                         enableSsl: enableSsl.prop("checked"), | ||||
|                         encryptionMethod: encryptionMethod.val(), | ||||
|                         autoSelectEncryption: autoSelectEncryption.prop("checked"), | ||||
|                         requireCredentials: requireCredentials.prop("checked"), | ||||
|                         useDefaultCredentials: useDefaultCredentials.filter(':checked').val(), | ||||
|                         userName: userName.val(), | ||||
|                         password: password.val(), | ||||
|                         to: to.val(), | ||||
|   | ||||
| @@ -29,6 +29,7 @@ | ||||
|         <compilation targetFramework="4.8"> | ||||
|             <assemblies> | ||||
|                 <add assembly="System.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089" /> | ||||
|                 <add assembly="System.Net.Http, Version=4.2.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" /> | ||||
|                 <add assembly="System.Web.Abstractions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" /> | ||||
|                 <add assembly="System.Web.Routing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" /> | ||||
|                 <add assembly="System.Data.Linq, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089" /> | ||||
|   | ||||
| @@ -1,9 +1,13 @@ | ||||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <packages> | ||||
|   <package id="MailKit" version="3.1.1" targetFramework="net48" /> | ||||
|   <package id="Microsoft.AspNet.Mvc" version="5.2.7" targetFramework="net48" /> | ||||
|   <package id="Microsoft.AspNet.Razor" version="3.2.7" targetFramework="net48" /> | ||||
|   <package id="Microsoft.AspNet.WebPages" version="3.2.7" targetFramework="net48" /> | ||||
|   <package id="Microsoft.CodeDom.Providers.DotNetCompilerPlatform" version="2.0.1" targetFramework="net48" /> | ||||
|   <package id="Microsoft.Web.Infrastructure" version="1.0.0.0" targetFramework="net48" /> | ||||
|   <package id="MimeKit" version="3.1.1" targetFramework="net48" /> | ||||
|   <package id="Newtonsoft.Json" version="12.0.3" targetFramework="net48" /> | ||||
| </packages> | ||||
|   <package id="Portable.BouncyCastle" version="1.9.0" targetFramework="net48" /> | ||||
|   <package id="System.Buffers" version="4.5.1" targetFramework="net48" /> | ||||
| </packages> | ||||
		Reference in New Issue
	
	Block a user
	 József Horváth
					József Horváth