Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 47 additions & 7 deletions src/NLog.MailKit/MailTarget.cs
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@
/// </example>
[Target("Mail")]
[Target("MailKit")]
public class MailTarget : TargetWithLayoutHeaderAndFooter

Check warning on line 83 in src/NLog.MailKit/MailTarget.cs

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Split this class into smaller and more specialized ones to reduce its dependencies on other types from 31 to the maximum authorized 30 or less.

See more on https://sonarcloud.io/project/issues?id=nlog.mailkit&issues=AZ0CB9r6oIU5Q4rIju3c&open=AZ0CB9r6oIU5Q4rIju3c&pullRequest=241
{
private static readonly Encoding DefaultEncoding = System.Text.Encoding.UTF8;
private const SecureSocketOptions DefaultSecureSocketOption = SecureSocketOptions.StartTlsWhenAvailable;
Expand Down Expand Up @@ -300,10 +300,35 @@
{
InternalLogger.Debug("Init mailtarget with mailkit");
CheckRequiredParameters();

ValidateFixedEmailAddress(From, nameof(From));
ValidateFixedEmailAddress(To, nameof(To));
ValidateFixedEmailAddress(Cc, nameof(Cc));
ValidateFixedEmailAddress(Bcc, nameof(Bcc));
base.InitializeTarget();
}

private void ValidateFixedEmailAddress(Layout? emailAddress, string emailAddressType)
{
if (!ReferenceEquals(emailAddress, Layout.Empty) && emailAddress is SimpleLayout simpleLayout && simpleLayout.IsFixedText)
{
var mailAddressCollection = new InternetAddressList();
try
{
if (!AddAddresses(mailAddressCollection, emailAddress, LogEventInfo.CreateNullEvent(), allowThrow: true))
throw new NLogConfigurationException(string.Format(RequiredPropertyIsEmptyFormat, emailAddressType));
}
catch (NLogConfigurationException)
{
throw;
}
catch (Exception ex)
{
var nlogConfigException = new NLogConfigurationException($"MailTarget: Invalid {emailAddressType}-email-address: {simpleLayout.FixedText}", ex);
throw nlogConfigException;
}
}
}

/// <summary>
/// Create mail and send with SMTP
/// </summary>
Expand Down Expand Up @@ -500,12 +525,12 @@

private void CheckRequiredParameters()
{
if (From is null || ReferenceEquals(From, Layout.Empty))
if (IsEmptyLayout(From))
{
throw new NLogConfigurationException("MailTarget - From address is required");
}

if (To is null || ReferenceEquals(To, Layout.Empty))
if (IsEmptyLayout(To) && IsEmptyLayout(Cc) && IsEmptyLayout(Bcc))
{
throw new NLogConfigurationException("MailTarget - To address is required");
}
Expand All @@ -516,17 +541,22 @@
throw new NLogConfigurationException("MailTarget - SmtpAuthentication NTLM not yet supported");
}

if ((PickupDirectoryLocation is null || ReferenceEquals(PickupDirectoryLocation, Layout.Empty)) && (SmtpServer is null || ReferenceEquals(SmtpServer, Layout.Empty)))
if (IsEmptyLayout(PickupDirectoryLocation) && IsEmptyLayout(SmtpServer))
{
throw new NLogConfigurationException("MailTarget - SmtpServer is required");
}

if (smtpAuthentication == SmtpAuthenticationMode.OAuth2 && (SmtpUserName is null || ReferenceEquals(SmtpUserName, Layout.Empty) || SmtpPassword is null || ReferenceEquals(SmtpPassword, Layout.Empty)))
if (smtpAuthentication == SmtpAuthenticationMode.OAuth2 && (IsEmptyLayout(SmtpUserName) || IsEmptyLayout(SmtpPassword)))
{
throw new NLogConfigurationException("MailTarget - SmtpUserName (OAuth UserName) and SmtpPassword (OAuth AccessToken) is required when SmtpAuthentication = OAuth2");
}
}

private static bool IsEmptyLayout(Layout? layout)
{
return layout is null || ReferenceEquals(layout, Layout.Empty);
}

/// <summary>
/// Create key for grouping. Needed for multiple events in one mail message
/// </summary>
Expand Down Expand Up @@ -653,8 +683,9 @@
/// <param name="mailAddressCollection">Addresses appended to this list</param>
/// <param name="layout">layout with addresses, ; separated</param>
/// <param name="logEvent">event for rendering the <paramref name="layout" /></param>
/// <param name="allowThrow">Abort early when invalid email address format</param>
/// <returns>added a address?</returns>
private bool AddAddresses(InternetAddressList mailAddressCollection, Layout? layout, LogEventInfo logEvent)
private bool AddAddresses(InternetAddressList mailAddressCollection, Layout? layout, LogEventInfo logEvent, bool allowThrow = false)
{
var added = false;
var mailAddresses = RenderLogEvent(layout, logEvent);
Expand All @@ -667,7 +698,16 @@
if (string.IsNullOrEmpty(mailAddress))
continue;

mailAddressCollection.Add(MailboxAddress.Parse(mail));
try
{
mailAddressCollection.Add(MailboxAddress.Parse(mail));
}
catch (Exception ex)
{
InternalLogger.Error(ex, "{0}: Invalid email address: {1}", this, mailAddress);
if (allowThrow || LogManager.ThrowExceptions)
throw;
}
added = true;
}
}
Expand Down
40 changes: 40 additions & 0 deletions test/NLog.MailKit.Tests/UnitTests/MailTargetTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,46 @@ public void MailTarget_WithEmptyTo_ThrowsConfigException()
);
}

[Fact]
public void MailTarget_WithBlankTo_ThrowsConfigException()
{
var mmt = new MailTarget
{
From = "foo@bar.com",
To = " ",
Subject = "Hello from NLog",
SmtpServer = "server1",
SmtpPort = 27,
};

Assert.Throws<NLogConfigurationException>(() =>
new LogFactory().Setup().LoadConfiguration(cfg =>
{
cfg.Configuration.AddRuleForAllLevels(mmt);
})
);
}

[Fact]
public void MailTarget_WithInvalidTo_ThrowsConfigException()
{
var mmt = new MailTarget
{
From = "foo@bar.com",
To = "@",
Subject = "Hello from NLog",
SmtpServer = "server1",
SmtpPort = 27,
};

Assert.Throws<NLogConfigurationException>(() =>
new LogFactory().Setup().LoadConfiguration(cfg =>
{
cfg.Configuration.AddRuleForAllLevels(mmt);
})
);
}

[Fact]
public void MailTarget_WithEmptyFrom_ThrowsConfigException()
{
Expand Down
Loading