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-2015 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.opends.server.admin.server.ConfigurationChangeListener;
030import org.opends.server.admin.std.server.AlertHandlerCfg;
031import org.opends.server.admin.std.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
041/**
042 * This class implements a Directory Server alert handler that may be used to
043 * send administrative alerts via SMTP.
044 */
045public class SMTPAlertHandler
046       implements AlertHandler<SMTPAlertHandlerCfg>,
047                  ConfigurationChangeListener<SMTPAlertHandlerCfg>
048{
049  private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass();
050
051
052
053  /** The current configuration for this alert handler. */
054  private SMTPAlertHandlerCfg currentConfig;
055
056
057
058  /**
059   * Creates a new instance of this SMTP alert handler.
060   */
061  public SMTPAlertHandler()
062  {
063    super();
064
065    // All initialization should be done in the initializeAlertHandler method.
066  }
067
068
069
070  /** {@inheritDoc} */
071  public void initializeAlertHandler(SMTPAlertHandlerCfg configuration)
072       throws ConfigException, InitializationException
073  {
074    // Make sure that the Directory Server is configured with information about
075    // at least one SMTP server.
076    if (DirectoryServer.getMailServerPropertySets() == null ||
077        DirectoryServer.getMailServerPropertySets().isEmpty())
078    {
079      throw new ConfigException(ERR_SMTPALERTHANDLER_NO_SMTP_SERVERS.get());
080    }
081
082    configuration.addSMTPChangeListener(this);
083    currentConfig = configuration;
084  }
085
086
087
088  /** {@inheritDoc} */
089  public AlertHandlerCfg getAlertHandlerConfiguration()
090  {
091    return currentConfig;
092  }
093
094
095
096  /** {@inheritDoc} */
097  public boolean isConfigurationAcceptable(AlertHandlerCfg configuration,
098                                           List<LocalizableMessage> unacceptableReasons)
099  {
100    return true;
101  }
102
103
104
105  /** {@inheritDoc} */
106  public void finalizeAlertHandler()
107  {
108    // No action is required.
109  }
110
111
112
113  /** {@inheritDoc} */
114  public void sendAlertNotification(AlertGenerator generator, String alertType,
115                                    LocalizableMessage alertMessage)
116  {
117    SMTPAlertHandlerCfg cfg = currentConfig;
118
119    ArrayList<String> recipients = new ArrayList<>(cfg.getRecipientAddress());
120
121    String alertIDStr;
122    String alertMessageStr;
123    if (alertMessage != null) {
124      alertIDStr = alertMessage.resourceName() + "-" + alertMessage.ordinal();
125      alertMessageStr = alertMessage.toString();
126    } else {
127      alertIDStr = "-1";
128      alertMessageStr = "none";
129    }
130    String subject = replaceTokens(cfg.getMessageSubject(), alertType,
131                                   alertIDStr, alertMessageStr);
132
133    String body = replaceTokens(cfg.getMessageBody(), alertType, alertIDStr,
134                                alertMessageStr);
135
136    EMailMessage message = new EMailMessage(cfg.getSenderAddress(), recipients,
137                                            subject);
138
139    message.setBody(LocalizableMessage.raw(wrapText(body, 75)));
140
141    try
142    {
143      message.send();
144    }
145    catch (Exception e)
146    {
147      logger.traceException(e);
148      logger.error(WARN_SMTPALERTHANDLER_ERROR_SENDING_MESSAGE,
149          alertType, alertMessage, e.getLocalizedMessage());
150    }
151  }
152
153
154
155  /**
156   * Replaces any occurrences of special tokens in the given string with the
157   * appropriate value.  Tokens supported include:
158   * <UL>
159   *   <LI>%%alert-type%% -- Will be replaced with the alert type string</LI>
160   *   <LI>%%alert-id%% -- Will be replaced with the alert ID value</LI>
161   *   <LI>%%alert-message%% -- Will be replaced with the alert message</LI>
162   *   <LI>\n -- Will be replaced with an end-of-line character.
163   * </UL>
164   *
165   * @param  s             The string to be processed.
166   * @param  alertType     The string to use to replace the "%%alert-type%%"
167   *                       token.
168   * @param  alertID       The string to use to replace the "%%alert-id%%"
169   *                       token.
170   * @param  alertMessage  The string to use to replace the "%%alert-message%%"
171   *                       token.
172   *
173   * @return  A processed version of the provided string.
174   */
175  private String replaceTokens(String s, String alertType, String alertID,
176                               String alertMessage)
177  {
178    return s.replace("%%alert-type%%", alertType).
179             replace("%%alert-id%%", alertID).
180             replace("%%alert-message%%", alertMessage).
181             replace("\\n", "\r\n");
182  }
183
184
185
186  /** {@inheritDoc} */
187  public boolean isConfigurationChangeAcceptable(
188                      SMTPAlertHandlerCfg configuration,
189                      List<LocalizableMessage> unacceptableReasons)
190  {
191    return true;
192  }
193
194
195
196  /** {@inheritDoc} */
197  public ConfigChangeResult applyConfigurationChange(
198                                 SMTPAlertHandlerCfg configuration)
199  {
200    currentConfig = configuration;
201    return new ConfigChangeResult();
202  }
203}