001/*
002 * The contents of this file are subject to the terms of the Common Development and
003 * Distribution License (the License). You may not use this file except in compliance with the
004 * License.
005 *
006 * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the
007 * specific language governing permission and limitations under the License.
008 *
009 * When distributing Covered Software, include this CDDL Header Notice in each file and include
010 * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL
011 * Header, with the fields enclosed by brackets [] replaced by your own identifying
012 * information: "Portions Copyright [year] [name of copyright owner]".
013 *
014 * Copyright 2006-2009 Sun Microsystems, Inc.
015 * Portions Copyright 2014-2016 ForgeRock AS.
016 */
017package org.opends.server.extensions;
018
019import static org.opends.messages.ExtensionMessages.ERR_SMTPALERTHANDLER_NO_SMTP_SERVERS;
020import static org.opends.messages.ExtensionMessages.WARN_SMTPALERTHANDLER_ERROR_SENDING_MESSAGE;
021import static com.forgerock.opendj.cli.Utils.wrapText;
022
023import java.util.ArrayList;
024import java.util.List;
025
026import org.forgerock.i18n.LocalizableMessage;
027import org.forgerock.i18n.slf4j.LocalizedLogger;
028import org.forgerock.opendj.config.server.ConfigException;
029import org.forgerock.opendj.config.server.ConfigurationChangeListener;
030import org.forgerock.opendj.server.config.server.AlertHandlerCfg;
031import org.forgerock.opendj.server.config.server.SMTPAlertHandlerCfg;
032import org.opends.server.api.AlertGenerator;
033import org.opends.server.api.AlertHandler;
034import org.opends.server.core.DirectoryServer;
035import org.forgerock.opendj.config.server.ConfigChangeResult;
036import org.opends.server.types.InitializationException;
037import org.opends.server.util.EMailMessage;
038
039/**
040 * This class implements a Directory Server alert handler that may be used to
041 * send administrative alerts via SMTP.
042 */
043public class SMTPAlertHandler
044       implements AlertHandler<SMTPAlertHandlerCfg>,
045                  ConfigurationChangeListener<SMTPAlertHandlerCfg>
046{
047  private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass();
048
049  /** The current configuration for this alert handler. */
050  private SMTPAlertHandlerCfg currentConfig;
051
052  /** Creates a new instance of this SMTP alert handler. */
053  public SMTPAlertHandler()
054  {
055    super();
056
057    // All initialization should be done in the initializeAlertHandler method.
058  }
059
060  @Override
061  public void initializeAlertHandler(SMTPAlertHandlerCfg configuration)
062       throws ConfigException, InitializationException
063  {
064    // Make sure that the Directory Server is configured with information about
065    // at least one SMTP server.
066    if (DirectoryServer.getMailServerPropertySets() == null ||
067        DirectoryServer.getMailServerPropertySets().isEmpty())
068    {
069      throw new ConfigException(ERR_SMTPALERTHANDLER_NO_SMTP_SERVERS.get());
070    }
071
072    configuration.addSMTPChangeListener(this);
073    currentConfig = configuration;
074  }
075
076  @Override
077  public AlertHandlerCfg getAlertHandlerConfiguration()
078  {
079    return currentConfig;
080  }
081
082  @Override
083  public boolean isConfigurationAcceptable(AlertHandlerCfg configuration,
084                                           List<LocalizableMessage> unacceptableReasons)
085  {
086    return true;
087  }
088
089  @Override
090  public void finalizeAlertHandler()
091  {
092    // No action is required.
093  }
094
095  @Override
096  public void sendAlertNotification(AlertGenerator generator, String alertType,
097                                    LocalizableMessage alertMessage)
098  {
099    SMTPAlertHandlerCfg cfg = currentConfig;
100
101    ArrayList<String> recipients = new ArrayList<>(cfg.getRecipientAddress());
102
103    String alertIDStr;
104    String alertMessageStr;
105    if (alertMessage != null) {
106      alertIDStr = alertMessage.resourceName() + "-" + alertMessage.ordinal();
107      alertMessageStr = alertMessage.toString();
108    } else {
109      alertIDStr = "-1";
110      alertMessageStr = "none";
111    }
112    String subject = replaceTokens(cfg.getMessageSubject(), alertType,
113                                   alertIDStr, alertMessageStr);
114
115    String body = replaceTokens(cfg.getMessageBody(), alertType, alertIDStr,
116                                alertMessageStr);
117
118    EMailMessage message = new EMailMessage(cfg.getSenderAddress(), recipients,
119                                            subject);
120
121    message.setBody(LocalizableMessage.raw(wrapText(body, 75)));
122
123    try
124    {
125      message.send();
126    }
127    catch (Exception e)
128    {
129      logger.traceException(e);
130      logger.error(WARN_SMTPALERTHANDLER_ERROR_SENDING_MESSAGE,
131          alertType, alertMessage, e.getLocalizedMessage());
132    }
133  }
134
135  /**
136   * Replaces any occurrences of special tokens in the given string with the
137   * appropriate value.  Tokens supported include:
138   * <UL>
139   *   <LI>%%alert-type%% -- Will be replaced with the alert type string</LI>
140   *   <LI>%%alert-id%% -- Will be replaced with the alert ID value</LI>
141   *   <LI>%%alert-message%% -- Will be replaced with the alert message</LI>
142   *   <LI>\n -- Will be replaced with an end-of-line character.
143   * </UL>
144   *
145   * @param  s             The string to be processed.
146   * @param  alertType     The string to use to replace the "%%alert-type%%"
147   *                       token.
148   * @param  alertID       The string to use to replace the "%%alert-id%%"
149   *                       token.
150   * @param  alertMessage  The string to use to replace the "%%alert-message%%"
151   *                       token.
152   *
153   * @return  A processed version of the provided string.
154   */
155  private String replaceTokens(String s, String alertType, String alertID,
156                               String alertMessage)
157  {
158    return s.replace("%%alert-type%%", alertType).
159             replace("%%alert-id%%", alertID).
160             replace("%%alert-message%%", alertMessage).
161             replace("\\n", "\r\n");
162  }
163
164  @Override
165  public boolean isConfigurationChangeAcceptable(
166                      SMTPAlertHandlerCfg configuration,
167                      List<LocalizableMessage> unacceptableReasons)
168  {
169    return true;
170  }
171
172  @Override
173  public ConfigChangeResult applyConfigurationChange(
174                                 SMTPAlertHandlerCfg configuration)
175  {
176    currentConfig = configuration;
177    return new ConfigChangeResult();
178  }
179}