SmtpAppender

The SmtpAppender sends log events via email using the Simple Mail Transfer Protocol (SMTP). This appender is useful for sending email notifications when certain events occur, such as errors or critical failures in your application.

There are two implementations to choose from:

Type Assembly SMTP client

log4net.Ext.Mail.Appender.SmtpAppender (recommended)

log4net.Ext.Mail

MailKit

log4net.Appender.SmtpAppender (deprecated)

log4net

System.Net.Mail.SmtpClient

The built-in log4net.Appender.SmtpAppender is no longer recommended.

It sends mail through System.Net.Mail.SmtpClient, which Microsoft no longer recommends for new development because it does not support many modern protocols. In practice this shows up as connection failures against modern mail servers, most often around SSL/TLS negotiation.

Use the MailKit based SmtpAppender instead. It offers the same configuration options, so migrating usually means changing nothing but the type attribute.

MailKit based SmtpAppender (recommended)

This appender lives in the separate log4net.Ext.Mail package, so that log4net itself does not take on a mail dependency. Add it to your project:

dotnet add package log4net.Ext.Mail

Because the appender is not part of the log4net assembly, the type attribute must be assembly-qualified:

type="log4net.Ext.Mail.Appender.SmtpAppender, log4net.Ext.Mail"

The following example shows how to configure the SmtpAppender to deliver log events via SMTP email. The To, From, Subject and SmtpHost are required parameters. This example shows how to deliver only significant events.

A LevelEvaluator is specified with a threshold of WARN. This means that an email will be sent for each WARN or higher level message that is logged. Each email will also contain up to 512 (BufferSize) previous messages of any level to provide context.

Messages not sent will be discarded.

<appender name="SmtpAppender" type="log4net.Ext.Mail.Appender.SmtpAppender, log4net.Ext.Mail">
  <to value="to@example.com" />
  <from value="from@example.com" />
  <subject value="test logging message" />
  <smtpHost value="smtp.example.com" />
  <bufferSize value="512" />
  <lossy value="true" />
  <evaluator type="log4net.Core.LevelEvaluator">
    <threshold value="WARN"/>
  </evaluator>
  <layout type="log4net.Layout.PatternLayout">
    <conversionPattern value="%newline%date [%thread] %-5level %logger - %message%newline%newline%newline" />
  </layout>
</appender>

This example shows how to configure the SmtpAppender to deliver all messages in emails with 512 bufferSize messages per email.

<appender name="SmtpAppender" type="log4net.Ext.Mail.Appender.SmtpAppender, log4net.Ext.Mail">
  <to value="to@example.com" />
  <from value="from@example.com" />
  <subject value="test logging message" />
  <smtpHost value="smtp.example.com" />
  <bufferSize value="512" />
  <lossy value="false" />
  <layout type="log4net.Layout.PatternLayout">
    <conversionPattern value="%newline%date [%thread] %-5level %logger - %message%newline%newline%newline" />
  </layout>
</appender>

This example shows a more verbose formatting layout for the mail messages.

<appender name="SmtpAppender" type="log4net.Ext.Mail.Appender.SmtpAppender, log4net.Ext.Mail">
  <to value="to@example.com" />
  <from value="from@example.com" />
  <subject value="test logging message" />
  <smtpHost value="smtp.example.com" />
  <bufferSize value="512" />
  <lossy value="false" />
  <evaluator type="log4net.Core.LevelEvaluator,log4net">
    <threshold value="WARN" />
  </evaluator>
  <layout type="log4net.Layout.PatternLayout,log4net">
    <conversionPattern value="%property{log4net:HostName} :: %level :: %message %newlineLogger: %logger%newlineThread: %thread%newlineDate: %date%newline%newline" />
  </layout>
</appender>

This example authenticates against a mail server that requires an encrypted connection on the submission port.

<appender name="SmtpAppender" type="log4net.Ext.Mail.Appender.SmtpAppender, log4net.Ext.Mail">
  <to value="ops@example.com,oncall@example.com" />
  <cc value="team@example.com" />
  <from value="log4net@example.com" />
  <replyTo value="noreply@example.com" />
  <subject value="Errors from the payment service" />
  <smtpHost value="smtp.example.com" />
  <port value="587" />
  <enableSsl value="true" />
  <authentication value="Basic" />
  <username value="log4net@example.com" />
  <password value="secret" />
  <priority value="High" />
  <bufferSize value="512" />
  <lossy value="true" />
  <evaluator type="log4net.Core.LevelEvaluator">
    <threshold value="ERROR"/>
  </evaluator>
  <layout type="log4net.Layout.PatternLayout">
    <conversionPattern value="%newline%date [%thread] %-5level %logger - %message%newline" />
  </layout>
</appender>

Options

Option Description

to

Required. Comma-delimited list of recipient email addresses.

from

Required. The sender’s email address.

subject

Required. The subject line of the email.

smtpHost

Required. The name or address of the SMTP relay server.

cc

Comma-delimited list of addresses to carbon copy.

bcc

Comma-delimited list of addresses to blind carbon copy.

replyTo

The reply-to address.

port

The port the SMTP server listens on. Defaults to 25.

enableSsl

Whether to require transport security. Defaults to false. Shorthand for transportSecurity: true selects Required, false selects None.

transportSecurity

How the connection is secured. One of None (default), Required, ImplicitTls, StartTls or StartTlsWhenAvailable. See Transport security.

authentication

One of None (default), Basic or Ntlm. Basic and Ntlm both require username and password.

username

The user name to authenticate with. Ignored when authentication is None.

password

The password to authenticate with. Ignored when authentication is None.

priority

One of Low, Normal (default) or High, mapped onto the MIME Priority header.

subjectEncoding

The encoding of the subject line, for example utf-8. Defaults to utf-8.

bodyEncoding

The encoding of the message body, for example utf-8. Defaults to utf-8.

bufferSize

How many log events to buffer into one email. See Appenders.

lossy

Whether buffered events may be discarded rather than sent.

evaluator

An ITriggeringEventEvaluator deciding which events trigger a send.

to, cc and bcc also accept semicolons as separators, and quoted display names such as "Doe, John" <john@example.com>.

Transport security

enableSsl covers the usual cases and behaves as it does in the legacy appender: true requires transport security, so connecting fails when the server does not offer it rather than continuing unencrypted.

transportSecurity is the same setting expressed precisely, for servers that need something else. The two properties cannot disagree: whichever is assigned last wins.

Value Description

None

The connection is not encrypted. Equivalent to enableSsl set to false, and the default.

Required

Transport security is required and the mechanism follows the port: implicit TLS on port 465, STARTTLS on every other port. Equivalent to enableSsl set to true.

ImplicitTls

The session is encrypted before the SMTP greeting, whatever the port. Use this for a server expecting implicit TLS on a port other than 465, which Required would try to negotiate with STARTTLS instead.

StartTls

STARTTLS is required, whatever the port.

StartTlsWhenAvailable

STARTTLS is used when the server advertises it, and the connection continues unencrypted when it does not.

StartTlsWhenAvailable is opportunistic. An attacker able to modify the traffic can remove the server’s STARTTLS advertisement, and the session then proceeds in plaintext, exposing the credentials sent by authentication and the log content itself. Only choose it for a network where that is acceptable, and prefer Required.

Differences from the legacy appender

The options above are named exactly as in the legacy appender, but a few behave differently:

  • smtpHost is required. MailKit has no notion of a machine-wide default SMTP server, so there is nothing to fall back on when the option is omitted.

  • authentication set to Ntlm requires username and password. MailKit cannot reuse the Windows logon session of the current thread or process, which the legacy appender did.

  • Semicolon-delimited recipient lists in to, cc and bcc are parsed correctly.

  • transportSecurity has no counterpart in the legacy appender, which offers only enableSsl.

enableSsl keeps its meaning, so a migrated configuration secures the connection exactly as before. If the legacy appender reached your server with enableSsl set to true, so does this one. The new transportSecurity option is only needed for a server that the legacy appender could not reach either, such as one expecting implicit TLS on a port other than 465.

Built-in SmtpAppender (deprecated)

This appender is still shipped and still works, but it is marked [Obsolete], so referencing log4net.Appender.SmtpAppender from code produces a compiler warning. Configuring it from XML keeps working without any warning. See the note at the top of this page.

The built-in appender is configured with the same options, except for the differences listed in Differences from the legacy appender. It needs no assembly-qualified type name, because it is part of the log4net assembly.

<appender name="SmtpAppender" type="log4net.Appender.SmtpAppender">
  <to value="to@example.com" />
  <from value="from@example.com" />
  <subject value="test logging message" />
  <smtpHost value="smtp.example.com" />
  <bufferSize value="512" />
  <lossy value="true" />
  <evaluator type="log4net.Core.LevelEvaluator">
    <threshold value="WARN"/>
  </evaluator>
  <layout type="log4net.Layout.PatternLayout">
    <conversionPattern value="%newline%date [%thread] %-5level %logger - %message%newline%newline%newline" />
  </layout>
</appender>

If you cannot take on the MailKit dependency, SmtpPickupDirAppender is an alternative that avoids an SMTP client altogether by writing the emails to a pickup directory.