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