View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements. See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache license, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License. You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the license for the specific language governing permissions and
15   * limitations under the license.
16   */
17  
18  package org.apache.logging.log4j.core.appender;
19  
20  import java.io.Serializable;
21  
22  import org.apache.logging.log4j.core.Appender;
23  import org.apache.logging.log4j.core.Filter;
24  import org.apache.logging.log4j.core.Layout;
25  import org.apache.logging.log4j.core.LogEvent;
26  import org.apache.logging.log4j.core.config.Configuration;
27  import org.apache.logging.log4j.core.config.DefaultConfiguration;
28  import org.apache.logging.log4j.core.config.plugins.Plugin;
29  import org.apache.logging.log4j.core.config.plugins.PluginAttribute;
30  import org.apache.logging.log4j.core.config.plugins.PluginConfiguration;
31  import org.apache.logging.log4j.core.config.plugins.PluginElement;
32  import org.apache.logging.log4j.core.config.plugins.PluginFactory;
33  import org.apache.logging.log4j.core.filter.ThresholdFilter;
34  import org.apache.logging.log4j.core.layout.HtmlLayout;
35  import org.apache.logging.log4j.core.net.SmtpManager;
36  import org.apache.logging.log4j.core.util.Booleans;
37  
38  /**
39   * Send an e-mail when a specific logging event occurs, typically on errors or
40   * fatal errors.
41   *
42   * <p>
43   * The number of logging events delivered in this e-mail depend on the value of
44   * <b>BufferSize</b> option. The <code>SmtpAppender</code> keeps only the last
45   * <code>BufferSize</code> logging events in its cyclic buffer. This keeps
46   * memory requirements at a reasonable level while still delivering useful
47   * application context.
48   *
49   * By default, an email message will formatted as HTML. This can be modified by
50   * setting a layout for the appender.
51   *
52   * By default, an email message will be sent when an ERROR or higher severity
53   * message is appended. This can be modified by setting a filter for the
54   * appender.
55   */
56  @Plugin(name = "SMTP", category = "Core", elementType = Appender.ELEMENT_TYPE, printObject = true)
57  public final class SmtpAppender extends AbstractAppender {
58  
59      private static final int DEFAULT_BUFFER_SIZE = 512;
60  
61      /** The SMTP Manager */
62      private final SmtpManager manager;
63  
64      private SmtpAppender(final String name, final Filter filter, final Layout<? extends Serializable> layout, final SmtpManager manager,
65                           final boolean ignoreExceptions) {
66          super(name, filter, layout, ignoreExceptions);
67          this.manager = manager;
68      }
69  
70      /**
71       * Create a SmtpAppender.
72       *
73       * @param name
74       *            The name of the Appender.
75       * @param to
76       *            The comma-separated list of recipient email addresses.
77       * @param cc
78       *            The comma-separated list of CC email addresses.
79       * @param bcc
80       *            The comma-separated list of BCC email addresses.
81       * @param from
82       *            The email address of the sender.
83       * @param replyTo
84       *            The comma-separated list of reply-to email addresses.
85       * @param subject The subject of the email message.
86       * @param smtpProtocol The SMTP transport protocol (such as "smtps", defaults to "smtp").
87       * @param smtpHost
88       *            The SMTP hostname to send to.
89       * @param smtpPortStr
90       *            The SMTP port to send to.
91       * @param smtpUsername
92       *            The username required to authenticate against the SMTP server.
93       * @param smtpPassword
94       *            The password required to authenticate against the SMTP server.
95       * @param smtpDebug
96       *            Enable mail session debuging on STDOUT.
97       * @param bufferSizeStr
98       *            How many log events should be buffered for inclusion in the
99       *            message?
100      * @param layout
101      *            The layout to use (defaults to HtmlLayout).
102      * @param filter
103      *            The Filter or null (defaults to ThresholdFilter, level of
104      *            ERROR).
105      * @param ignore If {@code "true"} (default) exceptions encountered when appending events are logged; otherwise
106      *               they are propagated to the caller.
107      * @return The SmtpAppender.
108      */
109     @PluginFactory
110     public static SmtpAppender createAppender(
111             @PluginConfiguration final Configuration config,
112             @PluginAttribute("name") final String name,
113             @PluginAttribute("to") final String to,
114             @PluginAttribute("cc") final String cc,
115             @PluginAttribute("bcc") final String bcc,
116             @PluginAttribute("from") final String from,
117             @PluginAttribute("replyTo") final String replyTo,
118             @PluginAttribute("subject") final String subject,
119             @PluginAttribute("smtpProtocol") final String smtpProtocol,
120             @PluginAttribute("smtpHost") final String smtpHost,
121             @PluginAttribute("smtpPort") final String smtpPortStr,
122             @PluginAttribute("smtpUsername") final String smtpUsername,
123             @PluginAttribute("smtpPassword") final String smtpPassword,
124             @PluginAttribute("smtpDebug") final String smtpDebug,
125             @PluginAttribute("bufferSize") final String bufferSizeStr,
126             @PluginElement("Layout") Layout<? extends Serializable> layout,
127             @PluginElement("Filter") Filter filter,
128             @PluginAttribute("ignoreExceptions") final String ignore) {
129         if (name == null) {
130             LOGGER.error("No name provided for SmtpAppender");
131             return null;
132         }
133 
134         final boolean ignoreExceptions = Booleans.parseBoolean(ignore, true);
135         final int smtpPort = AbstractAppender.parseInt(smtpPortStr, 0);
136         final boolean isSmtpDebug = Boolean.parseBoolean(smtpDebug);
137         final int bufferSize = bufferSizeStr == null ? DEFAULT_BUFFER_SIZE : Integer.parseInt(bufferSizeStr);
138 
139         if (layout == null) {
140             layout = HtmlLayout.createDefaultLayout();
141         }
142         if (filter == null) {
143             filter = ThresholdFilter.createFilter(null, null, null);
144         }
145         final Configuration configuration = config != null ? config : new DefaultConfiguration();
146 
147         final SmtpManager manager = SmtpManager.getSmtpManager(configuration, to, cc, bcc, from, replyTo, subject, smtpProtocol,
148             smtpHost, smtpPort, smtpUsername, smtpPassword, isSmtpDebug, filter.toString(),  bufferSize);
149         if (manager == null) {
150             return null;
151         }
152 
153         return new SmtpAppender(name, filter, layout, manager, ignoreExceptions);
154     }
155 
156     /**
157      * Capture all events in CyclicBuffer.
158      * @param event The Log event.
159      * @return true if the event should be filtered.
160      */
161     @Override
162     public boolean isFiltered(final LogEvent event) {
163         final boolean filtered = super.isFiltered(event);
164         if (filtered) {
165             manager.add(event);
166         }
167         return filtered;
168     }
169 
170     /**
171      * Perform SmtpAppender specific appending actions, mainly adding the event
172      * to a cyclic buffer and checking if the event triggers an e-mail to be
173      * sent.
174      * @param event The Log event.
175      */
176     @Override
177     public void append(final LogEvent event) {
178         manager.sendEvents(getLayout(), event);
179     }
180 }