Index: core/src/test/java/org/apache/logging/log4j/core/appender/SMTPAppenderTest.java
===================================================================
--- core/src/test/java/org/apache/logging/log4j/core/appender/SMTPAppenderTest.java	(revision 0)
+++ core/src/test/java/org/apache/logging/log4j/core/appender/SMTPAppenderTest.java	(revision 0)
@@ -0,0 +1,162 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *	  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.log4j.core.appender;
+
+import javax.mail.Address;
+import javax.mail.Message;
+import javax.mail.MessagingException;
+import javax.mail.internet.InternetAddress;
+
+import org.apache.logging.log4j.Level;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.core.Logger;
+import org.apache.logging.log4j.core.LoggerContext;
+import org.junit.Test;
+
+import com.dumbster.smtp.SimpleSmtpServer;
+import com.dumbster.smtp.SmtpMessage;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertArrayEquals;
+
+public class SMTPAppenderTest {
+
+    @Test
+    public void testMessageFactorySetFrom() throws MessagingException {
+        final SMTPAppender.MimeMessageBuilder builder = new SMTPAppender.MimeMessageBuilder(null);
+        final String address = "testing@example.com";
+
+        assertNull(builder.getMimeMessage().getFrom());
+
+        builder.setFrom(null);
+        assertArrayEquals(new Address[] { InternetAddress.getLocalAddress(null) }, builder.getMimeMessage().getFrom());
+
+        builder.setFrom(address);
+        assertArrayEquals(new Address[] { new InternetAddress(address) }, builder.getMimeMessage().getFrom());
+    }
+
+    @Test
+    public void testMessageFactorySetReplyTo() throws MessagingException {
+        final SMTPAppender.MimeMessageBuilder builder = new SMTPAppender.MimeMessageBuilder(null);
+        final String addresses = "testing1@example.com,testing2@example.com";
+
+        assertNull(builder.getMimeMessage().getReplyTo());
+
+        builder.setReplyTo(null);
+        assertNull(builder.getMimeMessage().getReplyTo());
+
+        builder.setReplyTo(addresses);
+        assertArrayEquals(InternetAddress.parse(addresses), builder.getMimeMessage().getReplyTo());
+    }
+
+    @Test
+    public void testMessageFactorySetRecipients() throws MessagingException {
+        final SMTPAppender.MimeMessageBuilder builder = new SMTPAppender.MimeMessageBuilder(null);
+        final String addresses = "testing1@example.com,testing2@example.com";
+
+        assertNull(builder.getMimeMessage().getRecipients(Message.RecipientType.TO));
+
+        builder.setRecipients(Message.RecipientType.TO, null);
+        assertNull(builder.getMimeMessage().getRecipients(Message.RecipientType.TO));
+
+        builder.setRecipients(Message.RecipientType.TO, addresses);
+        assertArrayEquals(InternetAddress.parse(addresses), builder.getMimeMessage().getRecipients(Message.RecipientType.TO));
+    }
+
+    @Test
+    public void testMessageFactorySetSubject() throws MessagingException {
+        final SMTPAppender.MimeMessageBuilder builder = new SMTPAppender.MimeMessageBuilder(null);
+        final String subject = "Test Subject";
+
+        assertNull(builder.getMimeMessage().getSubject());
+
+        builder.setSubject(null);
+        assertNull(builder.getMimeMessage().getSubject());
+
+        builder.setSubject(subject);
+        assertEquals(subject, builder.getMimeMessage().getSubject());
+    }
+
+    @Test
+    public void testCyclicBuffer() {
+        final SMTPAppender.CyclicBuffer<Integer> buffer = new SMTPAppender.CyclicBuffer<Integer>(Integer.class, 3);
+
+        assertTrue(buffer.isEmpty());
+        buffer.add(1);
+        assertFalse(buffer.isEmpty());
+        assertEquals(1, (int) buffer.remove());
+
+        assertTrue(buffer.isEmpty());
+        buffer.add(1);
+        buffer.add(2);
+        buffer.add(3);
+        buffer.add(4);
+
+        assertEquals(2, (int) buffer.remove());
+        assertEquals(3, (int) buffer.remove());
+        assertEquals(4, (int) buffer.remove());
+        assertTrue(buffer.isEmpty());
+    }
+
+    private static final String HOST = "localhost";
+    private static final String PORT = "8199";
+    private static final int PORTNUM = Integer.parseInt(PORT);
+
+    @Test
+    public void testDelivery() {
+        final SMTPAppender appender = SMTPAppender.createAppender("Test", "to@example.com", "cc@example.com", "bcc@example.com", "from@example.com",
+                                                                  "replyTo@example.com", "Subject", null, HOST, PORT, null, null, "false", "3", null, null,
+                                                                  "true");
+        appender.start();
+
+        final LoggerContext context = (LoggerContext) LogManager.getContext();
+        final Logger root = context.getLogger("SMTPAppenderTest");
+        root.addAppender(appender);
+        root.setAdditive(false);
+        root.setLevel(Level.DEBUG);
+
+        final SimpleSmtpServer server = SimpleSmtpServer.start(PORTNUM);
+
+        root.debug("Debug message #1");
+        root.debug("Debug message #2");
+        root.debug("Debug message #3");
+        root.error("Error with exception", new RuntimeException("Exception message"));
+
+        server.stop();
+        assertTrue(server.getReceivedEmailSize() == 1);
+        SmtpMessage email = (SmtpMessage) server.getReceivedEmail().next();
+
+        assertEquals("to@example.com", email.getHeaderValue("To"));
+        assertEquals("cc@example.com", email.getHeaderValue("Cc"));
+        // assertEquals("bcc@example.com", email.getHeaderValue("Bcc")); // BCC
+        // can't be tested with Dumpster 1.6
+        assertEquals("from@example.com", email.getHeaderValue("From"));
+        assertEquals("replyTo@example.com", email.getHeaderValue("Reply-To"));
+        assertEquals("Subject", email.getHeaderValue("Subject"));
+
+        String body = email.getBody();
+        assertFalse(body.contains("Debug message #1"));
+        assertTrue(body.contains("Debug message #2"));
+        assertTrue(body.contains("Debug message #3"));
+        assertTrue(body.contains("Error with exception"));
+        assertTrue(body.contains("RuntimeException"));
+        assertTrue(body.contains("Exception message"));
+    }
+}
Index: core/src/test/java/org/apache/logging/log4j/core/net/SMTPSessionManagerTest.java
===================================================================
--- core/src/test/java/org/apache/logging/log4j/core/net/SMTPSessionManagerTest.java	(revision 0)
+++ core/src/test/java/org/apache/logging/log4j/core/net/SMTPSessionManagerTest.java	(revision 0)
@@ -0,0 +1,96 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *	  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.log4j.core.net;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import java.util.Properties;
+
+import javax.mail.Session;
+
+import org.junit.Test;
+
+public class SMTPSessionManagerTest {
+    @Test
+    public void testSessionManagerProtocol() {
+        final String property = "mail.transport.protocol";
+
+        final SMTPSessionManager manager1 = SMTPSessionManager.getSMTPSessionManager("smtp", null, 0, null, null, false);
+        assertEquals("smtp", manager1.getSession().getProperties().getProperty(property));
+
+        final SMTPSessionManager manager2 = SMTPSessionManager.getSMTPSessionManager("smtps", null, 0, null, null, false);
+        assertEquals("smtps", manager2.getSession().getProperties().getProperty(property));
+
+        final SMTPSessionManager manager3 = SMTPSessionManager.getSMTPSessionManager(null, null, 0, null, null, false);
+        assertEquals("smtp", manager3.getSession().getProperties().getProperty(property));
+    }
+
+    @Test
+    public void testSessionFactoryHost() {
+        final String property = "mail.smtp.host";
+
+        final SMTPSessionManager manager1 = SMTPSessionManager.getSMTPSessionManager(null, "my.example.com", 0, null, null, false);
+        assertEquals("my.example.com", manager1.getSession().getProperties().get(property));
+
+        final SMTPSessionManager manager2 = SMTPSessionManager.getSMTPSessionManager(null, null, 0, null, null, false);
+        assertNull(manager2.getSession().getProperties().get(property));
+    }
+
+    @Test
+    public void testSessionFactoryPort() {
+        final String property = "mail.smtp.port";
+
+        final SMTPSessionManager manager1 = SMTPSessionManager.getSMTPSessionManager(null, null, 587, null, null, false);
+        assertEquals("587", manager1.getSession().getProperties().get(property));
+
+        final SMTPSessionManager manager2 = SMTPSessionManager.getSMTPSessionManager(null, null, 0, null, null, false);
+        assertNull(manager2.getSession().getProperties().get(property));
+    }
+
+    @Test
+    public void testSessionFactoryGetAuthenticator() {
+
+        final String property = "mail.smtp.auth";
+
+        final SMTPSessionManager manager1 = SMTPSessionManager.getSMTPSessionManager(null, null, 0, null, null, false);
+        assertNull(manager1.getSession().getProperties().get(property));
+
+        final SMTPSessionManager manager2 = SMTPSessionManager.getSMTPSessionManager(null, null, 0, "username", null, false);
+        assertNull(manager2.getSession().getProperties().get(property));
+
+        final SMTPSessionManager manager3 = SMTPSessionManager.getSMTPSessionManager(null, null, 0, null, "password", false);
+        assertNull(manager3.getSession().getProperties().get(property));
+
+        final SMTPSessionManager manager4 = SMTPSessionManager.getSMTPSessionManager(null, null, 0, "username", "password", false);
+        assertEquals("true", manager4.getSession().getProperties().get(property));
+        // Can't test much more, as javax.mail.Authenticator has only protected methods.
+    }
+
+    @Test
+    public void testSessionFactoryCreateSession() {
+        final Session session = SMTPSessionManager.getSMTPSessionManager("smtps", "my.example.com", 465, "username", "password", true).getSession();
+        final Properties properties = session.getProperties();
+
+        assertEquals("smtps", properties.get("mail.transport.protocol"));
+        assertEquals("my.example.com", properties.get("mail.smtps.host"));
+        assertEquals("465", properties.get("mail.smtps.port"));
+        assertEquals("true", properties.get("mail.smtps.auth"));
+        assertTrue(session.getDebug());
+    }
+}
Index: core/src/main/java/org/apache/logging/log4j/core/net/SMTPSessionManager.java
===================================================================
--- core/src/main/java/org/apache/logging/log4j/core/net/SMTPSessionManager.java	(revision 0)
+++ core/src/main/java/org/apache/logging/log4j/core/net/SMTPSessionManager.java	(revision 0)
@@ -0,0 +1,119 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *	  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.log4j.core.net;
+
+import java.util.Properties;
+
+import javax.mail.Authenticator;
+import javax.mail.PasswordAuthentication;
+import javax.mail.Session;
+
+import org.apache.logging.log4j.core.appender.AbstractManager;
+import org.apache.logging.log4j.core.appender.ManagerFactory;
+
+public class SMTPSessionManager extends AbstractManager {
+    private static final SMTPSessionManagerFactory factory = new SMTPSessionManagerFactory();
+
+    private final Session session;
+
+    protected SMTPSessionManager(final String name, final Session session) {
+        super(name);
+        this.session = session;
+    }
+
+    public static SMTPSessionManager getSMTPSessionManager(String protocol, final String host, final int port, final String username, final String password,
+            final boolean isDebug) {
+        if (protocol == null || protocol.length() == 0) {
+            protocol = "smtp";
+        }
+
+        String name = protocol + ":" + host + ":" + port + ":" + username + ":" + password + (isDebug ? ":debug" : "");
+        return (SMTPSessionManager) getManager(name, factory, new FactoryData(protocol, host, port, username, password, isDebug));
+    }
+
+    public Session getSession() {
+        return session;
+    }
+
+    private static class FactoryData {
+        private final String protocol;
+        private final String host;
+        private final int port;
+        private final String username;
+        private final String password;
+        private final boolean isDebug;
+
+        public FactoryData(final String protocol, final String host, final int port, final String username, final String password, final boolean isDebug) {
+            this.protocol = protocol;
+            this.host = host;
+            this.port = port;
+            this.username = username;
+            this.password = password;
+            this.isDebug = isDebug;
+        }
+    }
+
+    private static class SMTPSessionManagerFactory implements ManagerFactory<SMTPSessionManager, FactoryData> {
+
+        public SMTPSessionManager createManager(final String name, final FactoryData data) {
+            final String prefix = "mail." + data.protocol;
+
+            Properties properties = getProperties();
+            properties.put("mail.transport.protocol", data.protocol);
+
+            if (null != data.host) {
+                properties.put(prefix + ".host", data.host);
+            }
+            if (data.port > 0) {
+                properties.put(prefix + ".port", String.valueOf(data.port));
+            }
+
+            final Authenticator authenticator = buildAuthenticator(data.username, data.password);
+            if (null != authenticator) {
+                properties.put(prefix + ".auth", "true");
+            }
+
+            final Session session = Session.getInstance(properties, authenticator);
+            session.setProtocolForAddress("rfc822", data.protocol);
+            session.setDebug(data.isDebug);
+
+            return new SMTPSessionManager(name, session);
+        }
+
+        private Properties getProperties() {
+            try {
+                return new Properties(System.getProperties());
+            } catch (SecurityException ex) {
+                // Sandboxed - can't read System Properties
+                return new Properties();
+            }
+        }
+
+        private Authenticator buildAuthenticator(final String username, final String password) {
+            if (null != password && null != username) {
+                return new Authenticator() {
+                    private final PasswordAuthentication passwordAuthentication = new PasswordAuthentication(username, password);
+
+                    protected PasswordAuthentication getPasswordAuthentication() {
+                        return passwordAuthentication;
+                    }
+                };
+            }
+            return null;
+        }
+    }
+}
Index: core/src/main/java/org/apache/logging/log4j/core/appender/SMTPAppender.java
===================================================================
--- core/src/main/java/org/apache/logging/log4j/core/appender/SMTPAppender.java	(revision 0)
+++ core/src/main/java/org/apache/logging/log4j/core/appender/SMTPAppender.java	(revision 0)
@@ -0,0 +1,421 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *	  http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.logging.log4j.core.appender;
+
+import org.apache.logging.log4j.core.appender.AbstractAppender;
+import org.apache.logging.log4j.core.config.plugins.Plugin;
+import org.apache.logging.log4j.core.config.plugins.PluginAttr;
+import org.apache.logging.log4j.core.config.plugins.PluginElement;
+import org.apache.logging.log4j.core.config.plugins.PluginFactory;
+import org.apache.logging.log4j.core.filter.ThresholdFilter;
+import org.apache.logging.log4j.core.layout.HTMLLayout;
+import org.apache.logging.log4j.core.net.SMTPSessionManager;
+import org.apache.logging.log4j.core.Filter;
+import org.apache.logging.log4j.core.Layout;
+import org.apache.logging.log4j.core.LogEvent;
+
+import javax.activation.DataSource;
+import javax.mail.Message;
+import javax.mail.MessagingException;
+import javax.mail.Session;
+import javax.mail.Transport;
+import javax.mail.internet.AddressException;
+import javax.mail.internet.InternetAddress;
+import javax.mail.internet.InternetHeaders;
+import javax.mail.internet.MimeBodyPart;
+import javax.mail.internet.MimeMessage;
+import javax.mail.internet.MimeMultipart;
+import javax.mail.internet.MimeUtility;
+import javax.mail.util.ByteArrayDataSource;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.lang.reflect.Array;
+import java.util.Date;
+
+/**
+ * Send an e-mail when a specific logging event occurs, typically on errors or
+ * fatal errors.
+ * 
+ * <p>
+ * The number of logging events delivered in this e-mail depend on the value of
+ * <b>BufferSize</b> option. The <code>SMTPAppender</code> keeps only the last
+ * <code>BufferSize</code> logging events in its cyclic buffer. This keeps
+ * memory requirements at a reasonable level while still delivering useful
+ * application context.
+ * 
+ * By default, an email message will formatted as HTML. This can be modified by
+ * setting a layout for the appender.
+ * 
+ * By default, an email message will be sent when an ERROR or higher severity
+ * message is appended. This can be modified by setting a filter for the
+ * appender.
+ * 
+ * @author Scott Severtson, based loosely on Ceki G&uuml;lc&uuml;'s work for
+ *         Log4J 1.x
+ * @since 1.0
+ */
+@Plugin(name = "SMTP", type = "Core", elementType = "appender", printObject = true)
+public class SMTPAppender extends AbstractAppender {
+    protected final CyclicBuffer<LogEvent> buffer;
+    protected final MimeMessage message;
+
+    private SMTPAppender(final String name, final Filter filter, final Layout<?> layout, final MimeMessage message, final int bufferSize,
+            boolean handleExceptions) {
+        super(name, filter, layout, handleExceptions);
+        this.message = message;
+        this.buffer = new CyclicBuffer<LogEvent>(LogEvent.class, bufferSize);
+    }
+
+    /**
+     * Create a SMTPAppender.
+     * 
+     * @param name
+     *            The name of the Appender.
+     * @param to
+     *            The comma-separated list of recipient email addresses.
+     * @param cc
+     *            The comma-separated list of CC email addresses.
+     * @param bcc
+     *            The comma-separated list of BCC email addresses.
+     * @param from
+     *            The email address of the sender.
+     * @param replyTo
+     *            The comma-separated list of reply-to email addresses.
+     * @param smtpProtocol
+     *            The SMTP transport protocol (such as "smtps", defaults to
+     *            "smtp").
+     * @param smtpHost
+     *            The SMTP hostname to send to.
+     * @param smtpPortNum
+     *            The SMTP port to send to.
+     * @param smtpUsername
+     *            The username required to authenticate against the SMTP server.
+     * @param smtpPassword
+     *            The password required to authenticate against the SMTP server.
+     * @param smtpDebug
+     *            Enable mail session debuging on STDOUT.
+     * @param bufferSizeNum
+     *            How many log events should be buffered for inclusion in the
+     *            message?
+     * @param layout
+     *            The layout to use (defaults to HTMLLayout).
+     * @param filter
+     *            The Filter or null (defaults to ThresholdFilter, level of
+     *            ERROR).
+     * @param suppressExceptions
+     *            "true" if exceptions should be hidden from the application,
+     *            "false" otherwise (defaults to "true").
+     * @return The SMTPAppender.
+     */
+    @PluginFactory
+    public static SMTPAppender createAppender(@PluginAttr("name") final String name,
+                                              @PluginAttr("to") final String to,
+                                              @PluginAttr("cc") final String cc,
+                                              @PluginAttr("bcc") final String bcc,
+                                              @PluginAttr("from") final String from,
+                                              @PluginAttr("replyTo") final String replyTo,
+                                              @PluginAttr("subject") final String subject,
+                                              @PluginAttr("smtpProtocol") String smtpProtocol,
+                                              @PluginAttr("smtpHost") final String smtpHost,
+                                              @PluginAttr("smtpPort") final String smtpPortNum,
+                                              @PluginAttr("smtpUsername") final String smtpUsername,
+                                              @PluginAttr("smtpPassword") final String smtpPassword,
+                                              @PluginAttr("smtpDebug") final String smtpDebug,
+                                              @PluginAttr("bufferSize") final String bufferSizeNum,
+                                              @PluginElement("layout") Layout<?> layout,
+                                              @PluginElement("filter") Filter filter,
+                                              @PluginAttr("suppressExceptions") final String suppressExceptions) {
+        if (name == null) {
+            LOGGER.error("No name provided for SMTPAppender");
+            return null;
+        }
+
+        final boolean isHandleExceptions = suppressExceptions == null ? true : Boolean.valueOf(suppressExceptions);
+        final int smtpPort = smtpPortNum == null ? 0 : Integer.parseInt(smtpPortNum);
+        final boolean isSmtpDebug = smtpDebug == null ? false : Boolean.valueOf(smtpDebug);
+        final int bufferSize = bufferSizeNum == null ? 512 : Integer.valueOf(bufferSizeNum);
+
+        if (layout == null) {
+            layout = HTMLLayout.createLayout(null, null, null, null, null, null);
+        }
+        if (filter == null) {
+            filter = ThresholdFilter.createFilter(null, null, null);
+        }
+
+        final SMTPSessionManager manager = SMTPSessionManager.getSMTPSessionManager(smtpProtocol, smtpHost, smtpPort, smtpUsername, smtpPassword, isSmtpDebug);
+        if (manager == null) {
+            return null;
+        }
+
+        final MimeMessage message;
+        try {
+            final Session session = manager.getSession();
+            message = new MimeMessageBuilder(session).setFrom(from).setReplyTo(replyTo).setRecipients(Message.RecipientType.TO, to)
+                    .setRecipients(Message.RecipientType.CC, cc).setRecipients(Message.RecipientType.BCC, bcc).setSubject(subject).getMimeMessage();
+        } catch (MessagingException e) {
+            LOGGER.error("Could not set SMTPAppender message options.", e);
+            return null;
+        }
+
+        return new SMTPAppender(name, filter, layout, message, bufferSize, isHandleExceptions);
+    }
+
+    /**
+     * Capture all events in CyclicBuffer
+     */
+    @Override
+    public boolean isFiltered(LogEvent event) {
+        synchronized (buffer) {
+            buffer.add(event);
+        }
+        return super.isFiltered(event);
+    }
+
+    /**
+     * Perform SMTPAppender specific appending actions, mainly adding the event
+     * to a cyclic buffer and checking if the event triggers an e-mail to be
+     * sent.
+     */
+    public void append(LogEvent event) {
+        sendBuffer();
+    }
+
+    /**
+     * Send the contents of the cyclic buffer as an e-mail message.
+     */
+    protected void sendBuffer() {
+        try {
+            byte[] rawBytes = formatContentToBytes(buffer, getLayout());
+
+            String contentType = getContentType(getLayout());
+            String encoding = getEncoding(rawBytes, contentType);
+            byte[] encodedBytes = encodeContentToBytes(rawBytes, encoding);
+
+            InternetHeaders headers = getHeaders(contentType, encoding);
+            MimeMultipart mp = getMimeMultipart(encodedBytes, headers);
+
+            sendMultipartMessage(message, mp);
+        } catch (MessagingException e) {
+            LOGGER.error("Error occured while sending e-mail notification.", e);
+        } catch (IOException e) {
+            LOGGER.error("Error occured while sending e-mail notification.", e);
+        } catch (RuntimeException e) {
+            LOGGER.error("Error occured while sending e-mail notification.", e);
+        }
+    }
+
+    protected byte[] formatContentToBytes(CyclicBuffer<LogEvent> cb, Layout<?> layout) throws IOException {
+        ByteArrayOutputStream raw = new ByteArrayOutputStream();
+        writeContent(cb, layout, raw);
+        return raw.toByteArray();
+    }
+
+    private void writeContent(CyclicBuffer<LogEvent> cb, Layout<?> layout, ByteArrayOutputStream out) throws IOException {
+        writeHeader(layout, out);
+        writeBuffer(cb, layout, out);
+        writeFooter(layout, out);
+    }
+
+    protected void writeHeader(Layout<?> layout, OutputStream out) throws IOException {
+        byte[] header = layout.getHeader();
+        if (header != null) {
+            out.write(header);
+        }
+    }
+
+    protected void writeBuffer(CyclicBuffer<LogEvent> cb, Layout<?> layout, OutputStream out) throws IOException {
+        synchronized (cb) {
+            while (!cb.isEmpty()) {
+                LogEvent event = cb.remove();
+                byte[] bytes = layout.toByteArray(event);
+                out.write(bytes);
+            }
+        }
+    }
+
+    protected void writeFooter(Layout<?> layout, OutputStream out) throws IOException {
+        byte[] footer = layout.getFooter();
+        if (footer != null) {
+            out.write(footer);
+        }
+    }
+
+    protected String getContentType(Layout<?> layout) {
+        // HACK: Log4J 1.x had a Layout.getContentType() method
+        if (layout instanceof HTMLLayout) {
+            return "text/html";
+        }
+        return "text/plain";
+    }
+
+    protected String getEncoding(byte[] rawBytes, String contentType) {
+        DataSource dataSource = new ByteArrayDataSource(rawBytes, contentType);
+        return MimeUtility.getEncoding(dataSource);
+    }
+
+    protected byte[] encodeContentToBytes(byte[] rawBytes, String encoding) throws MessagingException, IOException {
+        ByteArrayOutputStream encoded = new ByteArrayOutputStream();
+        encodeContent(rawBytes, encoding, encoded);
+        return encoded.toByteArray();
+    }
+
+    protected void encodeContent(byte[] bytes, String encoding, ByteArrayOutputStream out) throws MessagingException, IOException {
+        OutputStream encoder = MimeUtility.encode(out, encoding);
+        encoder.write(bytes);
+        encoder.close();
+    }
+
+    protected InternetHeaders getHeaders(String contentType, String encoding) {
+        InternetHeaders headers = new InternetHeaders();
+        headers.setHeader("Content-Type", contentType + "; charset=UTF-8");
+        headers.setHeader("Content-Transfer-Encoding", encoding);
+        return headers;
+    }
+
+    protected MimeMultipart getMimeMultipart(byte[] encodedBytes, InternetHeaders headers) throws MessagingException {
+        MimeMultipart mp = new MimeMultipart();
+        MimeBodyPart part = new MimeBodyPart(headers, encodedBytes);
+        mp.addBodyPart(part);
+        return mp;
+    }
+
+    protected void sendMultipartMessage(MimeMessage message, MimeMultipart mp) throws MessagingException {
+        synchronized (message) {
+            message.setContent(mp);
+            message.setSentDate(new Date());
+            Transport.send(message);
+        }
+    }
+
+    protected static class MimeMessageBuilder {
+        private final MimeMessage message;
+
+        public MimeMessageBuilder(Session session) {
+            message = new MimeMessage(session);
+        }
+
+        public MimeMessageBuilder setFrom(final String from) throws MessagingException {
+            InternetAddress address = parseAddress(from);
+
+            if (null != address) {
+                message.setFrom(address);
+            } else {
+                message.setFrom();
+            }
+            return this;
+        }
+
+        public MimeMessageBuilder setReplyTo(final String replyTo) throws MessagingException {
+            InternetAddress[] addresses = parseAddresses(replyTo);
+
+            if (null != addresses) {
+                message.setReplyTo(addresses);
+            }
+            return this;
+        }
+
+        public MimeMessageBuilder setRecipients(final Message.RecipientType recipientType, final String recipients) throws MessagingException {
+            InternetAddress[] addresses = parseAddresses(recipients);
+
+            if (null != addresses) {
+                message.setRecipients(recipientType, addresses);
+            }
+            return this;
+        }
+
+        public MimeMessageBuilder setSubject(final String subject) throws MessagingException {
+            if (subject != null) {
+                message.setSubject(subject, "UTF-8");
+            }
+            return this;
+        }
+
+        public MimeMessage getMimeMessage() {
+            return message;
+        }
+
+        private static InternetAddress parseAddress(String address) throws AddressException {
+            return address == null ? null : new InternetAddress(address);
+        }
+
+        private static InternetAddress[] parseAddresses(String addresses) throws AddressException {
+            return addresses == null ? null : InternetAddress.parse(addresses, true);
+        }
+    }
+
+    protected static class CyclicBuffer<T> {
+        private T[] ring;
+        private int first = 0;
+        private int last = 0;
+        private int numElems = 0;
+
+        /**
+         * Instantiate a new CyclicBuffer of at most <code>maxSize</code>
+         * events.
+         */
+        protected CyclicBuffer(Class<T> clazz, int size) throws IllegalArgumentException {
+            if (size < 1) {
+                throw new IllegalArgumentException("The maxSize argument (" + size + ") is not a positive integer.");
+            }
+            this.ring = makeArray(clazz, size);
+        }
+
+        @SuppressWarnings("unchecked")
+        private T[] makeArray(Class<T> clazz, int size) {
+            return (T[]) Array.newInstance(clazz, size);
+        }
+
+        /**
+         * Add an item as the last event in the buffer.
+         */
+        protected void add(T item) {
+            ring[last] = item;
+            if (++last == ring.length) {
+                last = 0;
+            }
+
+            if (numElems < ring.length) {
+                numElems++;
+            } else if (++first == ring.length) {
+                first = 0;
+            }
+        }
+
+        /**
+         * Remove and return the oldest (first) item in the buffer.
+         */
+        protected T remove() {
+            T item = null;
+            if (numElems > 0) {
+                numElems--;
+                item = ring[first];
+                ring[first] = null;
+                if (++first == ring.length) {
+                    first = 0;
+                }
+            }
+            return item;
+        }
+
+        public boolean isEmpty() {
+            return 0 == numElems;
+        }
+    }
+}
\ No newline at end of file
Index: core/pom.xml
===================================================================
--- core/pom.xml	(revision 1425101)
+++ core/pom.xml	(working copy)
@@ -112,6 +112,19 @@
       <version>1.0</version>
       <optional>true</optional>
     </dependency>
+    <dependency>
+      <groupId>javax.mail</groupId>
+      <artifactId>mail</artifactId>
+      <version>1.4.5</version>
+      <optional>true</optional>
+    </dependency>
+    <dependency>
+	  <groupId>dumbster</groupId>
+	  <artifactId>dumbster</artifactId>
+	  <version>1.6</version>
+	  <optional>true</optional>
+	  <scope>test</scope>
+    </dependency>
   </dependencies>
   <build>
     <plugins>
Index: log4j12-api/pom.xml
===================================================================
--- log4j12-api/pom.xml	(revision 1425101)
+++ log4j12-api/pom.xml	(working copy)
@@ -54,6 +54,14 @@
       <type>test-jar</type>
       <scope>test</scope>
     </dependency>
+    <dependency>
+      <groupId>javax.mail</groupId>
+      <artifactId>mail</artifactId>
+      <version>1.4.5</version>
+      <optional>true</optional>
+      <scope>test</scope>
+    </dependency>
+
   </dependencies>
       <reporting>
         <plugins>
Index: jcl-bridge/pom.xml
===================================================================
--- jcl-bridge/pom.xml	(revision 1425101)
+++ jcl-bridge/pom.xml	(working copy)
@@ -62,6 +62,13 @@
       <type>test-jar</type>
       <scope>test</scope>
     </dependency>
+    <dependency>
+      <groupId>javax.mail</groupId>
+      <artifactId>mail</artifactId>
+      <version>1.4.5</version>
+      <optional>true</optional>
+      <scope>test</scope>
+    </dependency>
   </dependencies>
       <reporting>
         <plugins>
Index: flume-ng/src/main/java/org/apache/logging/log4j/flume/appender/FlumeAppender.java
===================================================================
--- flume-ng/src/main/java/org/apache/logging/log4j/flume/appender/FlumeAppender.java	(revision 1425101)
+++ flume-ng/src/main/java/org/apache/logging/log4j/flume/appender/FlumeAppender.java	(working copy)
@@ -152,8 +152,8 @@
         final int retries = agentRetries == null ? 0 : Integer.parseInt(agentRetries);
 
         if (layout == null) {
-            layout = RFC5424Layout.createLayout(null, null, null, "True", null, null, null, null, excludes,
-                includes, required, null, null);
+            layout = RFC5424Layout.createLayout(null, null, null, "True", null, null, null, null, null,
+                excludes, includes, required, null, null);
         }
 
         if (name == null) {
Index: flume-ng/pom.xml
===================================================================
--- flume-ng/pom.xml	(revision 1425101)
+++ flume-ng/pom.xml	(working copy)
@@ -108,6 +108,13 @@
       <version>1.0.1</version>
       <scope>test</scope>
     </dependency>
+    <dependency>
+      <groupId>javax.mail</groupId>
+      <artifactId>mail</artifactId>
+      <version>1.4.5</version>
+      <optional>true</optional>
+      <scope>test</scope>
+    </dependency>
   </dependencies>
   <build>
     <plugins>
Index: web/pom.xml
===================================================================
--- web/pom.xml	(revision 1425101)
+++ web/pom.xml	(working copy)
@@ -67,6 +67,13 @@
       <artifactId>junit</artifactId>
       <scope>test</scope>
     </dependency>
+    <dependency>
+      <groupId>javax.mail</groupId>
+      <artifactId>mail</artifactId>
+      <version>1.4.5</version>
+      <optional>true</optional>
+      <scope>test</scope>
+    </dependency>
   </dependencies>
       <reporting>
         <plugins>
Index: slf4j-impl/pom.xml
===================================================================
--- slf4j-impl/pom.xml	(revision 1425101)
+++ slf4j-impl/pom.xml	(working copy)
@@ -62,6 +62,13 @@
       <artifactId>junit</artifactId>
       <scope>test</scope>
     </dependency>
+    <dependency>
+      <groupId>javax.mail</groupId>
+      <artifactId>mail</artifactId>
+      <version>1.4.5</version>
+      <optional>true</optional>
+      <scope>test</scope>
+    </dependency>
   </dependencies>
       <reporting>
         <plugins>
