Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Log4net html formatted SmtpAppender

I am trying to send me email in HTML format.

    <appender name="SmtpAppender" type="log4net.Appender.SmtpAppender">

  <to value="[email protected]"/>
  <from value="[email protected]"/>
  <subject value="zzzAdmin Logged Event" />
  <smtpHost value="email.zzz.com"/>
  <bufferSize value="1"/>
  <lossy value="false"/>
  <authentication value="Basic" />

I log the error as html formatted text, but the email clients render the HTML as plain text.

How can I tell the SMTPAppender to add an HTML type to the email message so clients will render the message as the HTML that it is.

like image 280
Ian Vink Avatar asked Apr 04 '13 22:04

Ian Vink


2 Answers

Since log4net isn't supporting HTML format in the message body so far, I wrote my own appender:

using System;
using System.Net.Mail;
using log4net.Appender;

namespace log4net.Appender
{
    public class ExtendedSmtpAppender : SmtpAppender
    {
        public bool IsBodyHtml { get; set; }

        protected override void SendEmail(string messageBody)
        {
            // .NET 2.0 has a new API for SMTP email System.Net.Mail
            // This API supports credentials and multiple hosts correctly.
            // The old API is deprecated.

            // Create and configure the smtp client
            SmtpClient smtpClient = new SmtpClient();
            if (!String.IsNullOrEmpty(SmtpHost))
            {
                smtpClient.Host = SmtpHost;
            }
            smtpClient.Port = Port;
            smtpClient.DeliveryMethod = SmtpDeliveryMethod.Network;
            smtpClient.EnableSsl = EnableSsl;

            if (Authentication == SmtpAuthentication.Basic)
            {
                // Perform basic authentication
                smtpClient.Credentials = new System.Net.NetworkCredential(Username, Password);
            }
            else if (Authentication == SmtpAuthentication.Ntlm)
            {
                // Perform integrated authentication (NTLM)
                smtpClient.Credentials = System.Net.CredentialCache.DefaultNetworkCredentials;
            }

            using (MailMessage mailMessage = new MailMessage())
            {
                mailMessage.IsBodyHtml = IsBodyHtml;
                mailMessage.Body = messageBody;
                //mailMessage.BodyEncoding = BodyEncoding;
                mailMessage.From = new MailAddress(From);
                mailMessage.To.Add(To);
                if (!String.IsNullOrEmpty(Cc))
                {
                    mailMessage.CC.Add(Cc);
                }
                if (!String.IsNullOrEmpty(Bcc))
                {
                    mailMessage.Bcc.Add(Bcc);
                }
                if (!String.IsNullOrEmpty(ReplyTo))
                {
                    // .NET 4.0 warning CS0618: 'System.Net.Mail.MailMessage.ReplyTo' is obsolete:
                    // 'ReplyTo is obsoleted for this type.  Please use ReplyToList instead which can accept multiple addresses. http://go.microsoft.com/fwlink/?linkid=14202'
#if !FRAMEWORK_4_0_OR_ABOVE
                    mailMessage.ReplyTo = new MailAddress(ReplyTo);
#else
                    mailMessage.ReplyToList.Add(new MailAddress(m_replyTo));
#endif
                }
                mailMessage.Subject = Subject;
                //mailMessage.SubjectEncoding = m_subjectEncoding;
                mailMessage.Priority = Priority;

                // TODO: Consider using SendAsync to send the message without blocking. This would be a change in
                // behaviour compared to .NET 1.x. We would need a SendCompletedCallback to log errors.
                smtpClient.Send(mailMessage);
            }
        }
    }
}

To use this appender in your log4net config, just replace namespace and class name of your standard SmtpAppender definition and add the isBodyHtml option as follows:

<appender name="SmtpAppender" type="log4net.Appender.ExtendedSmtpAppender">
    ...
    <isBodyHtml value="true" />
    ...
</appender>

The SendEmail method body source is taken from the latest version of the standard log4net's SmtpAppender. I only removed old Framework versions supporting stuff and added this string:

mailMessage.IsBodyHtml = IsBodyHtml;

You can get the latest version of the standard log4net's SmtpAppender here.

UPDATE:
Below is a sample config (inspired with these examples):

<log4net>
  <!-- SmtpExAppender is set to be our ExtendedSmtpAppender -->
  <appender name="SmtpExAppender" type="log4net.Appender.ExtendedSmtpAppender">
    <to value="[email protected]" />
    <from value="[email protected]" />
    <subject value="test logging message" />
    <isBodyHtml value="true" />
    <smtpHost value="SMTPServer.domain.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 [%property{NDC}] - %message%newline%newline%newline" />
    </layout>
  </appender>

  <!-- Set root logger level to DEBUG and its only appender to SmtpExAppender -->
  <root>
    <level value="DEBUG" />
    <appender-ref ref="SmtpExAppender" />
  </root>
</log4net>
like image 151
Alexander Abakumov Avatar answered Nov 04 '22 05:11

Alexander Abakumov


The built in SmtpAppender does not support this so you will need to roll your own appender.

like image 21
sgmoore Avatar answered Nov 04 '22 05:11

sgmoore