Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update dependencies and add overloads to allow custom SMTP Server Ports #48

Closed
wants to merge 4 commits into from
Closed
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
224 changes: 152 additions & 72 deletions src/Serilog.Sinks.Email/LoggerConfigurationEmailExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
using Serilog.Formatting.Display;
using Serilog.Sinks.Email;
using Serilog.Formatting;
using System.ComponentModel;

namespace Serilog
{
Expand All @@ -45,29 +46,27 @@ public static class LoggerConfigurationEmailExtensions
/// <param name="mailSubject">The subject, can be a plain string or a template such as {Timestamp} [{Level}] occurred.</param>
/// <returns>Logger configuration, allowing configuration to continue.</returns>
/// <exception cref="ArgumentNullException">A required parameter is null.</exception>
[Obsolete("New code should not be compiled against this obsolete overload"), EditorBrowsable(EditorBrowsableState.Never)]
public static LoggerConfiguration Email(
this LoggerSinkConfiguration loggerConfiguration,
string fromEmail,
string toEmail,
string outputTemplate = DefaultOutputTemplate,
LogEventLevel restrictedToMinimumLevel = LevelAlias.Minimum,
int batchPostingLimit = EmailSink.DefaultBatchPostingLimit,
TimeSpan? period = null,
IFormatProvider formatProvider = null,
string mailSubject = EmailConnectionInfo.DefaultSubject)
string outputTemplate,
LogEventLevel restrictedToMinimumLevel,
int batchPostingLimit,
TimeSpan? period,
IFormatProvider formatProvider,
string mailSubject)
{
if (loggerConfiguration == null) throw new ArgumentNullException("loggerConfiguration");
if (fromEmail == null) throw new ArgumentNullException("fromEmail");
if (toEmail == null) throw new ArgumentNullException("toEmail");
if (loggerConfiguration == null) throw new ArgumentNullException(nameof(loggerConfiguration));
if (fromEmail == null) throw new ArgumentNullException(nameof(fromEmail));
if (toEmail == null) throw new ArgumentNullException(nameof(toEmail));

var connectionInfo = new EmailConnectionInfo
{
FromEmail = fromEmail,
ToEmail = toEmail,
EmailSubject = mailSubject
};
var eventFormatter = new MessageTemplateTextFormatter(outputTemplate, formatProvider);
var subjectFormatter = new MessageTemplateTextFormatter(mailSubject, formatProvider);

return Email(loggerConfiguration, connectionInfo, outputTemplate, restrictedToMinimumLevel, batchPostingLimit, period, formatProvider);
return BuildSink(loggerConfiguration, fromEmail, toEmail, eventFormatter, subjectFormatter, null, EmailConnectionInfo.DefaultPort,
null, restrictedToMinimumLevel, batchPostingLimit, period);
}

/// <summary>
Expand All @@ -87,33 +86,29 @@ public static LoggerConfiguration Email(
/// <param name="mailSubject">The subject, can be a plain string or a template such as {Timestamp} [{Level}] occurred.</param>
/// <returns>Logger configuration, allowing configuration to continue.</returns>
/// <exception cref="ArgumentNullException">A required parameter is null.</exception>
[Obsolete("New code should not be compiled against this obsolete overload"), EditorBrowsable(EditorBrowsableState.Never)]
public static LoggerConfiguration Email(
this LoggerSinkConfiguration loggerConfiguration,
string fromEmail,
string toEmail,
string mailServer,
ICredentialsByHost networkCredential = null,
string outputTemplate = DefaultOutputTemplate,
LogEventLevel restrictedToMinimumLevel = LevelAlias.Minimum,
int batchPostingLimit = EmailSink.DefaultBatchPostingLimit,
TimeSpan? period = null,
IFormatProvider formatProvider = null,
string mailSubject = EmailConnectionInfo.DefaultSubject)
ICredentialsByHost networkCredential,
string outputTemplate,
LogEventLevel restrictedToMinimumLevel,
int batchPostingLimit,
TimeSpan? period,
IFormatProvider formatProvider,
string mailSubject)
{
if (loggerConfiguration == null) throw new ArgumentNullException("loggerConfiguration");
if (fromEmail == null) throw new ArgumentNullException("fromEmail");
if (toEmail == null) throw new ArgumentNullException("toEmail");
if (loggerConfiguration == null) throw new ArgumentNullException(nameof(loggerConfiguration));
if (fromEmail == null) throw new ArgumentNullException(nameof(fromEmail));
if (toEmail == null) throw new ArgumentNullException(nameof(toEmail));

var connectionInfo = new EmailConnectionInfo
{
FromEmail = fromEmail,
ToEmail = toEmail,
MailServer = mailServer,
NetworkCredentials = networkCredential,
EmailSubject = mailSubject
};
var eventFormatter = new MessageTemplateTextFormatter(outputTemplate, formatProvider);
var subjectFormatter = new MessageTemplateTextFormatter(mailSubject, formatProvider);

return Email(loggerConfiguration, connectionInfo, outputTemplate, restrictedToMinimumLevel, batchPostingLimit, period, formatProvider);
return BuildSink(loggerConfiguration, fromEmail, toEmail, eventFormatter, subjectFormatter, mailServer,
EmailConnectionInfo.DefaultPort, networkCredential, restrictedToMinimumLevel, batchPostingLimit, period);
}

/// <summary>
Expand All @@ -138,28 +133,23 @@ public static LoggerConfiguration Email(
string fromEmail,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this overload missing an [Obsolete]?

IEnumerable<string> toEmails,
string mailServer,
ICredentialsByHost networkCredential = null,
string outputTemplate = DefaultOutputTemplate,
LogEventLevel restrictedToMinimumLevel = LevelAlias.Minimum,
int batchPostingLimit = EmailSink.DefaultBatchPostingLimit,
TimeSpan? period = null,
IFormatProvider formatProvider = null,
string mailSubject = EmailConnectionInfo.DefaultSubject)
ICredentialsByHost networkCredential,
string outputTemplate,
LogEventLevel restrictedToMinimumLevel,
int batchPostingLimit,
TimeSpan? period,
IFormatProvider formatProvider,
string mailSubject)
{
if (loggerConfiguration == null) throw new ArgumentNullException("loggerConfiguration");
if (fromEmail == null) throw new ArgumentNullException("fromEmail");
if (toEmails == null) throw new ArgumentNullException("toEmails");

var connectionInfo = new EmailConnectionInfo
{
FromEmail = fromEmail,
ToEmail = string.Join(";", toEmails),
MailServer = mailServer,
NetworkCredentials = networkCredential,
EmailSubject = mailSubject
};
if (loggerConfiguration == null) throw new ArgumentNullException(nameof(loggerConfiguration));
if (fromEmail == null) throw new ArgumentNullException(nameof(fromEmail));
if (toEmails == null) throw new ArgumentNullException(nameof(toEmails));

var eventFormatter = new MessageTemplateTextFormatter(outputTemplate, formatProvider);
var subjectFormatter = new MessageTemplateTextFormatter(mailSubject, formatProvider);

return Email(loggerConfiguration, connectionInfo, outputTemplate, restrictedToMinimumLevel, batchPostingLimit, period, formatProvider, mailSubject);
return BuildSink(loggerConfiguration, fromEmail, String.Join(";", toEmails), eventFormatter, subjectFormatter, mailServer,
EmailConnectionInfo.DefaultPort, networkCredential, restrictedToMinimumLevel, batchPostingLimit, period);
}

/// <summary>
Expand All @@ -176,6 +166,7 @@ public static LoggerConfiguration Email(
/// <param name="mailSubject">The subject, can be a plain string or a template such as {Timestamp} [{Level}] occurred.</param>
/// <returns>Logger configuration, allowing configuration to continue.</returns>
/// <exception cref="ArgumentNullException">A required parameter is null.</exception>
[Obsolete("New code should not be compiled against this obsolete overload"), EditorBrowsable(EditorBrowsableState.Never)]
public static LoggerConfiguration Email(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this one be obsolete? I think the port is present on EmailConnectionInfo, so no change should be needed here AFAICT.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can't configure EmailConnectionInfo from appsettings.json with Serilog.Settings.Configuration. EmailConfigurationInfo completely defeats the point of having default values for the parameters.

this LoggerSinkConfiguration loggerConfiguration,
EmailConnectionInfo connectionInfo,
Expand All @@ -186,20 +177,19 @@ public static LoggerConfiguration Email(
IFormatProvider formatProvider = null,
string mailSubject = EmailConnectionInfo.DefaultSubject)
{
if (connectionInfo == null) throw new ArgumentNullException("connectionInfo");
if (connectionInfo == null) throw new ArgumentNullException(nameof(connectionInfo));

if (!string.IsNullOrEmpty(connectionInfo.EmailSubject))
{
mailSubject = connectionInfo.EmailSubject;
}

var defaultedPeriod = period ?? EmailSink.DefaultPeriod;
var formatter = new MessageTemplateTextFormatter(outputTemplate, formatProvider);
var subjectLineFormatter = new MessageTemplateTextFormatter(mailSubject, formatProvider);
var eventFormatter = new MessageTemplateTextFormatter(outputTemplate, formatProvider);
var subjectFormatter = new MessageTemplateTextFormatter(mailSubject, formatProvider);

return loggerConfiguration.Sink(
new EmailSink(connectionInfo, batchPostingLimit, defaultedPeriod, formatter, subjectLineFormatter),
restrictedToMinimumLevel);
return BuildSink(loggerConfiguration, connectionInfo.FromEmail, connectionInfo.ToEmail, eventFormatter, subjectFormatter,
connectionInfo.MailServer, connectionInfo.Port, connectionInfo.NetworkCredentials, restrictedToMinimumLevel,
batchPostingLimit, period);
}

/// <summary>
Expand All @@ -214,25 +204,115 @@ public static LoggerConfiguration Email(
/// <param name="mailSubject">The subject, can be a plain string or a template such as {Timestamp} [{Level}] occurred.</param>
/// <returns>Logger configuration, allowing configuration to continue.</returns>
/// <exception cref="ArgumentNullException">A required parameter is null.</exception>
[Obsolete("New code should not be compiled against this obsolete overload"), EditorBrowsable(EditorBrowsableState.Never)]
public static LoggerConfiguration Email(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As per above, this one seems like it should be fine, via EmailConnectionInfo.

this LoggerSinkConfiguration loggerConfiguration,
EmailConnectionInfo connectionInfo,
ITextFormatter textFormatter,
LogEventLevel restrictedToMinimumLevel = LevelAlias.Minimum,
int batchPostingLimit = EmailSink.DefaultBatchPostingLimit,
TimeSpan? period = null,
string mailSubject = EmailConnectionInfo.DefaultSubject)
LogEventLevel restrictedToMinimumLevel,
int batchPostingLimit,
TimeSpan? period,
string mailSubject)
{
if (connectionInfo == null) throw new ArgumentNullException(nameof(connectionInfo));
if (textFormatter == null) throw new ArgumentNullException(nameof(textFormatter));

var subjectFormatter = new MessageTemplateTextFormatter(mailSubject, null);

return BuildSink(loggerConfiguration, connectionInfo.FromEmail, connectionInfo.ToEmail, textFormatter, subjectFormatter,
connectionInfo.MailServer, connectionInfo.Port, connectionInfo.NetworkCredentials, restrictedToMinimumLevel,
batchPostingLimit, period);
}

/// <summary>
/// Adds a sink that sends log events via email.
/// </summary>
/// <param name="loggerConfiguration">The logger configuration.</param>
/// <param name="fromEmail">The email address emails will be sent from</param>
/// <param name="toEmail">The email address emails will be sent to</param>
/// <param name="mailSubject">The subject, can be a plain string or a template such as {Timestamp} [{Level}] occurred.</param>
/// <param name="outputTemplate">A message template describing the format used to write to the sink.
/// the default is "{Timestamp} [{Level}] {Message}{NewLine}{Exception}".</param>
/// <param name="formatProvider">Supplies culture-specific formatting information, or null.</param>
/// <param name="mailServer">The SMTP server; if <i>mailServer</i> == <i>null</i> the settings from App.config or Web.config will be used.</param>
/// <param name="smtpPort">The SMTP server port</param>
/// <param name="networkCredential">The network credentials to use to authenticate with mailServer</param>
/// <param name="minimumLogLevel">The minimum log event level required in order to write an event to the sink.</param>
/// <param name="batchSizeLimit">The maximum number of events to include in a single email.</param>
/// <param name="period">The time to wait between checking for event batches.</param>
/// <returns>Logger configuration, allowing configuration to continue.</returns>
/// <exception cref="ArgumentNullException">A required parameter is null.</exception>
public static LoggerConfiguration Email(
this LoggerSinkConfiguration loggerConfiguration,
string fromEmail,
string toEmail,
string mailSubject = EmailConnectionInfo.DefaultSubject,
string outputTemplate = DefaultOutputTemplate,
string mailServer = null,
int smtpPort = EmailConnectionInfo.DefaultPort,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new parameter needs to be last, so that existing calls with unnamed parameters continue to compile.

ICredentialsByHost networkCredential = null,
LogEventLevel minimumLogLevel = LevelAlias.Minimum,
IFormatProvider formatProvider = null,
int batchSizeLimit = EmailSink.DefaultBatchPostingLimit,
TimeSpan? period = null)
{
if (fromEmail == null) throw new ArgumentNullException(nameof(fromEmail));
if (toEmail == null) throw new ArgumentNullException(nameof(toEmail));

var eventFormatter = new MessageTemplateTextFormatter(outputTemplate, formatProvider);
var subjectFormatter = new MessageTemplateTextFormatter(mailSubject, formatProvider);

return BuildSink(loggerConfiguration, fromEmail, toEmail, eventFormatter, subjectFormatter, mailServer, smtpPort,
networkCredential, minimumLogLevel, batchSizeLimit, period);
}

/// <summary>
/// This method is responsible for adapting all the above overloads to exactly what is required by <see cref="EmailSink"/>.
/// </summary>
/// <param name="loggerConfiguration">The logger configuration.</param>
/// <param name="fromEmail">The email address emails will be sent from</param>
/// <param name="toEmail">The email address emails will be sent to</param>
/// <param name="mailServer">The SMTP server; if <i>mailServer</i> == <i>null</i> the settings from App.config or Web.config will be used.</param>
/// <param name="smtpPort">The SMTP server port</param>
/// <param name="networkCredential">The network credentials to use to authenticate with mailServer</param>
/// <param name="minimumLogLevel">The minimum log event level required in order to write an event to the sink.</param>
/// <param name="batchSizeLimit">The maximum number of events to include in a single email.</param>
/// <param name="period">The time to wait between checking for event batches.</param>
/// <param name="eventFormatter">ITextFormatter implementation to write log entry to email body.</param>
/// <param name="subjectFormatter">ITextFormatter implementation to write log entry to email subject.</param>
/// <returns>Logger configuration, allowing configuration to continue.</returns>
/// <exception cref="ArgumentNullException">A required parameter is null.</exception>
private static LoggerConfiguration BuildSink(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: the codebase avoids explicit private/internal modifiers.

this LoggerSinkConfiguration loggerConfiguration,
string fromEmail,
string toEmail,
ITextFormatter eventFormatter,
ITextFormatter subjectFormatter,
string mailServer,
int smtpPort,
ICredentialsByHost networkCredential,
LogEventLevel minimumLogLevel,
int batchSizeLimit,
TimeSpan? period)
{
if (connectionInfo == null) throw new ArgumentNullException("connectionInfo");
if (textFormatter == null) throw new ArgumentNullException("textFormatter");
if (fromEmail == null) throw new ArgumentNullException(nameof(fromEmail));
if (toEmail == null) throw new ArgumentNullException(nameof(toEmail));
if (eventFormatter == null) throw new ArgumentNullException(nameof(eventFormatter));
if (subjectFormatter == null) throw new ArgumentNullException(nameof(subjectFormatter));

ITextFormatter mailSubjectFormatter = new MessageTemplateTextFormatter(mailSubject, null);
var connectionInfo = new EmailConnectionInfo
{
FromEmail = fromEmail,
ToEmail = toEmail,
MailServer = mailServer,
Port = smtpPort,
NetworkCredentials = networkCredential
};

var defaultedPeriod = period ?? EmailSink.DefaultPeriod;
var defaultPeriod = period ?? EmailSink.DefaultPeriod;

return loggerConfiguration.Sink(
new EmailSink(connectionInfo, batchPostingLimit, defaultedPeriod, textFormatter, mailSubjectFormatter),
restrictedToMinimumLevel);
new EmailSink(connectionInfo, batchSizeLimit, defaultPeriod, eventFormatter, subjectFormatter), minimumLogLevel);
}
}
}
7 changes: 5 additions & 2 deletions src/Serilog.Sinks.Email/Serilog.Sinks.Email.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,11 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Serilog" Version="2.0.0" />
<PackageReference Include="Serilog.Sinks.PeriodicBatching" Version="2.0.0" />
<PackageReference Include="MailKit" Version="2.0.1" />
<PackageReference Include="Serilog" Version="2.6.0" />
<PackageReference Include="Serilog.Sinks.PeriodicBatching" Version="2.1.1" />
<PackageReference Include="System.Linq" Version="4.3.0" />
<PackageReference Include="System.Threading" Version="4.3.0" />
</ItemGroup>

<ItemGroup Condition=" '$(TargetFramework)' == 'net45' ">
Expand Down
2 changes: 1 addition & 1 deletion src/Serilog.Sinks.Email/Sinks/Email/EmailConnectionInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ public class EmailConnectionInfo
/// <summary>
/// The default port used by for SMTP transfer.
/// </summary>
const int DefaultPort = 25;
public const int DefaultPort = 25;

/// <summary>
/// The default subject used for email messages.
Expand Down
Loading