Skip to content

Commit

Permalink
Email.Azure: Deconstructing email addresses that include a display na…
Browse files Browse the repository at this point in the history
…me (Lombiq Technologies: OCORE-204) (#16889)
  • Loading branch information
BenedekFarkas authored Oct 28, 2024
1 parent b021e6a commit 5447c54
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 22 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,9 @@ public class AzureEmailProvider : AzureEmailProviderBase

public AzureEmailProvider(
IOptions<AzureEmailOptions> options,
IEmailAddressValidator emailAddressValidator,
ILogger<AzureEmailProvider> logger,
IStringLocalizer<AzureEmailProvider> stringLocalizer)
: base(options.Value, emailAddressValidator, logger, stringLocalizer)
: base(options.Value, logger, stringLocalizer)
{
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using System.Net.Mail;
using Azure;
using Azure.Communication.Email;
using Microsoft.Extensions.Localization;
Expand Down Expand Up @@ -78,7 +79,6 @@ public abstract class AzureEmailProviderBase : IEmailProvider
};

private readonly AzureEmailOptions _providerOptions;
private readonly IEmailAddressValidator _emailAddressValidator;
private readonly ILogger _logger;

private EmailClient _emailClient;
Expand All @@ -87,12 +87,10 @@ public abstract class AzureEmailProviderBase : IEmailProvider

public AzureEmailProviderBase(
AzureEmailOptions options,
IEmailAddressValidator emailAddressValidator,
ILogger logger,
IStringLocalizer stringLocalizer)
{
_providerOptions = options;
_emailAddressValidator = emailAddressValidator;
_logger = logger;
S = stringLocalizer;
}
Expand All @@ -116,12 +114,15 @@ public virtual async Task<EmailResult> SendAsync(MailMessage message)

if (!string.IsNullOrWhiteSpace(senderAddress))
{
if (!_emailAddressValidator.Validate(senderAddress))
if (MailAddress.TryCreate(senderAddress, out var senderMailAddress))
{
// For compatibility with configuration for other providers that allow a sender with display name.
message.From = senderMailAddress.Address;
}
else
{
return EmailResult.FailedResult(nameof(message.From), S["Invalid email address for the sender: '{0}'.", senderAddress]);
}

message.From = senderAddress;
}

var errors = new Dictionary<string, IList<LocalizedString>>();
Expand Down Expand Up @@ -149,7 +150,7 @@ public virtual async Task<EmailResult> SendAsync(MailMessage message)
{
_logger.LogError(ex, "An error occurred while sending an email using the Azure Email Provider.");

// IMPORTANT, do not expose ex.Message as it could contain the connection string in a raw format!
// IMPORTANT: Do not expose ex.Message as it could contain the connection string in a raw format!
return EmailResult.FailedResult(string.Empty, S["An error occurred while sending an email."]);
}
}
Expand All @@ -158,22 +159,43 @@ private EmailMessage FromMailMessage(MailMessage message, Dictionary<string, ILi
{
var recipients = message.GetRecipients();

List<EmailAddress> toRecipients = null;
if (recipients.To.Count > 0)
var toRecipients = new List<EmailAddress>();
foreach (var toRecipient in recipients.To)
{
toRecipients = [.. recipients.To.Select(r => new EmailAddress(r))];
if (MailAddress.TryCreate(toRecipient, out var toMailAddress))
{
toRecipients.Add(ConvertMailAddressToAzureEmailAddress(toMailAddress));
}
else
{
errors[nameof(recipients.To)].Add(S["Invalid email address for the 'To' recipient: '{0}'.", toRecipient]);
}
}

List<EmailAddress> ccRecipients = null;
if (recipients.Cc.Count > 0)
var ccRecipients = new List<EmailAddress>();
foreach (var ccRecipient in recipients.Cc)
{
ccRecipients = [.. recipients.Cc.Select(r => new EmailAddress(r))];
if (MailAddress.TryCreate(ccRecipient, out var ccMailAddress))
{
ccRecipients.Add(ConvertMailAddressToAzureEmailAddress(ccMailAddress));
}
else
{
errors[nameof(recipients.Cc)].Add(S["Invalid email address for the 'CC' recipient: '{0}'.", ccRecipient]);
}
}

List<EmailAddress> bccRecipients = null;
if (recipients.Bcc.Count > 0)
var bccRecipients = new List<EmailAddress>();
foreach (var bccRecipient in recipients.Bcc)
{
bccRecipients = [.. recipients.Bcc.Select(r => new EmailAddress(r))];
if (MailAddress.TryCreate(bccRecipient, out var bccMailAddress))
{
bccRecipients.Add(ConvertMailAddressToAzureEmailAddress(bccMailAddress));
}
else
{
errors[nameof(recipients.Bcc)].Add(S["Invalid email address for the 'BCC' recipient: '{0}'.", bccRecipient]);
}
}

var content = new EmailContent(message.Subject);
Expand All @@ -191,9 +213,16 @@ private EmailMessage FromMailMessage(MailMessage message, Dictionary<string, ILi
new EmailRecipients(toRecipients, ccRecipients, bccRecipients),
content);

foreach (var address in message.GetReplyTo())
foreach (var replyTo in message.GetReplyTo())
{
emailMessage.ReplyTo.Add(new EmailAddress(address));
if (MailAddress.TryCreate(replyTo, out var replyToMailAddress))
{
emailMessage.ReplyTo.Add(ConvertMailAddressToAzureEmailAddress(replyToMailAddress));
}
else
{
errors[nameof(emailMessage.ReplyTo)].Add(S["Invalid email address to reply to: '{0}'.", replyTo]);
}
}

foreach (var attachment in message.Attachments)
Expand Down Expand Up @@ -224,4 +253,7 @@ private EmailMessage FromMailMessage(MailMessage message, Dictionary<string, ILi

return emailMessage;
}

private static EmailAddress ConvertMailAddressToAzureEmailAddress(MailAddress mailAddress) =>
new EmailAddress(mailAddress.Address, mailAddress.DisplayName);
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,9 @@ public class DefaultAzureEmailProvider : AzureEmailProviderBase

public DefaultAzureEmailProvider(
IOptions<DefaultAzureEmailOptions> options,
IEmailAddressValidator emailAddressValidator,
ILogger<DefaultAzureEmailProvider> logger,
IStringLocalizer<DefaultAzureEmailProvider> stringLocalizer)
: base(options.Value, emailAddressValidator, logger, stringLocalizer)
: base(options.Value, logger, stringLocalizer)
{
}

Expand Down

0 comments on commit 5447c54

Please sign in to comment.