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);
}
}
}