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    }