This places the most recent LoggingEvent in the email body and allows the 
subject to be set dynamically while still including the other messages in the 
buffer as an attachment. I've always wanted something like this and finally 
found time to write a first version. It could be improved to allow the 
attachment to be compressed. I didn't need all the fancy special header, 
footer, ssl, etc. support but its trivial to add that stuff back in:

    public class MailAttachmentSmtpAppender : SmtpAppender
    {
        public PatternLayout SubjectLayout { get; set; }

        protected override void SendBuffer(LoggingEvent[] events)
        {
            try
            {
                using (var stream = new MemoryStream())
                {
                    using (var writer = new StreamWriter(stream))
                    {
                        for (int i = 0; i < events.Length; i++)
                        {
                            RenderLoggingEvent(writer, events[i]);
                        }

                        writer.Flush();
                        stream.Seek(0, SeekOrigin.Begin);

                        SendMail(events[events.Length - 1], stream);
                    }
                }
            }
            catch (Exception e)
            {
                ErrorHandler.Error("Error occurred while sending e-mail 
notification.", e);
            }
        }

        protected virtual void SendMail(LoggingEvent lastEvent, Stream 
renderedEvents)
        {
            SmtpClient smtpClient = new SmtpClient(SmtpHost);

            using (MailMessage mailMessage = new MailMessage())
            {
                mailMessage.To.Add(To);
                mailMessage.From = new MailAddress(From);
                if (SubjectLayout != null)
                {
                    using (var subjectWriter = new StringWriter())
                    {
                        SubjectLayout.Format(subjectWriter, lastEvent);
                        mailMessage.Subject = subjectWriter.ToString();
                    }
                }
                else
                {
                    mailMessage.Subject = Subject;
                }
                mailMessage.Body = RenderLoggingEvent(lastEvent);
                mailMessage.Attachments.Add(new Attachment(renderedEvents, 
"logs.txt", "text/plain"));
                smtpClient.Send(mailMessage);
            }
        }
    }

Reply via email to