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 org.apache.logging.log4j.core.config.plugins.Plugin;
021    import org.apache.logging.log4j.core.config.plugins.PluginAttr;
022    import org.apache.logging.log4j.core.config.plugins.PluginElement;
023    import org.apache.logging.log4j.core.config.plugins.PluginFactory;
024    import org.apache.logging.log4j.core.filter.ThresholdFilter;
025    import org.apache.logging.log4j.core.layout.HTMLLayout;
026    import org.apache.logging.log4j.core.net.SMTPManager;
027    import org.apache.logging.log4j.core.Filter;
028    import org.apache.logging.log4j.core.Layout;
029    import org.apache.logging.log4j.core.LogEvent;
030    
031    /**
032     * Send an e-mail when a specific logging event occurs, typically on errors or
033     * fatal errors.
034     *
035     * <p>
036     * The number of logging events delivered in this e-mail depend on the value of
037     * <b>BufferSize</b> option. The <code>SMTPAppender</code> keeps only the last
038     * <code>BufferSize</code> logging events in its cyclic buffer. This keeps
039     * memory requirements at a reasonable level while still delivering useful
040     * application context.
041     *
042     * By default, an email message will formatted as HTML. This can be modified by
043     * setting a layout for the appender.
044     *
045     * By default, an email message will be sent when an ERROR or higher severity
046     * message is appended. This can be modified by setting a filter for the
047     * appender.
048     */
049    @Plugin(name = "SMTP", type = "Core", elementType = "appender", printObject = true)
050    public final class SMTPAppender extends AbstractAppender {
051    
052        private static final int DEFAULT_BUFFER_SIZE = 512;
053    
054        /** The SMTP Manager */
055        protected final SMTPManager manager;
056    
057        private SMTPAppender(final String name, final Filter filter, final Layout<?> layout, final SMTPManager manager,
058                             final boolean handleExceptions) {
059            super(name, filter, layout, handleExceptions);
060            this.manager = manager;
061        }
062    
063        /**
064         * Create a SMTPAppender.
065         *
066         * @param name
067         *            The name of the Appender.
068         * @param to
069         *            The comma-separated list of recipient email addresses.
070         * @param cc
071         *            The comma-separated list of CC email addresses.
072         * @param bcc
073         *            The comma-separated list of BCC email addresses.
074         * @param from
075         *            The email address of the sender.
076         * @param replyTo
077         *            The comma-separated list of reply-to email addresses.
078         * @param subject The subject of the email message.
079         * @param smtpProtocol The SMTP transport protocol (such as "smtps", defaults to "smtp").
080         * @param smtpHost
081         *            The SMTP hostname to send to.
082         * @param smtpPortNum
083         *            The SMTP port to send to.
084         * @param smtpUsername
085         *            The username required to authenticate against the SMTP server.
086         * @param smtpPassword
087         *            The password required to authenticate against the SMTP server.
088         * @param smtpDebug
089         *            Enable mail session debuging on STDOUT.
090         * @param bufferSizeNum
091         *            How many log events should be buffered for inclusion in the
092         *            message?
093         * @param layout
094         *            The layout to use (defaults to HTMLLayout).
095         * @param filter
096         *            The Filter or null (defaults to ThresholdFilter, level of
097         *            ERROR).
098         * @param suppressExceptions
099         *            "true" if exceptions should be hidden from the application,
100         *            "false" otherwise (defaults to "true").
101         * @return The SMTPAppender.
102         */
103        @PluginFactory
104        public static SMTPAppender createAppender(@PluginAttr("name") final String name,
105                                                  @PluginAttr("to") final String to,
106                                                  @PluginAttr("cc") final String cc,
107                                                  @PluginAttr("bcc") final String bcc,
108                                                  @PluginAttr("from") final String from,
109                                                  @PluginAttr("replyTo") final String replyTo,
110                                                  @PluginAttr("subject") final String subject,
111                                                  @PluginAttr("smtpProtocol") final String smtpProtocol,
112                                                  @PluginAttr("smtpHost") final String smtpHost,
113                                                  @PluginAttr("smtpPort") final String smtpPortNum,
114                                                  @PluginAttr("smtpUsername") final String smtpUsername,
115                                                  @PluginAttr("smtpPassword") final String smtpPassword,
116                                                  @PluginAttr("smtpDebug") final String smtpDebug,
117                                                  @PluginAttr("bufferSize") final String bufferSizeNum,
118                                                  @PluginElement("layout") Layout<?> layout,
119                                                  @PluginElement("filter") Filter filter,
120                                                  @PluginAttr("suppressExceptions") final String suppressExceptions) {
121            if (name == null) {
122                LOGGER.error("No name provided for SMTPAppender");
123                return null;
124            }
125    
126            final boolean isHandleExceptions = suppressExceptions == null ? true : Boolean.valueOf(suppressExceptions);
127            final int smtpPort = smtpPortNum == null ? 0 : Integer.parseInt(smtpPortNum);
128            final boolean isSmtpDebug = smtpDebug == null ? false : Boolean.valueOf(smtpDebug);
129            final int bufferSize = bufferSizeNum == null ? DEFAULT_BUFFER_SIZE : Integer.valueOf(bufferSizeNum);
130    
131            if (layout == null) {
132                layout = HTMLLayout.createLayout(null, null, null, null, null, null);
133            }
134            if (filter == null) {
135                filter = ThresholdFilter.createFilter(null, null, null);
136            }
137    
138            final SMTPManager manager = SMTPManager.getSMTPManager(to, cc, bcc, from, replyTo, subject, smtpProtocol,
139                smtpHost, smtpPort, smtpUsername, smtpPassword, isSmtpDebug, filter.toString(),  bufferSize);
140            if (manager == null) {
141                return null;
142            }
143    
144            return new SMTPAppender(name, filter, layout, manager, isHandleExceptions);
145        }
146    
147        /**
148         * Capture all events in CyclicBuffer.
149         * @param event The Log event.
150         * @return true if the event should be filtered.
151         */
152        @Override
153        public boolean isFiltered(final LogEvent event) {
154            final boolean filtered = super.isFiltered(event);
155            if (filtered) {
156                manager.add(event);
157            }
158            return filtered;
159        }
160    
161        /**
162         * Perform SMTPAppender specific appending actions, mainly adding the event
163         * to a cyclic buffer and checking if the event triggers an e-mail to be
164         * sent.
165         * @param event The Log event.
166         */
167        public void append(final LogEvent event) {
168            manager.sendEvents(getLayout(), event);
169        }
170    }