/graylog2-server/src/main/java/org/graylog2/alerts/StaticEmailAlertSender.java
Java | 260 lines | 196 code | 43 blank | 21 comment | 39 complexity | 0ac80e214ee347a98197f0a3ec6ebaec MD5 | raw file
Possible License(s): GPL-3.0
- /**
- * This file is part of Graylog.
- *
- * Graylog is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Graylog is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Graylog. If not, see <http://www.gnu.org/licenses/>.
- */
- package org.graylog2.alerts;
- import com.google.common.base.Splitter;
- import com.google.common.base.Strings;
- import com.google.common.collect.ImmutableSet;
- import org.apache.commons.mail.DefaultAuthenticator;
- import org.apache.commons.mail.Email;
- import org.apache.commons.mail.EmailConstants;
- import org.apache.commons.mail.EmailException;
- import org.apache.commons.mail.SimpleEmail;
- import org.graylog2.configuration.EmailConfiguration;
- import org.graylog2.database.NotFoundException;
- import org.graylog2.notifications.Notification;
- import org.graylog2.notifications.NotificationService;
- import org.graylog2.plugin.Message;
- import org.graylog2.plugin.Tools;
- import org.graylog2.plugin.alarms.AlertCondition;
- import org.graylog2.plugin.alarms.transports.TransportConfigurationException;
- import org.graylog2.plugin.configuration.Configuration;
- import org.graylog2.plugin.database.users.User;
- import org.graylog2.plugin.streams.Stream;
- import org.graylog2.plugin.system.NodeId;
- import org.graylog2.shared.users.UserService;
- import org.graylog2.streams.StreamRuleService;
- import org.joda.time.DateTime;
- import org.slf4j.Logger;
- import org.slf4j.LoggerFactory;
- import javax.inject.Inject;
- import java.net.URI;
- import java.util.List;
- import java.util.Set;
- import static com.google.common.base.Strings.isNullOrEmpty;
- public class StaticEmailAlertSender implements AlertSender {
- private static final Logger LOG = LoggerFactory.getLogger(StaticEmailAlertSender.class);
- private final StreamRuleService streamRuleService;
- protected final EmailConfiguration configuration;
- private final UserService userService;
- private final NotificationService notificationService;
- private final NodeId nodeId;
- private Configuration pluginConfig;
- @Inject
- public StaticEmailAlertSender(EmailConfiguration configuration,
- StreamRuleService streamRuleService,
- UserService userService,
- NotificationService notificationService,
- NodeId nodeId) {
- this.configuration = configuration;
- this.streamRuleService = streamRuleService;
- this.userService = userService;
- this.notificationService = notificationService;
- this.nodeId = nodeId;
- }
- @Override
- public void initialize(org.graylog2.plugin.configuration.Configuration configuration) {
- this.pluginConfig = configuration;
- }
- @Override
- public void sendEmails(Stream stream, AlertCondition.CheckResult checkResult) throws TransportConfigurationException, EmailException {
- sendEmails(stream, checkResult, null);
- }
- private void sendEmail(String emailAddress, Stream stream, AlertCondition.CheckResult checkResult, List<Message> backlog) throws TransportConfigurationException, EmailException {
- LOG.debug("Sending mail to " + emailAddress);
- if(!configuration.isEnabled()) {
- throw new TransportConfigurationException("Email transport is not enabled in server configuration file!");
- }
- final Email email = new SimpleEmail();
- email.setCharset(EmailConstants.UTF_8);
- if (Strings.isNullOrEmpty(configuration.getHostname())) {
- throw new TransportConfigurationException("No hostname configured for email transport while trying to send alert email!");
- } else {
- email.setHostName(configuration.getHostname());
- }
- email.setSmtpPort(configuration.getPort());
- if (configuration.isUseSsl()) {
- email.setSslSmtpPort(Integer.toString(configuration.getPort()));
- }
- if(configuration.isUseAuth()) {
- email.setAuthenticator(new DefaultAuthenticator(
- Strings.nullToEmpty(configuration.getUsername()),
- Strings.nullToEmpty(configuration.getPassword())
- ));
- }
- email.setSSLOnConnect(configuration.isUseSsl());
- email.setStartTLSEnabled(configuration.isUseTls());
- if (pluginConfig != null && !Strings.isNullOrEmpty(pluginConfig.getString("sender"))) {
- email.setFrom(pluginConfig.getString("sender"));
- } else {
- email.setFrom(configuration.getFromEmail());
- }
- email.setSubject(buildSubject(stream, checkResult, backlog));
- email.setMsg(buildBody(stream, checkResult, backlog));
- email.addTo(emailAddress);
- email.send();
- }
- protected String buildSubject(Stream stream, AlertCondition.CheckResult checkResult, List<Message> backlog) {
- StringBuilder sb = new StringBuilder();
- final String subjectPrefix = configuration.getSubjectPrefix();
- if (!isNullOrEmpty(subjectPrefix)) {
- sb.append(subjectPrefix).append(" ");
- }
- sb.append("Graylog alert for stream: ").append(stream.getTitle());
- return sb.toString();
- }
- protected String buildBody(Stream stream, AlertCondition.CheckResult checkResult, List<Message> backlog) {
- StringBuilder sb = new StringBuilder();
- sb.append(checkResult.getResultDescription());
- sb.append("\n\n");
- sb.append("##########\n");
- sb.append("Date: ").append(Tools.nowUTC().toString()).append("\n");
- sb.append("Stream ID: ").append(stream.getId()).append("\n");
- sb.append("Stream title: ").append(stream.getTitle()).append("\n");
- sb.append("Stream URL: ").append(buildStreamDetailsURL(configuration.getWebInterfaceUri(), checkResult, stream)).append("\n");
- try {
- sb.append("Stream rules: ").append(streamRuleService.loadForStream(stream)).append("\n");
- } catch (NotFoundException e) {
- LOG.error("Unable to find stream rules for stream: " + stream.getId(), e);
- }
- sb.append("Alert triggered at: ").append(checkResult.getTriggeredAt()).append("\n");
- sb.append("Triggered condition: ").append(checkResult.getTriggeredCondition()).append("\n");
- sb.append("##########");
- if (backlog != null) {
- sb.append(buildBacklogSummary(backlog));
- }
- return sb.toString();
- }
- protected String buildStreamDetailsURL(URI baseUri, AlertCondition.CheckResult checkResult, Stream stream) {
- // Return an informational message if the web interface URL hasn't been set
- if (baseUri == null || isNullOrEmpty(baseUri.getHost())) {
- return "Please configure 'transport_email_web_interface_url' in your Graylog configuration file.";
- }
- int time = 5;
- if (checkResult.getTriggeredCondition().getParameters().get("time") != null) {
- time = (int) checkResult.getTriggeredCondition().getParameters().get("time");
- }
- DateTime dateAlertEnd = checkResult.getTriggeredAt();
- DateTime dateAlertStart = dateAlertEnd.minusMinutes(time);
- String alertStart = Tools.getISO8601String(dateAlertStart);
- String alertEnd = Tools.getISO8601String(dateAlertEnd);
- return baseUri + "/streams/" + stream.getId() + "/messages?rangetype=absolute&from=" + alertStart + "&to=" + alertEnd + "&q=*";
- }
- protected String buildBacklogSummary(List<Message> backlog) {
- if (backlog == null || backlog.isEmpty())
- return "";
- final StringBuilder sb = new StringBuilder();
- MessageFormatter messageFormatter = new MessageFormatter();
- sb.append("\n\nLast ");
- if (backlog.size() > 1)
- sb.append(backlog.size()).append(" relevant messages:\n");
- else
- sb.append("relevant message:\n");
- sb.append("======================\n\n");
- for (final Message message : backlog) {
- sb.append(messageFormatter.formatForMail(message));
- sb.append("\n");
- }
- return sb.toString();
- }
- @Override
- public void sendEmails(Stream stream, AlertCondition.CheckResult checkResult, List<Message> backlog) throws TransportConfigurationException, EmailException {
- if(!configuration.isEnabled()) {
- throw new TransportConfigurationException("Email transport is not enabled in server configuration file!");
- }
- if (stream.getAlertReceivers() == null || stream.getAlertReceivers().isEmpty()) {
- throw new RuntimeException("Stream [" + stream + "] has no alert receivers.");
- }
- final ImmutableSet.Builder<String> recipientsBuilder = ImmutableSet.builder();
- // Send emails to subscribed users.
- final List<String> userNames = stream.getAlertReceivers().get("users");
- if(userNames != null) {
- for (String username : userNames) {
- final User user = userService.load(username);
- if(user != null && !isNullOrEmpty(user.getEmail())) {
- // LDAP users might have multiple email addresses defined.
- // See: https://github.com/Graylog2/graylog2-server/issues/1439
- final Iterable<String> addresses = Splitter.on(",").omitEmptyStrings().trimResults().split(user.getEmail());
- recipientsBuilder.addAll(addresses);
- }
- }
- }
- // Send emails to directly subscribed email addresses.
- if(stream.getAlertReceivers().get("emails") != null) {
- for (String email : stream.getAlertReceivers().get("emails")) {
- if(!email.isEmpty()) {
- recipientsBuilder.add(email);
- }
- }
- }
- final Set<String> recipients = recipientsBuilder.build();
- if (recipients.size() == 0) {
- final Notification notification = notificationService.buildNow()
- .addNode(nodeId.toString())
- .addType(Notification.Type.GENERIC)
- .addSeverity(Notification.Severity.NORMAL)
- .addDetail("title", "Stream \"" + stream.getTitle() + "\" is alerted, but no recipients have been defined!")
- .addDetail("description", "To fix this, go to the alerting configuration of the stream and add at least one alert recipient.");
- notificationService.publishIfFirst(notification);
- }
- for (String email : recipients) {
- sendEmail(email, stream, checkResult, backlog);
- }
- }
- }