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    import java.io.Serializable;
032    
033    /**
034     * Send an e-mail when a specific logging event occurs, typically on errors or
035     * fatal errors.
036     *
037     * <p>
038     * The number of logging events delivered in this e-mail depend on the value of
039     * <b>BufferSize</b> option. The <code>SMTPAppender</code> keeps only the last
040     * <code>BufferSize</code> logging events in its cyclic buffer. This keeps
041     * memory requirements at a reasonable level while still delivering useful
042     * application context.
043     *
044     * By default, an email message will formatted as HTML. This can be modified by
045     * setting a layout for the appender.
046     *
047     * By default, an email message will be sent when an ERROR or higher severity
048     * message is appended. This can be modified by setting a filter for the
049     * appender.
050     */
051    @Plugin(name = "SMTP", category = "Core", elementType = "appender", printObject = true)
052    public final class SMTPAppender<T extends Serializable> extends AbstractAppender<T> {
053    
054        private static final int DEFAULT_BUFFER_SIZE = 512;
055    
056        /** The SMTP Manager */
057        protected final SMTPManager manager;
058    
059        private SMTPAppender(final String name, final Filter filter, final Layout<T> layout, final SMTPManager manager,
060                             final boolean handleExceptions) {
061            super(name, filter, layout, handleExceptions);
062            this.manager = manager;
063        }
064    
065        /**
066         * Create a SMTPAppender.
067         *
068         * @param name
069         *            The name of the Appender.
070         * @param to
071         *            The comma-separated list of recipient email addresses.
072         * @param cc
073         *            The comma-separated list of CC email addresses.
074         * @param bcc
075         *            The comma-separated list of BCC email addresses.
076         * @param from
077         *            The email address of the sender.
078         * @param replyTo
079         *            The comma-separated list of reply-to email addresses.
080         * @param subject The subject of the email message.
081         * @param smtpProtocol The SMTP transport protocol (such as "smtps", defaults to "smtp").
082         * @param smtpHost
083         *            The SMTP hostname to send to.
084         * @param smtpPortNum
085         *            The SMTP port to send to.
086         * @param smtpUsername
087         *            The username required to authenticate against the SMTP server.
088         * @param smtpPassword
089         *            The password required to authenticate against the SMTP server.
090         * @param smtpDebug
091         *            Enable mail session debuging on STDOUT.
092         * @param bufferSizeNum
093         *            How many log events should be buffered for inclusion in the
094         *            message?
095         * @param layout
096         *            The layout to use (defaults to HTMLLayout).
097         * @param filter
098         *            The Filter or null (defaults to ThresholdFilter, level of
099         *            ERROR).
100         * @param suppressExceptions
101         *            "true" if exceptions should be hidden from the application,
102         *            "false" otherwise (defaults to "true").
103         * @return The SMTPAppender.
104         */
105        @PluginFactory
106        public static <S extends Serializable> SMTPAppender<S> createAppender(@PluginAttr("name") final String name,
107                                                  @PluginAttr("to") final String to,
108                                                  @PluginAttr("cc") final String cc,
109                                                  @PluginAttr("bcc") final String bcc,
110                                                  @PluginAttr("from") final String from,
111                                                  @PluginAttr("replyTo") final String replyTo,
112                                                  @PluginAttr("subject") final String subject,
113                                                  @PluginAttr("smtpProtocol") final String smtpProtocol,
114                                                  @PluginAttr("smtpHost") final String smtpHost,
115                                                  @PluginAttr("smtpPort") final String smtpPortNum,
116                                                  @PluginAttr("smtpUsername") final String smtpUsername,
117                                                  @PluginAttr("smtpPassword") final String smtpPassword,
118                                                  @PluginAttr("smtpDebug") final String smtpDebug,
119                                                  @PluginAttr("bufferSize") final String bufferSizeNum,
120                                                  @PluginElement("layout") Layout<S> layout,
121                                                  @PluginElement("filter") Filter filter,
122                                                  @PluginAttr("suppressExceptions") final String suppressExceptions) {
123            if (name == null) {
124                LOGGER.error("No name provided for SMTPAppender");
125                return null;
126            }
127    
128            final boolean isHandleExceptions = suppressExceptions == null ? true : Boolean.valueOf(suppressExceptions);
129            final int smtpPort = smtpPortNum == null ? 0 : Integer.parseInt(smtpPortNum);
130            final boolean isSmtpDebug = smtpDebug == null ? false : Boolean.valueOf(smtpDebug);
131            final int bufferSize = bufferSizeNum == null ? DEFAULT_BUFFER_SIZE : Integer.valueOf(bufferSizeNum);
132    
133            if (layout == null) {
134                @SuppressWarnings({"unchecked", "UnnecessaryLocalVariable"})
135                Layout<S> l = (Layout<S>)HTMLLayout.createLayout(null, null, null, null, null, null);
136                layout = l;
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<S>(name, filter, layout, manager, isHandleExceptions);
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    }