diff --git a/src/Umbraco.Core/Events/SendEmailEventArgs.cs b/src/Umbraco.Core/Events/SendEmailEventArgs.cs
index cfe43233cd..7ee9469b57 100644
--- a/src/Umbraco.Core/Events/SendEmailEventArgs.cs
+++ b/src/Umbraco.Core/Events/SendEmailEventArgs.cs
@@ -1,13 +1,13 @@
using System;
-using System.Net.Mail;
+using Umbraco.Core.Models;
namespace Umbraco.Core.Events
{
public class SendEmailEventArgs : EventArgs
{
- public MailMessage Message { get; private set; }
+ public EmailMessage Message { get; }
- public SendEmailEventArgs(MailMessage message)
+ public SendEmailEventArgs(EmailMessage message)
{
Message = message;
}
diff --git a/src/Umbraco.Core/IEmailSender.cs b/src/Umbraco.Core/IEmailSender.cs
index 748b8e6b0a..aab944e04d 100644
--- a/src/Umbraco.Core/IEmailSender.cs
+++ b/src/Umbraco.Core/IEmailSender.cs
@@ -1,5 +1,5 @@
-using System.Net.Mail;
-using System.Threading.Tasks;
+using System.Threading.Tasks;
+using Umbraco.Core.Models;
namespace Umbraco.Core
{
@@ -8,7 +8,6 @@ namespace Umbraco.Core
///
public interface IEmailSender
{
- // TODO: This would be better if MailMessage was our own abstraction!
- Task SendAsync(MailMessage message);
+ Task SendAsync(EmailMessage message);
}
}
diff --git a/src/Umbraco.Core/Models/EmailMessage.cs b/src/Umbraco.Core/Models/EmailMessage.cs
new file mode 100644
index 0000000000..e036f157d6
--- /dev/null
+++ b/src/Umbraco.Core/Models/EmailMessage.cs
@@ -0,0 +1,26 @@
+using System;
+
+namespace Umbraco.Core.Models
+{
+ public class EmailMessage
+ {
+ public string From { get; }
+ public string To { get; }
+ public string Subject { get; }
+ public string Body { get; }
+ public bool IsBodyHtml { get; set; } = false;
+
+ public EmailMessage(string from, string to, string subject, string body)
+ {
+ if (string.IsNullOrEmpty(from)) throw new ArgumentException("Value cannot be null or empty.", nameof(from));
+ if (string.IsNullOrEmpty(to)) throw new ArgumentException("Value cannot be null or empty.", nameof(to));
+ if (string.IsNullOrEmpty(subject)) throw new ArgumentException("Value cannot be null or empty.", nameof(subject));
+ if (string.IsNullOrEmpty(body)) throw new ArgumentException("Value cannot be null or empty.", nameof(body));
+
+ From = from;
+ To = to;
+ Subject = subject;
+ Body = body;
+ }
+ }
+}
diff --git a/src/Umbraco.Infrastructure/HealthCheck/NotificationMethods/EmailNotificationMethod.cs b/src/Umbraco.Infrastructure/HealthCheck/NotificationMethods/EmailNotificationMethod.cs
index d925ce14bf..65fa7e3d47 100644
--- a/src/Umbraco.Infrastructure/HealthCheck/NotificationMethods/EmailNotificationMethod.cs
+++ b/src/Umbraco.Infrastructure/HealthCheck/NotificationMethods/EmailNotificationMethod.cs
@@ -1,12 +1,11 @@
using System;
-using System.Net.Mail;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Options;
using Umbraco.Core;
-using Umbraco.Core.Configuration;
using Umbraco.Core.Configuration.Models;
using Umbraco.Core.HealthCheck;
+using Umbraco.Core.Models;
using Umbraco.Core.Services;
using Umbraco.Infrastructure.HealthCheck;
@@ -72,20 +71,18 @@ namespace Umbraco.Web.HealthCheck.NotificationMethods
var subject = _textService.Localize("healthcheck/scheduledHealthCheckEmailSubject", new[] { host.ToString() });
var mailSender = new EmailSender(Options.Create(_globalSettings));
- using (var mailMessage = CreateMailMessage(subject, message))
- {
- await mailSender.SendAsync(mailMessage);
- }
+ var mailMessage = CreateMailMessage(subject, message);
+ await mailSender.SendAsync(mailMessage);
}
- private MailMessage CreateMailMessage(string subject, string message)
+ private EmailMessage CreateMailMessage(string subject, string message)
{
var to = _contentSettings.Notifications.Email;
if (string.IsNullOrWhiteSpace(subject))
subject = "Umbraco Health Check Status";
- return new MailMessage(to, RecipientEmail, subject, message)
+ return new EmailMessage(to, RecipientEmail, subject, message)
{
IsBodyHtml = message.IsNullOrWhiteSpace() == false && message.Contains("<") && message.Contains("")
};
diff --git a/src/Umbraco.Infrastructure/Services/Implement/NotificationService.cs b/src/Umbraco.Infrastructure/Services/Implement/NotificationService.cs
index 7964cd273e..e7adf79e08 100644
--- a/src/Umbraco.Infrastructure/Services/Implement/NotificationService.cs
+++ b/src/Umbraco.Infrastructure/Services/Implement/NotificationService.cs
@@ -3,7 +3,6 @@ using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
-using System.Net.Mail;
using System.Text;
using System.Threading;
using Microsoft.Extensions.Options;
@@ -179,7 +178,7 @@ namespace Umbraco.Core.Services.Implement
///
public IEnumerable FilterUserNotificationsByPath(IEnumerable userNotifications, string path)
{
- var pathParts = path.Split(new[] {','}, StringSplitOptions.RemoveEmptyEntries);
+ var pathParts = path.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
return userNotifications.Where(r => pathParts.InvariantContains(r.EntityId.ToString(CultureInfo.InvariantCulture))).ToList();
}
@@ -406,22 +405,19 @@ namespace Umbraco.Core.Services.Implement
summary.ToString());
var fromMail = _contentSettings.Notifications.Email ?? _globalSettings.Smtp.From;
- // create the mail message
- var mail = new MailMessage(fromMail, fromMail);
- // populate the message
+ var subject = createSubject((mailingUser, subjectVars));
+ var body = "";
+ var isBodyHtml = false;
-
- mail.Subject = createSubject((mailingUser, subjectVars));
if (_contentSettings.Notifications.DisableHtmlEmail)
{
- mail.IsBodyHtml = false;
- mail.Body = createBody((user: mailingUser, body: bodyVars, false));
+ body = createBody((user: mailingUser, body: bodyVars, false));
}
else
{
- mail.IsBodyHtml = true;
- mail.Body =
+ isBodyHtml = true;
+ body =
string.Concat(@"
@@ -430,14 +426,17 @@ namespace Umbraco.Core.Services.Implement
// nh, issue 30724. Due to hardcoded http strings in resource files, we need to check for https replacements here
// adding the server name to make sure we don't replace external links
- if (_globalSettings.UseHttps && string.IsNullOrEmpty(mail.Body) == false)
+ if (_globalSettings.UseHttps && string.IsNullOrEmpty(body) == false)
{
- string serverName = siteUri.Host;
- mail.Body = mail.Body.Replace(
- string.Format("http://{0}", serverName),
- string.Format("https://{0}", serverName));
+ var serverName = siteUri.Host;
+ body = body.Replace(
+ $"http://{serverName}",
+ $"https://{serverName}");
}
+ // create the mail message
+ var mail = new EmailMessage(fromMail, mailingUser.Email, subject, body) {IsBodyHtml = isBodyHtml};
+
return new NotificationRequest(mail, actionName, mailingUser.Name, mailingUser.Email);
}
@@ -488,7 +487,7 @@ namespace Umbraco.Core.Services.Implement
private class NotificationRequest
{
- public NotificationRequest(MailMessage mail, string action, string userName, string email)
+ public NotificationRequest(EmailMessage mail, string action, string userName, string email)
{
Mail = mail;
Action = action;
@@ -496,13 +495,13 @@ namespace Umbraco.Core.Services.Implement
Email = email;
}
- public MailMessage Mail { get; private set; }
+ public EmailMessage Mail { get; }
- public string Action { get; private set; }
+ public string Action { get; }
- public string UserName { get; private set; }
+ public string UserName { get; }
- public string Email { get; private set; }
+ public string Email { get; }
}
private void Process(BlockingCollection notificationRequests)
@@ -524,10 +523,6 @@ namespace Umbraco.Core.Services.Implement
{
_logger.LogError(ex, "An error occurred sending notification");
}
- finally
- {
- request.Mail.Dispose();
- }
}
lock (Locker)
{
diff --git a/src/Umbraco.Infrastructure/Users/EmailSender.cs b/src/Umbraco.Infrastructure/Users/EmailSender.cs
index c45a9af0d3..a58426d82f 100644
--- a/src/Umbraco.Infrastructure/Users/EmailSender.cs
+++ b/src/Umbraco.Infrastructure/Users/EmailSender.cs
@@ -1,13 +1,12 @@
using System;
-using System.Linq;
using System.Net.Mail;
using System.Threading.Tasks;
using Microsoft.Extensions.Options;
using MimeKit;
using MimeKit.Text;
-using Umbraco.Core.Configuration;
using Umbraco.Core.Configuration.Models;
using Umbraco.Core.Events;
+using Umbraco.Core.Models;
using SmtpClient = MailKit.Net.Smtp.SmtpClient;
namespace Umbraco.Core
@@ -40,7 +39,7 @@ namespace Umbraco.Core
/// Sends the message non-async
///
///
- public void Send(MailMessage message)
+ public void Send(EmailMessage message)
{
if (_smtpConfigured.Value == false && _enableEvents)
{
@@ -70,7 +69,7 @@ namespace Umbraco.Core
///
///
///
- public async Task SendAsync(MailMessage message)
+ public async Task SendAsync(EmailMessage message)
{
if (_smtpConfigured.Value == false && _enableEvents)
{
@@ -130,9 +129,9 @@ namespace Umbraco.Core
if (handler != null) handler(null, e);
}
- private MimeMessage ConstructEmailMessage(MailMessage mailMessage)
+ private MimeMessage ConstructEmailMessage(EmailMessage mailMessage)
{
- var fromEmail = mailMessage.From?.Address;
+ var fromEmail = mailMessage.From;
if(string.IsNullOrEmpty(fromEmail))
fromEmail = _globalSettings.Smtp.From;
@@ -142,7 +141,7 @@ namespace Umbraco.Core
From = { new MailboxAddress(fromEmail)},
Body = new TextPart(mailMessage.IsBodyHtml ? TextFormat.Html : TextFormat.Plain) { Text = mailMessage.Body }
};
- messageToSend.To.AddRange(mailMessage.To.Select(x=>new MailboxAddress(x.Address)));
+ messageToSend.To.Add(new MailboxAddress(mailMessage.To));
return messageToSend;
}
diff --git a/src/Umbraco.Web.BackOffice/Controllers/AuthenticationController.cs b/src/Umbraco.Web.BackOffice/Controllers/AuthenticationController.cs
index a6b350da91..89840a8696 100644
--- a/src/Umbraco.Web.BackOffice/Controllers/AuthenticationController.cs
+++ b/src/Umbraco.Web.BackOffice/Controllers/AuthenticationController.cs
@@ -2,7 +2,6 @@
using System.Collections.Generic;
using System.Linq;
using System.Net;
-using System.Net.Mail;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Routing;
using Microsoft.AspNetCore.Authentication;
@@ -310,6 +309,7 @@ namespace Umbraco.Web.BackOffice.Controllers
var user = _userService.GetByEmail(model.Email);
if (user != null)
{
+ var from = _globalSettings.Smtp.From;
var code = await _userManager.GeneratePasswordResetTokenAsync(identityUser);
var callbackUrl = ConstructCallbackUrl(identityUser.Id, code);
@@ -322,12 +322,9 @@ namespace Umbraco.Web.BackOffice.Controllers
// Ensure the culture of the found user is used for the email!
UmbracoUserExtensions.GetUserCulture(identityUser.Culture, _textService, _globalSettings));
- var mailMessage = new MailMessage()
+ var mailMessage = new EmailMessage(from, user.Email, subject, message)
{
- Subject = subject,
- Body = message,
- IsBodyHtml = true,
- To = { user.Email }
+ IsBodyHtml = true
};
await _emailSender.SendAsync(mailMessage);
diff --git a/src/Umbraco.Web.BackOffice/Controllers/UsersController.cs b/src/Umbraco.Web.BackOffice/Controllers/UsersController.cs
index d45951a3df..0776e757e3 100644
--- a/src/Umbraco.Web.BackOffice/Controllers/UsersController.cs
+++ b/src/Umbraco.Web.BackOffice/Controllers/UsersController.cs
@@ -3,7 +3,6 @@ using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
-using System.Net.Mail;
using System.Runtime.Serialization;
using System.Security.Cryptography;
using System.Threading.Tasks;
@@ -543,12 +542,9 @@ namespace Umbraco.Web.BackOffice.Controllers
UmbracoUserExtensions.GetUserCulture(to.Language, _localizedTextService, _globalSettings),
new[] { userDisplay.Name, from, message, inviteUri.ToString(), fromEmail });
- var mailMessage = new MailMessage()
+ var mailMessage = new EmailMessage(fromEmail, to.Email, emailSubject, emailBody)
{
- Subject = emailSubject,
- Body = emailBody,
- IsBodyHtml = true,
- To = { to.Email}
+ IsBodyHtml = true
};
await _emailSender.SendAsync(mailMessage);
diff --git a/src/Umbraco.Web/Editors/AuthenticationController.cs b/src/Umbraco.Web/Editors/AuthenticationController.cs
index 5265dc13cb..1ca85d919d 100644
--- a/src/Umbraco.Web/Editors/AuthenticationController.cs
+++ b/src/Umbraco.Web/Editors/AuthenticationController.cs
@@ -3,7 +3,6 @@ using System.Linq;
using System.Net;
using System.Net.Http;
using System.Collections.Generic;
-using System.Net.Mail;
using System.Security.Principal;
using System.Threading.Tasks;
using System.Web;