    001    /*
    002     * Licensed to the Apache Software Foundation (ASF) under one or more
    003     * contributor license agreements. See the NOTICE file distributed with
    004     * this work for additional information regarding copyright ownership.
    005     * The ASF licenses this file to You under the Apache license, Version 2.0
    006     * (the "License"); you may not use this file except in compliance with
    007     * the License. You may obtain a copy of the License at
    008     *
    009     *      http://www.apache.org/licenses/LICENSE-2.0
    010     *
    011     * Unless required by applicable law or agreed to in writing, software
    012     * distributed under the License is distributed on an "AS IS" BASIS,
    013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    014     * See the license for the specific language governing permissions and
    015     * limitations under the license.
    016     */
    017
    018    package org.apache.logging.log4j.core.appender;
    019
    020    import java.io.Serializable;
    021
    022    import org.apache.logging.log4j.core.Filter;
    023    import org.apache.logging.log4j.core.Layout;
    024    import org.apache.logging.log4j.core.LogEvent;
    025    import org.apache.logging.log4j.core.config.plugins.Plugin;
    026    import org.apache.logging.log4j.core.config.plugins.PluginAttribute;
    027    import org.apache.logging.log4j.core.config.plugins.PluginElement;
    028    import org.apache.logging.log4j.core.config.plugins.PluginFactory;
    029    import org.apache.logging.log4j.core.filter.ThresholdFilter;
    030    import org.apache.logging.log4j.core.layout.HtmlLayout;
    031    import org.apache.logging.log4j.core.net.SmtpManager;
    032    import org.apache.logging.log4j.core.util.Booleans;
    033
    034    /**
    035     * Send an e-mail when a specific logging event occurs, typically on errors or
    036     * fatal errors.
    037     *
    038     * <p>
    039     * The number of logging events delivered in this e-mail depend on the value of
    040     * <b>BufferSize</b> option. The <code>SmtpAppender</code> keeps only the last
    041     * <code>BufferSize</code> logging events in its cyclic buffer. This keeps
    042     * memory requirements at a reasonable level while still delivering useful
    043     * application context.
    044     *
    045     * By default, an email message will formatted as HTML. This can be modified by
    046     * setting a layout for the appender.
    047     *
    048     * By default, an email message will be sent when an ERROR or higher severity
    049     * message is appended. This can be modified by setting a filter for the
    050     * appender.
    051     */
    052    @Plugin(name = "SMTP", category = "Core", elementType = "appender", printObject = true)
    053    public final class SmtpAppender extends AbstractAppender {
    054
    055        private static final long serialVersionUID = 1L;
    056        private static final int DEFAULT_BUFFER_SIZE = 512;
    057
    058        /** The SMTP Manager */
    059        private final SmtpManager manager;
    060
    061        private SmtpAppender(final String name, final Filter filter, final Layout<? extends Serializable> layout, final SmtpManager manager,
    062                             final boolean ignoreExceptions) {
    063            super(name, filter, layout, ignoreExceptions);
    064            this.manager = manager;
    065        }
    066
    067        /**
    068         * Create a SmtpAppender.
    069         *
    070         * @param name
    071         *            The name of the Appender.
    072         * @param to
    073         *            The comma-separated list of recipient email addresses.
    074         * @param cc
    075         *            The comma-separated list of CC email addresses.
    076         * @param bcc
    077         *            The comma-separated list of BCC email addresses.
    078         * @param from
    079         *            The email address of the sender.
    080         * @param replyTo
    081         *            The comma-separated list of reply-to email addresses.
    082         * @param subject The subject of the email message.
    083         * @param smtpProtocol The SMTP transport protocol (such as "smtps", defaults to "smtp").
    084         * @param smtpHost
    085         *            The SMTP hostname to send to.
    086         * @param smtpPortStr
    087         *            The SMTP port to send to.
    088         * @param smtpUsername
    089         *            The username required to authenticate against the SMTP server.
    090         * @param smtpPassword
    091         *            The password required to authenticate against the SMTP server.
    092         * @param smtpDebug
    093         *            Enable mail session debuging on STDOUT.
    094         * @param bufferSizeStr
    095         *            How many log events should be buffered for inclusion in the
    096         *            message?
    097         * @param layout
    098         *            The layout to use (defaults to HtmlLayout).
    099         * @param filter
    100         *            The Filter or null (defaults to ThresholdFilter, level of
    101         *            ERROR).
    102         * @param ignore If {@code "true"} (default) exceptions encountered when appending events are logged; otherwise
    103         *               they are propagated to the caller.
    104         * @return The SmtpAppender.
    105         */
    106        @PluginFactory
    107        public static SmtpAppender createAppender(
    108                @PluginAttribute("name") final String name,
    109                @PluginAttribute("to") final String to,
    110                @PluginAttribute("cc") final String cc,
    111                @PluginAttribute("bcc") final String bcc,
    112                @PluginAttribute("from") final String from,
    113                @PluginAttribute("replyTo") final String replyTo,
    114                @PluginAttribute("subject") final String subject,
    115                @PluginAttribute("smtpProtocol") final String smtpProtocol,
    116                @PluginAttribute("smtpHost") final String smtpHost,
    117                @PluginAttribute("smtpPort") final String smtpPortStr,
    118                @PluginAttribute("smtpUsername") final String smtpUsername,
    119                @PluginAttribute("smtpPassword") final String smtpPassword,
    120                @PluginAttribute("smtpDebug") final String smtpDebug,
    121                @PluginAttribute("bufferSize") final String bufferSizeStr,
    122                @PluginElement("Layout") Layout<? extends Serializable> layout,
    123                @PluginElement("Filter") Filter filter,
    124                @PluginAttribute("ignoreExceptions") final String ignore) {
    125            if (name == null) {
    126                LOGGER.error("No name provided for SmtpAppender");
    127                return null;
    128            }
    129
    130            final boolean ignoreExceptions = Booleans.parseBoolean(ignore, true);
    131            final int smtpPort = AbstractAppender.parseInt(smtpPortStr, 0);
    132            final boolean isSmtpDebug = Boolean.parseBoolean(smtpDebug);
    133            final int bufferSize = bufferSizeStr == null ? DEFAULT_BUFFER_SIZE : Integer.parseInt(bufferSizeStr);
    134
    135            if (layout == null) {
    136                layout = HtmlLayout.createDefaultLayout();
    137            }
    138            if (filter == null) {
    139                filter = ThresholdFilter.createFilter(null, null, null);
    140            }
    141
    142            final SmtpManager manager = SmtpManager.getSMTPManager(to, cc, bcc, from, replyTo, subject, smtpProtocol,
    143                smtpHost, smtpPort, smtpUsername, smtpPassword, isSmtpDebug, filter.toString(),  bufferSize);
    144            if (manager == null) {
    145                return null;
    146            }
    147
    148            return new SmtpAppender(name, filter, layout, manager, ignoreExceptions);
    149        }
    150
    151        /**
    152         * Capture all events in CyclicBuffer.
    153         * @param event The Log event.
    154         * @return true if the event should be filtered.
    155         */
    156        @Override
    157        public boolean isFiltered(final LogEvent event) {
    158            final boolean filtered = super.isFiltered(event);
    159            if (filtered) {
    160                manager.add(event);
    161            }
    162            return filtered;
    163        }
    164
    165        /**
    166         * Perform SmtpAppender specific appending actions, mainly adding the event
    167         * to a cyclic buffer and checking if the event triggers an e-mail to be
    168         * sent.
    169         * @param event The Log event.
    170         */
    171        @Override
    172        public void append(final LogEvent event) {
    173            manager.sendEvents(getLayout(), event);
    174        }
    175    }