Merge pull request #9252 from umbraco/netcore/feature/AB8969-email-message-abstraction

NetCore: Email message abstraction
This commit is contained in:
Bjarke Berg
2020-10-23 14:20:10 +02:00
committed by GitHub
9 changed files with 76 additions and 67 deletions

View File

@@ -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;
}

View File

@@ -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
/// </summary>
public interface IEmailSender
{
// TODO: This would be better if MailMessage was our own abstraction!
Task SendAsync(MailMessage message);
Task SendAsync(EmailMessage message);
}
}

View File

@@ -0,0 +1,35 @@
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; }
public EmailMessage(string from, string to, string subject, string body, bool isBodyHtml)
{
if (from == null) throw new ArgumentNullException(nameof(from));
if (from.Length == 0) throw new ArgumentException("Value cannot be empty.", nameof(from));
if (to == null) throw new ArgumentNullException(nameof(to));
if (to.Length == 0) throw new ArgumentException("Value cannot be empty.", nameof(to));
if (subject == null) throw new ArgumentNullException(nameof(subject));
if (subject.Length == 0) throw new ArgumentException("Value cannot be empty.", nameof(subject));
if (body == null) throw new ArgumentNullException(nameof(body));
if (body.Length == 0) throw new ArgumentException("Value cannot be empty.", nameof(body));
From = from;
To = to;
Subject = subject;
Body = body;
IsBodyHtml = isBodyHtml;
}
}
}

View File

@@ -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,23 +71,19 @@ 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)
{
IsBodyHtml = message.IsNullOrWhiteSpace() == false && message.Contains("<") && message.Contains("</")
};
var isBodyHtml = message.IsNullOrWhiteSpace() == false && message.Contains("<") && message.Contains("</");
return new EmailMessage(to, RecipientEmail, subject, message, isBodyHtml);
}
}
}

View File

@@ -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
/// <returns></returns>
public IEnumerable<Notification> FilterUserNotificationsByPath(IEnumerable<Notification> 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(@"<html><head>
</head>
<body style='font-family: Trebuchet MS, arial, sans-serif; font-color: black;'>
@@ -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);
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<NotificationRequest> notificationRequests)
@@ -524,10 +523,6 @@ namespace Umbraco.Core.Services.Implement
{
_logger.LogError(ex, "An error occurred sending notification");
}
finally
{
request.Mail.Dispose();
}
}
lock (Locker)
{

View File

@@ -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
/// </summary>
/// <param name="message"></param>
public void Send(MailMessage message)
public void Send(EmailMessage message)
{
if (_smtpConfigured.Value == false && _enableEvents)
{
@@ -70,7 +69,7 @@ namespace Umbraco.Core
/// </summary>
/// <param name="message"></param>
/// <returns></returns>
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;
}

View File

@@ -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,13 +322,7 @@ 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()
{
Subject = subject,
Body = message,
IsBodyHtml = true,
To = { user.Email }
};
var mailMessage = new EmailMessage(from, user.Email, subject, message, true);
await _emailSender.SendAsync(mailMessage);

View File

@@ -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,13 +542,7 @@ namespace Umbraco.Web.BackOffice.Controllers
UmbracoUserExtensions.GetUserCulture(to.Language, _localizedTextService, _globalSettings),
new[] { userDisplay.Name, from, message, inviteUri.ToString(), fromEmail });
var mailMessage = new MailMessage()
{
Subject = emailSubject,
Body = emailBody,
IsBodyHtml = true,
To = { to.Email}
};
var mailMessage = new EmailMessage(fromEmail, to.Email, emailSubject, emailBody, true);
await _emailSender.SendAsync(mailMessage);
}

View File

@@ -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;