From 3715af423d1f2510ed9c4b61b0f31060f2346a4e Mon Sep 17 00:00:00 2001
From: neil_a_wilson <neil_a_wilson@localhost>
Date: Fri, 20 Jul 2007 20:04:30 +0000
Subject: [PATCH] Add a general framework for OpenDS to send e-mail messages, and add an SMTP alert handler that can be used to send e-mail messages in response to administrative alerts generated within the server.

---
 opendj-sdk/opends/src/server/org/opends/server/extensions/SMTPAlertHandler.java                |  231 +++++++++++++++++++++
 opendj-sdk/opends/src/admin/defn/org/opends/server/admin/std/GlobalConfiguration.xml           |   26 ++
 opendj-sdk/opends/src/server/org/opends/server/core/DirectoryServer.java                       |   37 +--
 opendj-sdk/opends/src/server/org/opends/server/messages/ConfigMessages.java                    |   16 +
 opendj-sdk/opends/resource/config/config.ldif                                                  |   12 +
 opendj-sdk/opends/src/server/org/opends/server/util/EMailMessage.java                          |    9 
 opendj-sdk/opends/src/server/org/opends/server/messages/ExtensionsMessages.java                |   32 ++
 opendj-sdk/opends/src/server/org/opends/server/util/ServerConstants.java                       |   16 +
 opendj-sdk/opends/src/server/org/opends/server/core/CoreConfigManager.java                     |  112 ++++++++++
 opendj-sdk/opends/resource/schema/02-config.ldif                                               |   27 ++
 opendj-sdk/opends/src/admin/defn/org/opends/server/admin/std/SMTPAlertHandlerConfiguration.xml |  133 ++++++++++++
 11 files changed, 617 insertions(+), 34 deletions(-)

diff --git a/opendj-sdk/opends/resource/config/config.ldif b/opendj-sdk/opends/resource/config/config.ldif
index 003d635..898737d 100644
--- a/opendj-sdk/opends/resource/config/config.ldif
+++ b/opendj-sdk/opends/resource/config/config.ldif
@@ -95,7 +95,19 @@
 objectClass: ds-cfg-alert-handler
 cn: JMX Alert Handler
 ds-cfg-alert-handler-class: org.opends.server.extensions.JMXAlertHandler
+ds-cfg-alert-handler-enabled: true
+
+dn: cn=SMTP Alert Handler,cn=Alert Handlers,cn=config
+objectClass: top
+objectClass: ds-cfg-alert-handler
+objectClass: ds-cfg-smtp-alert-handler
+cn: JMX Alert Handler
+ds-cfg-alert-handler-class: org.opends.server.extensions.SMTPAlertHandler
 ds-cfg-alert-handler-enabled: false
+ds-cfg-sender-address: opends-alerts@example.com
+ds-cfg-recipient-address: directory-administrators@example.com
+ds-cfg-message-subject: OpenDS Alert %%alert-type%%
+ds-cfg-message-body: Alert Type:  %%alert-type%%\n\nAlert ID:  %%alert-id%%\n\nAlert Message:  %%alert-message%%
 
 dn: cn=Backends,cn=config
 objectClass: top
diff --git a/opendj-sdk/opends/resource/schema/02-config.ldif b/opendj-sdk/opends/resource/schema/02-config.ldif
index 106a7ed..a510e36 100644
--- a/opendj-sdk/opends/resource/schema/02-config.ldif
+++ b/opendj-sdk/opends/resource/schema/02-config.ldif
@@ -1477,12 +1477,26 @@
   X-ORIGIN 'OpenDS Directory Server' )
 attributeTypes: ( 1.3.6.1.4.1.26027.1.1.443
   NAME 'ds-cfg-state-update-failure-policy'
-  SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'OpenDS Directory Server' )
+  SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE
+  X-ORIGIN 'OpenDS Directory Server' )
 attributeTypes: ( 1.3.6.1.4.1.26027.1.1.444
   NAME 'ds-cfg-password-history-count' SYNTAX 1.3.6.1.4.1.1466.115.121.1.27
-  X-ORIGIN 'OpenDS Directory Server' )
+  SINGLE-VALUE X-ORIGIN 'OpenDS Directory Server' )
 attributeTypes: ( 1.3.6.1.4.1.26027.1.1.445
   NAME 'ds-cfg-password-history-duration' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
+  SINGLE-VALUE X-ORIGIN 'OpenDS Directory Server' )
+attributeTypes: ( 1.3.6.1.4.1.26027.1.1.446 NAME 'ds-cfg-smtp-server'
+  SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'OpenDS Directory Server' )
+attributeTypes: ( 1.3.6.1.4.1.26027.1.1.447 NAME 'ds-cfg-sender-address'
+  SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE
+  X-ORIGIN 'OpenDS Directory Server' )
+attributeTypes: ( 1.3.6.1.4.1.26027.1.1.448 NAME 'ds-cfg-recipient-address'
+  SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'OpenDS Directory Server' )
+attributeTypes: ( 1.3.6.1.4.1.26027.1.1.449 NAME 'ds-cfg-message-subject'
+  SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE
+  X-ORIGIN 'OpenDS Directory Server' )
+attributeTypes: ( 1.3.6.1.4.1.26027.1.1.450 NAME 'ds-cfg-message-body'
+  SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE
   X-ORIGIN 'OpenDS Directory Server' )
 objectClasses: ( 1.3.6.1.4.1.26027.1.2.1
   NAME 'ds-cfg-access-control-handler' SUP top STRUCTURAL
@@ -1697,8 +1711,8 @@
   ds-cfg-notify-abandoned-operations $ ds-cfg-size-limit $ ds-cfg-time-limit $
   ds-cfg-proxied-authorization-identity-mapper-dn $ ds-cfg-writability-mode $
   ds-cfg-reject-unauthenticated-requests  $
-  ds-cfg-bind-with-dn-requires-password $ ds-cfg-lookthrough-limit )
-  X-ORIGIN 'OpenDS Directory Server' )
+  ds-cfg-bind-with-dn-requires-password $ ds-cfg-lookthrough-limit $
+  ds-cfg-smtp-server ) X-ORIGIN 'OpenDS Directory Server' )
 objectClasses: ( 1.3.6.1.4.1.26027.1.2.41 NAME 'ds-cfg-root-dn' SUP top
   AUXILIARY MAY ds-cfg-alternate-bind-dn X-ORIGIN 'OpenDS Directory Server' )
 objectClasses: ( 1.3.6.1.4.1.26027.1.2.42 NAME 'ds-cfg-root-dse'
@@ -2089,4 +2103,9 @@
   MAY ( ds-cfg-default-user-password-storage-scheme $
   ds-cfg-default-auth-password-storage-scheme )
   X-ORIGIN 'OpenDS Directory Server' )
+objectClasses: ( 1.3.6.1.4.1.26027.1.2.118
+  NAME 'ds-cfg-smtp-alert-handler' SUP ds-cfg-alert-handler STRUCTURAL
+  MUST ( ds-cfg-sender-address $ ds-cfg-recipient-address $
+  ds-cfg-message-subject $ ds-cfg-message-body )
+  X-ORIGIN 'OpenDS Directory Server' )
 
diff --git a/opendj-sdk/opends/src/admin/defn/org/opends/server/admin/std/GlobalConfiguration.xml b/opendj-sdk/opends/src/admin/defn/org/opends/server/admin/std/GlobalConfiguration.xml
index c59e367..f9901c5 100644
--- a/opendj-sdk/opends/src/admin/defn/org/opends/server/admin/std/GlobalConfiguration.xml
+++ b/opendj-sdk/opends/src/admin/defn/org/opends/server/admin/std/GlobalConfiguration.xml
@@ -475,5 +475,31 @@
     </adm:profile>
   </adm:property>
 
+  <adm:property name="smtp-server" mandatory="false" multi-valued="true">
+    <adm:synopsis>
+      Specifies the address (and optional port number) for a mail server that
+      can be used to send e-mail messages via SMTP.  It may be an IP address or
+      resolvable hostname, optionally followed by a colon and a port number.
+    </adm:synopsis>
+    <adm:default-behavior>
+      <adm:alias>
+        <adm:synopsis>
+          If no values are defined, then it will not be possible to take
+          advantage of server features that may provide thea bility to send
+          e-mail via SMTP.
+        </adm:synopsis>
+      </adm:alias>
+    </adm:default-behavior>
+    <adm:syntax>
+      <adm:string />
+    </adm:syntax>
+    <adm:profile name="ldap">
+      <ldap:attribute>
+        <ldap:oid>1.3.6.1.4.1.26027.1.1.446</ldap:oid>
+        <ldap:name>ds-cfg-smtp-server</ldap:name>
+      </ldap:attribute>
+    </adm:profile>
+  </adm:property>
+
 </adm:managed-object>
 
diff --git a/opendj-sdk/opends/src/admin/defn/org/opends/server/admin/std/SMTPAlertHandlerConfiguration.xml b/opendj-sdk/opends/src/admin/defn/org/opends/server/admin/std/SMTPAlertHandlerConfiguration.xml
new file mode 100644
index 0000000..085a0e3
--- /dev/null
+++ b/opendj-sdk/opends/src/admin/defn/org/opends/server/admin/std/SMTPAlertHandlerConfiguration.xml
@@ -0,0 +1,133 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+! CDDL HEADER START
+!
+! The contents of this file are subject to the terms of the
+! Common Development and Distribution License, Version 1.0 only
+! (the "License").  You may not use this file except in compliance
+! with the License.
+!
+! You can obtain a copy of the license at
+! trunk/opends/resource/legal-notices/OpenDS.LICENSE
+! or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+! See the License for the specific language governing permissions
+! and limitations under the License.
+!
+! When distributing Covered Code, include this CDDL HEADER in each
+! file and include the License file at
+! trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+! add the following below this CDDL HEADER, with the fields enclosed
+! by brackets "[]" replaced with your own identifying information:
+!      Portions Copyright [yyyy] [name of copyright owner]
+!
+! CDDL HEADER END
+!
+!
+!      Portions Copyright 2007 Sun Microsystems, Inc.
+! -->
+
+<adm:managed-object name="smtp-alert-handler" plural-name="smtp-alert-handlers"
+  package="org.opends.server.admin.std" extends="alert-handler"
+  xmlns:adm="http://www.opends.org/admin"
+  xmlns:ldap="http://www.opends.org/admin-ldap">
+
+  <adm:synopsis>
+    The
+    <adm:user-friendly-name />
+    may be used to send e-mail messages to notify administrators of significant
+    events that occur within the server.
+  </adm:synopsis>
+
+  <adm:profile name="ldap">
+    <ldap:object-class>
+      <ldap:oid>1.3.6.1.4.1.26027.1.2.118</ldap:oid>
+      <ldap:name>ds-cfg-smtp-alert-handler</ldap:name>
+      <ldap:superior>ds-cfg-alert-handler</ldap:superior>
+    </ldap:object-class>
+  </adm:profile>
+
+  <adm:property-override name="alert-handler-class">
+    <adm:default-behavior>
+      <adm:defined>
+        <adm:value>
+          org.opends.server.extensions.SMTPAlertHandler
+        </adm:value>
+      </adm:defined>
+    </adm:default-behavior>
+  </adm:property-override>
+
+  <adm:property name="sender-address" mandatory="true" multi-valued="false">
+    <adm:synopsis>
+      Specifies the e-mail address to use as the sender for messages generated
+      by this alert handler.
+    </adm:synopsis>
+    <adm:syntax>
+      <adm:string />
+    </adm:syntax>
+    <adm:profile name="ldap">
+      <ldap:attribute>
+        <ldap:oid>1.3.6.1.4.1.26027.1.1.447</ldap:oid>
+        <ldap:name>ds-cfg-sender-address</ldap:name>
+      </ldap:attribute>
+    </adm:profile>
+  </adm:property>
+
+  <adm:property name="recipient-address" mandatory="true" multi-valued="true">
+    <adm:synopsis>
+      Specifies an e-mail address to which the messages should be sent.
+      Multiple values may be provided if there should be more than one
+      recipient.
+    </adm:synopsis>
+    <adm:syntax>
+      <adm:string />
+    </adm:syntax>
+    <adm:profile name="ldap">
+      <ldap:attribute>
+        <ldap:oid>1.3.6.1.4.1.26027.1.1.448</ldap:oid>
+        <ldap:name>ds-cfg-recipient-address</ldap:name>
+      </ldap:attribute>
+    </adm:profile>
+  </adm:property>
+
+  <adm:property name="message-subject" mandatory="true" multi-valued="false">
+    <adm:synopsis>
+      Specifies the subject that should be used for e-mail messsages generated
+      by this alert handler.  The token "%%alert-type%%" will be dynamically
+      replaced with the alert type string.  The token "%%alert-id%%" will be
+      dynamically replaced with the alert ID value.  The token
+      "%%alert-message%%" will be dynamically replaced with the alert message.
+      The token "\n" will be replaced with an end-of-line marker.
+    </adm:synopsis>
+    <adm:syntax>
+      <adm:string />
+    </adm:syntax>
+    <adm:profile name="ldap">
+      <ldap:attribute>
+        <ldap:oid>1.3.6.1.4.1.26027.1.1.449</ldap:oid>
+        <ldap:name>ds-cfg-message-subject</ldap:name>
+      </ldap:attribute>
+    </adm:profile>
+  </adm:property>
+
+  <adm:property name="message-body" mandatory="true" multi-valued="false">
+    <adm:synopsis>
+      Specifies the body that should be used for e-mail messsages generated
+      by this alert handler.  The token "%%alert-type%%" will be dynamically
+      replaced with the alert type string.  The token "%%alert-id%%" will be
+      dynamically replaced with the alert ID value.  The token
+      "%%alert-message%%" will be dynamically replaced with the alert message.
+      The token "\n" will be replaced with an end-of-line marker.
+    </adm:synopsis>
+    <adm:syntax>
+      <adm:string />
+    </adm:syntax>
+    <adm:profile name="ldap">
+      <ldap:attribute>
+        <ldap:oid>1.3.6.1.4.1.26027.1.1.450</ldap:oid>
+        <ldap:name>ds-cfg-message-body</ldap:name>
+      </ldap:attribute>
+    </adm:profile>
+  </adm:property>
+
+</adm:managed-object>
+
diff --git a/opendj-sdk/opends/src/server/org/opends/server/core/CoreConfigManager.java b/opendj-sdk/opends/src/server/org/opends/server/core/CoreConfigManager.java
index 4604244..1ac0fcf 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/core/CoreConfigManager.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/core/CoreConfigManager.java
@@ -30,6 +30,8 @@
 
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Properties;
+import java.util.Set;
 
 import org.opends.server.admin.server.ConfigurationChangeListener;
 import org.opends.server.admin.std.server.GlobalCfg;
@@ -46,6 +48,7 @@
 
 import static org.opends.server.messages.ConfigMessages.*;
 import static org.opends.server.messages.MessageHandler.*;
+import static org.opends.server.util.ServerConstants.*;
 
 
 
@@ -88,10 +91,50 @@
          managementContext.getRootConfiguration();
 
 
-    // Get the global configuration, register with it as a change listener, and
-    // apply the configuration to the server.
+    // Get the global configuration and register with it as a change listener.
     GlobalCfg globalConfig = rootConfiguration.getGlobalConfiguration();
     globalConfig.addChangeListener(this);
+
+
+    // If there are any STMP servers specified, then make sure that if the value
+    // contains a colon that the portion after it is an integer between 1 and
+    // 65535.
+    Set<String> smtpServers = globalConfig.getSMTPServer();
+    if (smtpServers != null)
+    {
+      for (String server : smtpServers)
+      {
+        int colonPos = server.indexOf(':');
+        if ((colonPos == 0) || (colonPos == (server.length()-1)))
+        {
+          int    msgID   = MSGID_CONFIG_CORE_INVALID_SMTP_SERVER;
+          String message = getMessage(msgID, server);
+          throw new ConfigException(msgID, message);
+        }
+        else if (colonPos > 0)
+        {
+          try
+          {
+            int port = Integer.parseInt(server.substring(colonPos+1));
+            if ((port < 1) || (port > 65535))
+            {
+              int    msgID   = MSGID_CONFIG_CORE_INVALID_SMTP_SERVER;
+              String message = getMessage(msgID, server);
+              throw new ConfigException(msgID, message);
+            }
+          }
+          catch (Exception e)
+          {
+            int    msgID   = MSGID_CONFIG_CORE_INVALID_SMTP_SERVER;
+            String message = getMessage(msgID, server);
+            throw new ConfigException(msgID, message, e);
+          }
+        }
+      }
+    }
+
+
+    // Apply the configuration to the server.
     applyGlobalConfiguration(globalConfig);
   }
 
@@ -180,6 +223,34 @@
          globalConfig.isBindWithDNRequiresPassword());
 
     DirectoryServer.setLookthroughLimit(globalConfig.getLookthroughLimit());
+
+
+    ArrayList<Properties> mailServerProperties = new ArrayList<Properties>();
+    Set<String> smtpServers = globalConfig.getSMTPServer();
+    if ((smtpServers != null) && (! smtpServers.isEmpty()))
+    {
+      for (String smtpServer : smtpServers)
+      {
+        int colonPos = smtpServer.indexOf(':');
+        if (colonPos > 0)
+        {
+          String smtpHost = smtpServer.substring(0, colonPos);
+          String smtpPort = smtpServer.substring(colonPos+1);
+
+          Properties properties = new Properties();
+          properties.setProperty(SMTP_PROPERTY_HOST, smtpHost);
+          properties.setProperty(SMTP_PROPERTY_PORT, smtpPort);
+          mailServerProperties.add(properties);
+        }
+        else
+        {
+          Properties properties = new Properties();
+          properties.setProperty(SMTP_PROPERTY_HOST, smtpServer);
+          mailServerProperties.add(properties);
+        }
+      }
+    }
+    DirectoryServer.setMailServerPropertySets(mailServerProperties);
   }
 
 
@@ -217,6 +288,43 @@
       configAcceptable = false;
     }
 
+    Set<String> smtpServers = configuration.getSMTPServer();
+    if (smtpServers != null)
+    {
+      for (String server : smtpServers)
+      {
+        int colonPos = server.indexOf(':');
+        if ((colonPos == 0) || (colonPos == (server.length()-1)))
+        {
+          int    msgID   = MSGID_CONFIG_CORE_INVALID_SMTP_SERVER;
+          String message = getMessage(msgID, server);
+          unacceptableReasons.add(message);
+          configAcceptable = false;
+        }
+        else if (colonPos > 0)
+        {
+          try
+          {
+            int port = Integer.parseInt(server.substring(colonPos+1));
+            if ((port < 1) || (port > 65535))
+            {
+              int    msgID   = MSGID_CONFIG_CORE_INVALID_SMTP_SERVER;
+              String message = getMessage(msgID, server);
+              unacceptableReasons.add(message);
+              configAcceptable = false;
+            }
+          }
+          catch (Exception e)
+          {
+            int    msgID   = MSGID_CONFIG_CORE_INVALID_SMTP_SERVER;
+            String message = getMessage(msgID, server);
+            unacceptableReasons.add(message);
+            configAcceptable = false;
+          }
+        }
+      }
+    }
+
     return configAcceptable;
   }
 
diff --git a/opendj-sdk/opends/src/server/org/opends/server/core/DirectoryServer.java b/opendj-sdk/opends/src/server/org/opends/server/core/DirectoryServer.java
index d419e8a..10e3e66 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/core/DirectoryServer.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/core/DirectoryServer.java
@@ -361,9 +361,6 @@
   // The set of import task listeners registered with the Directory Server.
   private CopyOnWriteArrayList<ImportTaskListener> importTaskListeners;
 
-  // The sets of mail server properties
-  private CopyOnWriteArrayList<Properties> mailServerPropertySets;
-
   // The set of persistent searches registered with the Directory Server.
   private CopyOnWriteArrayList<PersistentSearch> persistentSearches;
 
@@ -443,6 +440,9 @@
   // The set of connections that are currently established.
   private LinkedHashSet<ClientConnection> establishedConnections;
 
+  // The sets of mail server properties
+  private List<Properties> mailServerPropertySets;
+
   // The set of schema changes made by editing the schema configuration files
   // with the server offline.
   private List<Modification> offlineSchemaChanges;
@@ -1071,11 +1071,6 @@
 
 
 
-      // Initialize information about the mail servers for use by the Directory
-      // Server.
-      initializeMailServerPropertySets();
-
-
       // Initialize the server alert handlers.
       initializeAlertHandlers();
 
@@ -2045,25 +2040,17 @@
 
 
   /**
-   * Initializes the set of properties to use to connect to mail servers for
-   * sending messages.
+   * Specifies the set of mail server properties that should be used for SMTP
+   * communication.
    *
-   * @throws  ConfigException  If there is a configuration problem with any of
-   *                           the mail server entries.
-   *
-   * @throws  InitializationException  If a problem occurs while initializing
-   *                                   the mail server property sets that is not
-   *                                   related to the server configuration.
+   * @param  mailServerPropertySets  A list of {@code Properties} objects that
+   *                                 provide information that can be used to
+   *                                 communicate with SMTP servers.
    */
-  public void initializeMailServerPropertySets()
-         throws ConfigException, InitializationException
+  public static void setMailServerPropertySets(List<Properties>
+                                                    mailServerPropertySets)
   {
-    mailServerPropertySets = new CopyOnWriteArrayList<Properties>();
-
-    // FIXME -- Actually read the information from the config handler.
-    Properties defaultProperties = new Properties();
-    defaultProperties.setProperty("mail.smtp.host", "127.0.0.1");
-    mailServerPropertySets.add(defaultProperties);
+    directoryServer.mailServerPropertySets = mailServerPropertySets;
   }
 
 
@@ -2075,7 +2062,7 @@
    * @return  The sets of information about the mail servers configured for use
    *          by the Directory Server.
    */
-  public static CopyOnWriteArrayList<Properties> getMailServerPropertySets()
+  public static List<Properties> getMailServerPropertySets()
   {
     return directoryServer.mailServerPropertySets;
   }
diff --git a/opendj-sdk/opends/src/server/org/opends/server/extensions/SMTPAlertHandler.java b/opendj-sdk/opends/src/server/org/opends/server/extensions/SMTPAlertHandler.java
new file mode 100644
index 0000000..45fa188
--- /dev/null
+++ b/opendj-sdk/opends/src/server/org/opends/server/extensions/SMTPAlertHandler.java
@@ -0,0 +1,231 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Portions Copyright 2006-2007 Sun Microsystems, Inc.
+ */
+package org.opends.server.extensions;
+
+
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.opends.server.admin.server.ConfigurationChangeListener;
+import org.opends.server.admin.std.server.AlertHandlerCfg;
+import org.opends.server.admin.std.server.SMTPAlertHandlerCfg;
+import org.opends.server.api.AlertGenerator;
+import org.opends.server.api.AlertHandler;
+import org.opends.server.core.DirectoryServer;
+import org.opends.server.config.ConfigException;
+import org.opends.server.loggers.debug.DebugTracer;
+import org.opends.server.types.ConfigChangeResult;
+import org.opends.server.types.DebugLogLevel;
+import org.opends.server.types.ErrorLogCategory;
+import org.opends.server.types.ErrorLogSeverity;
+import org.opends.server.types.InitializationException;
+import org.opends.server.types.ResultCode;
+import org.opends.server.util.EMailMessage;
+
+import static org.opends.server.loggers.ErrorLogger.*;
+import static org.opends.server.loggers.debug.DebugLogger.*;
+import static org.opends.server.messages.ExtensionsMessages.*;
+import static org.opends.server.messages.MessageHandler.*;
+import static org.opends.server.util.StaticUtils.*;
+
+
+
+/**
+ * This class implements a Directory Server alert handler that may be used to
+ * send administrative alerts via SMTP.
+ */
+public class SMTPAlertHandler
+       implements AlertHandler<SMTPAlertHandlerCfg>,
+                  ConfigurationChangeListener<SMTPAlertHandlerCfg>
+{
+  /**
+   * The tracer object for the debug logger.
+   */
+  private static final DebugTracer TRACER = getTracer();
+
+
+
+  // The current configuration for this alert handler.
+  private SMTPAlertHandlerCfg currentConfig;
+
+
+
+  /**
+   * Creates a new instance of this SMTP alert handler.
+   */
+  public SMTPAlertHandler()
+  {
+    super();
+
+    // All initialization should be done in the initializeAlertHandler method.
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public void initializeAlertHandler(SMTPAlertHandlerCfg configuration)
+       throws ConfigException, InitializationException
+  {
+    // Make sure that the Directory Server is configured with information about
+    // at least one SMTP server.
+    if ((DirectoryServer.getMailServerPropertySets() == null) ||
+        DirectoryServer.getMailServerPropertySets().isEmpty())
+    {
+      int    msgID   = MSGID_SMTPALERTHANDLER_NO_SMTP_SERVERS;
+      String message = getMessage(msgID);
+      throw new ConfigException(msgID, message);
+    }
+
+    configuration.addSMTPChangeListener(this);
+    currentConfig = configuration;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public boolean isConfigurationAcceptable(AlertHandlerCfg configuration,
+                                           List<String> unacceptableReasons)
+  {
+    return true;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public void finalizeAlertHandler()
+  {
+    // No action is required.
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public void sendAlertNotification(AlertGenerator generator, String alertType,
+                                    int alertID, String alertMessage)
+  {
+    SMTPAlertHandlerCfg cfg = currentConfig;
+
+    ArrayList<String> recipients =
+         new ArrayList<String>(cfg.getRecipientAddress());
+
+    String alertIDStr = String.valueOf(alertID);
+    String subject = replaceTokens(cfg.getMessageSubject(), alertType,
+                                   alertIDStr, alertMessage);
+
+    String body = replaceTokens(cfg.getMessageBody(), alertType, alertIDStr,
+                                alertMessage);
+
+    EMailMessage message = new EMailMessage(cfg.getSenderAddress(), recipients,
+                                            subject);
+
+    message.setBody(wrapText(body, 75));
+
+    try
+    {
+      message.send();
+    }
+    catch (Exception e)
+    {
+      if (debugEnabled())
+      {
+        TRACER.debugCaught(DebugLogLevel.ERROR, e);
+      }
+
+      int msgID = MSGID_SMTPALERTHANDLER_ERROR_SENDING_MESSAGE;
+      String msg = getMessage(msgID, alertType, alertMessage,
+                              stackTraceToSingleLineString(e));
+      logError(ErrorLogCategory.CORE_SERVER, ErrorLogSeverity.SEVERE_WARNING,
+               msg, msgID);
+    }
+  }
+
+
+
+  /**
+   * Replaces any occurrences of special tokens in the given string with the
+   * appropriate value.  Tokens supported include:
+   * <UL>
+   *   <LI>%%alert-type%% -- Will be replaced with the alert type string</LI>
+   *   <LI>%%alert-id%% -- Will be replaced with the alert ID value</LI>
+   *   <LI>%%alert-message%% -- Will be replaced with the alert message</LI>
+   *   <LI>\n -- Will be replaced with an end-of-line character.
+   * </UL>
+   *
+   * @param  s             The string to be processed.
+   * @param  alertType     The string to use to replace the "%%alert-type%%"
+   *                       token.
+   * @param  alertID       The string to use to replace the "%%alert-id%%"
+   *                       token.
+   * @param  alertMessage  The string to use to replace the "%%alert-message%%"
+   *                       token.
+   *
+   * @return  A processed version of the provided string.
+   */
+  private String replaceTokens(String s, String alertType, String alertID,
+                               String alertMessage)
+  {
+    return s.replace("%%alert-type%%", alertType).
+             replace("%%alert-id%%", alertID).
+             replace("%%alert-message%%", alertMessage).
+             replace("\\n", "\r\n");
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public boolean isConfigurationChangeAcceptable(
+                      SMTPAlertHandlerCfg configuration,
+                      List<String> unacceptableReasons)
+  {
+    return true;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public ConfigChangeResult applyConfigurationChange(
+                                 SMTPAlertHandlerCfg configuration)
+  {
+    currentConfig = configuration;
+
+    return new ConfigChangeResult(ResultCode.SUCCESS, false);
+  }
+}
+
diff --git a/opendj-sdk/opends/src/server/org/opends/server/messages/ConfigMessages.java b/opendj-sdk/opends/src/server/org/opends/server/messages/ConfigMessages.java
index daedce5..87be0ee 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/messages/ConfigMessages.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/messages/ConfigMessages.java
@@ -7057,6 +7057,16 @@
 
 
   /**
+   * The message ID for the message that will be used if an SMTP server value is
+   * not properly-formed.  This takes a single argument, which is the invalid
+   * server value.
+   */
+  public static final int MSGID_CONFIG_CORE_INVALID_SMTP_SERVER =
+       CATEGORY_MASK_CONFIG | SEVERITY_MASK_SEVERE_ERROR | 697;
+
+
+
+  /**
    * Associates a set of generic messages with the message IDs defined in this
    * class.
    */
@@ -7649,6 +7659,12 @@
                     "Configuration entry %s has an invalid value for " +
                     "configuration attribute " + ATTR_NOTIFY_ABANDONED_OPS +
                     " (it should be a Boolean value of true or false):  %s");
+    registerMessage(MSGID_CONFIG_CORE_INVALID_SMTP_SERVER,
+                    "The provided SMTP server value '%s' is invalid.  An " +
+                    "SMTP server value must have an IP address or a " +
+                    "resolvable name, and it may optionally be followed by a " +
+                    "colon and an integer value between 1 and 65535 to " +
+                    "specify the server port number");
     registerMessage(MSGID_CONFIG_CORE_INVALID_PROXY_MAPPER_DN,
                     "Configuration entry %s has an invalid value for " +
                     "configuration attribute " + ATTR_PROXY_MAPPER_DN +
diff --git a/opendj-sdk/opends/src/server/org/opends/server/messages/ExtensionsMessages.java b/opendj-sdk/opends/src/server/org/opends/server/messages/ExtensionsMessages.java
index e4006f6..c8cdadb 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/messages/ExtensionsMessages.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/messages/ExtensionsMessages.java
@@ -5512,6 +5512,27 @@
 
 
   /**
+   * The message ID for the message that will be used if the Directory Server is
+   * not configured with information about any SMTP servers.  This does not take
+   * any configuration arguments.
+   */
+  public static final int MSGID_SMTPALERTHANDLER_NO_SMTP_SERVERS =
+       CATEGORY_MASK_EXTENSIONS | SEVERITY_MASK_MILD_ERROR | 531;
+
+
+
+  /**
+   * The message ID for the message that will be used if an error occurs while
+   * trying to send an e-mail message.  This takes three arguments, which are
+   * the alert type, the alert message, and a string representation of the
+   * exception that was caught.
+   */
+  public static final int MSGID_SMTPALERTHANDLER_ERROR_SENDING_MESSAGE =
+       CATEGORY_MASK_EXTENSIONS | SEVERITY_MASK_SEVERE_WARNING | 532;
+
+
+
+  /**
    * Associates a set of generic messages with the message IDs defined in this
    * class.
    */
@@ -7919,6 +7940,17 @@
                     "The password policy state extended request included an " +
                     "operation with an invalid or unsupported operation type " +
                     "of %s");
+
+
+    registerMessage(MSGID_SMTPALERTHANDLER_NO_SMTP_SERVERS,
+                    "The Directory Server is not configured with any " +
+                    "SMTP servers.  The SMTP alert handler cannot be used " +
+                    "unless the Directory Server is configured with " +
+                    "information about at least one SMTP server");
+    registerMessage(MSGID_SMTPALERTHANDLER_ERROR_SENDING_MESSAGE,
+                    "An error occurred when trying to send an e-mail message " +
+                    "for administrative alert with type %s and message %s:  " +
+                    "%s");
   }
 }
 
diff --git a/opendj-sdk/opends/src/server/org/opends/server/util/EMailMessage.java b/opendj-sdk/opends/src/server/org/opends/server/util/EMailMessage.java
index b24c84c..2396b51 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/util/EMailMessage.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/util/EMailMessage.java
@@ -46,10 +46,10 @@
 import javax.mail.internet.MimeMultipart;
 
 import org.opends.server.core.DirectoryServer;
-
-import static org.opends.server.loggers.debug.DebugLogger.*;
 import org.opends.server.loggers.debug.DebugTracer;
 import org.opends.server.types.DebugLogLevel;
+
+import static org.opends.server.loggers.debug.DebugLogger.*;
 import static org.opends.server.messages.MessageHandler.*;
 import static org.opends.server.messages.UtilityMessages.*;
 
@@ -123,7 +123,9 @@
     this.recipients = recipients;
     this.subject    = subject;
 
-    body = new StringBuilder();
+    body         = new StringBuilder();
+    attachments  = new LinkedList<MimeBodyPart>();
+    bodyMIMEType = "text/plain";
   }
 
 
@@ -427,6 +429,7 @@
       try
       {
         Transport.send(message);
+        return;
       }
       catch (SendFailedException sfe)
       {
diff --git a/opendj-sdk/opends/src/server/org/opends/server/util/ServerConstants.java b/opendj-sdk/opends/src/server/org/opends/server/util/ServerConstants.java
index 4e97869..dd213c4 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/util/ServerConstants.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/util/ServerConstants.java
@@ -2552,5 +2552,21 @@
    */
   public static final String SCHEMA_BASE_FILE_NAME_WITHOUT_REVISION  =
        "schema.ldif.";
+
+
+
+  /**
+   * The name of the JavaMail property that can be used to specify the address
+   * of the SMTP server.
+   */
+  public static final String SMTP_PROPERTY_HOST = "mail.smtp.host";
+
+
+
+  /**
+   * The name of the JavaMail property that can be used to specify the port for
+   * the SMTP server.
+   */
+  public static final String SMTP_PROPERTY_PORT = "mail.smtp.port";
 }
 

--
Gitblit v1.10.0