opends/resource/config/config.ldif
@@ -101,6 +101,41 @@ ds-cfg-account-status-notification-type: password-reset ds-cfg-account-status-notification-type: password-changed dn: cn=SMTP Handler,cn=Account Status Notification Handlers,cn=config objectClass: top objectClass: ds-cfg-account-status-notification-handler objectClass: ds-cfg-smtp-account-status-notification-handler cn: SMTP Handler ds-cfg-account-status-notification-handler-class: org.opends.server.extensions.SMTPAccountStatusNotificationHandler ds-cfg-account-status-notification-handler-enabled: false ds-cfg-sender-address: opends-notifications@example.com ds-cfg-email-address-attribute-type: mail ds-cfg-send-notification-without-end-user-address: false ds-cfg-message-template-file: account-temporarily-locked:config/messages/account-temporarily-locked.template ds-cfg-message-template-file: account-permanently-locked:config/messages/account-permanently-locked.template ds-cfg-message-template-file: account-unlocked:config/messages/account-unlocked.template ds-cfg-message-template-file: account-idle-locked:config/messages/account-idle-locked.template ds-cfg-message-template-file: account-reset-locked:config/messages/account-reset-locked.template ds-cfg-message-template-file: account-disabled:config/messages/account-disabled.template ds-cfg-message-template-file: account-enabled:config/messages/account-enabled.template ds-cfg-message-template-file: account-expired:config/messages/account-expired.template ds-cfg-message-template-file: password-expired:config/messages/password-expired.template ds-cfg-message-template-file: password-expiring:config/messages/password-expiring.template ds-cfg-message-template-file: password-reset:config/messages/password-reset.template ds-cfg-message-template-file: password-changed:config/messages/password-changed.template ds-cfg-message-subject: account-temporarily-locked:Your directory account has been locked ds-cfg-message-subject: account-permanently-locked:Your directory account has been locked ds-cfg-message-subject: account-unlocked:Your directory account has been unlocked ds-cfg-message-subject: account-idle-locked:Your directory account has been locked ds-cfg-message-subject: account-reset-locked:Your directory account has been locked ds-cfg-message-subject: account-disabled:Your directory account has been disabled ds-cfg-message-subject: account-enabled:Your directory account has been re-enabled ds-cfg-message-subject: account-expired:Your directory account has expired ds-cfg-message-subject: password-expired:Your directory password has expired ds-cfg-message-subject: password-expiring:Your directory password is going to expire ds-cfg-message-subject: password-reset:Your directory password has been reset ds-cfg-message-subject: password-changed:Your directory password has been changed dn: cn=Alert Handlers,cn=config objectClass: top objectClass: ds-cfg-branch opends/resource/messages/account-disabled.template
New file @@ -0,0 +1,4 @@ Your directory account has been disabled. For further assistance, please contact a server administrator. opends/resource/messages/account-enabled.template
New file @@ -0,0 +1,4 @@ Your directory account has been re-enabled. For further assistance, please contact a server administrator. opends/resource/messages/account-expired.template
New file @@ -0,0 +1,4 @@ Your directory account has expired and may no longer be used. For further assistance, please contact a server administrator. opends/resource/messages/account-idle-locked.template
New file @@ -0,0 +1,5 @@ Your directory account has been locked because it has remained idle for too long. For further assistance, please contact a server administrator. opends/resource/messages/account-permanently-locked.template
New file @@ -0,0 +1,5 @@ Your directory account has been locked as a result of too many failed authentication attempts. Please contact an administrator to have your password reset. opends/resource/messages/account-reset-locked.template
New file @@ -0,0 +1,5 @@ Your directory account has been locked because you did not change your password in a timely manner after it was reset by an administrator. Please contact a server administrator to have the password reset again. opends/resource/messages/account-temporarily-locked.template
New file @@ -0,0 +1,6 @@ Your directory account has been temporarily locked as a result of too many failed authentication attempts. It will automatically be unlocked in %%notification-property:time-until-unlock%%. For further assistance, please contact a server administrator. opends/resource/messages/account-unlocked.template
New file @@ -0,0 +1,3 @@ Your directory account has been unlocked by a server administrator. If you have any further questions, please contact an administrator. opends/resource/messages/password-changed.template
New file @@ -0,0 +1,5 @@ Your directory password has been successfully updated. If you did not request that your password be changed, then contact a server administrator for further assistance. opends/resource/messages/password-expired.template
New file @@ -0,0 +1,3 @@ Your directory password has expired. Please contact a server administrator to have your password reset. opends/resource/messages/password-expiring.template
New file @@ -0,0 +1,7 @@ Your directory password will expire in %%notification-property:time-until-expiration%%. Please change your password before %%notification-property:password-expiration-time%% so that it does not expire. For further assistance, please contact a directory administrator. opends/resource/messages/password-reset.template
New file @@ -0,0 +1,3 @@ Your directory password has been successfully reset by an administrator. If you need further assistance, please contact a server administrator. opends/resource/schema/02-config.ldif
@@ -1511,8 +1511,7 @@ 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' ) 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.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' ) @@ -1577,6 +1576,16 @@ NAME 'ds-cfg-backend-compact-encoding' SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 SINGLE-VALUE X-ORIGIN 'OpenDS Directory Server' ) attributeTypes: ( 1.3.6.1.4.1.26027.1.1.476 NAME 'ds-cfg-email-address-attribute-type' 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.477 NAME 'ds-cfg-send-notification-without-end-user-address' SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 SINGLE-VALUE X-ORIGIN 'OpenDS Directory Server' ) attributeTypes: ( 1.3.6.1.4.1.26027.1.1.478 NAME 'ds-cfg-message-template-file' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 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 MUST ( cn $ ds-cfg-acl-handler-class $ ds-cfg-acl-handler-enabled ) @@ -2218,3 +2227,12 @@ STRUCTURAL MUST ds-cfg-unique-attribute-type MAY ds-cfg-unique-attribute-base-dn X-ORIGIN 'OpenDS Directory Server' ) objectClasses: ( 1.3.6.1.4.1.26027.1.2.123 NAME 'ds-cfg-smtp-account-status-notification-handler' SUP ds-cfg-account-status-notification-handler MUST ( ds-cfg-sender-address $ ds-cfg-send-notification-without-end-user-address $ ds-cfg-message-template-file ) MAY ( ds-cfg-email-address-attribute-type $ ds-cfg-recipient-address $ ds-cfg-message-subject ) X-ORIGIN 'OpenDS Directory Server' ) opends/src/admin/defn/org/opends/server/admin/std/SMTPAccountStatusNotificationHandlerConfiguration.xml
New file @@ -0,0 +1,209 @@ <?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-account-status-notification-handler" plural-name="smtp-account-status-notification-handlers" extends="account-status-notification-handler" package="org.opends.server.admin.std" xmlns:adm="http://www.opends.org/admin" xmlns:ldap="http://www.opends.org/admin-ldap"> <adm:synopsis> <adm:user-friendly-name /> is an account status notification handler that can be used to send email messages to end users and/or administrators whenever an account status notification is generated. </adm:synopsis> <adm:profile name="ldap"> <ldap:object-class> <ldap:oid>1.3.6.1.4.1.26027.1.2.123</ldap:oid> <ldap:name> ds-cfg-smtp-account-status-notification-handler </ldap:name> <ldap:superior> ds-cfg-account-status-notification-handler </ldap:superior> </ldap:object-class> </adm:profile> <adm:property-override name="notification-handler-class"> <adm:default-behavior> <adm:defined> <adm:value> org.opends.server.extensions.SMTPAccountStatusNotificationHandler </adm:value> </adm:defined> </adm:default-behavior> </adm:property-override> <adm:property name="email-address-attribute-type" mandatory="false" multi-valued="true"> <adm:synopsis> Specifies which attribute in user entries may be used to obtain the email address to use when notifying the end user. Multiple attributes can be specified as separate values, and in that case all email addresses identified in all such values will receive the notification. </adm:synopsis> <adm:default-behavior> <adm:alias> <adm:synopsis> If no email address attribute types are specified, then no attempt will be made to send email notification messages to end users. Only those users specified in the set of additional recipient addresses will be sent the notification messages. </adm:synopsis> </adm:alias> </adm:default-behavior> <adm:syntax> <adm:attribute-type /> </adm:syntax> <adm:profile name="ldap"> <ldap:attribute> <ldap:oid>1.3.6.1.4.1.26027.1.1.476</ldap:oid> <ldap:name>ds-cfg-email-address-attribute-type</ldap:name> </ldap:attribute> </adm:profile> </adm:property> <adm:property name="recipient-address" mandatory="false" multi-valued="true"> <adm:synopsis> Specifies an email address to which notification messages will be sent, either instead of or in addition to the end user for whom the notification has been generated. This may be used to ensure that server administrators also receive a copy of any notification messages that are generated. </adm:synopsis> <adm:default-behavior> <adm:alias> <adm:synopsis> If no additional recipient addresses are specified, then only the end users that are the subjects of the account status notifications will receive the notification messages. </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.448</ldap:oid> <ldap:name>ds-cfg-recipient-address</ldap:name> </ldap:attribute> </adm:profile> </adm:property> <adm:property name="send-message-without-end-user-address" mandatory="true" multi-valued="false"> <adm:synopsis> Indicates whether an email notification message should be generated and sent to the set of notification recipients even if the user entry does not contain any values for any of the email address attributes (and therefore it will not be possible to notify the end user). This is only applicable if both one or more email address attribute types and one or more additional recipient addresses are specified. </adm:synopsis> <adm:default-behavior> <adm:defined> <adm:value> true </adm:value> </adm:defined> </adm:default-behavior> <adm:syntax> <adm:boolean /> </adm:syntax> <adm:profile name="ldap"> <ldap:attribute> <ldap:oid>1.3.6.1.4.1.26027.1.1.477</ldap:oid> <ldap:name>ds-cfg-send-message-without-end-user-address</ldap:name> </ldap:attribute> </adm:profile> </adm:property> <adm:property name="sender-address" mandatory="true" multi-valued="false"> <adm:synopsis> Specifies the e-mail address from which the message will be sent. Note that this does not necessarily have to be a legitimate e-mail address. </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="message-subject" mandatory="true" multi-valued="true"> <adm:synopsis> Specifies the subject that should be used for email messages generated by this account status notification handler. The values for this property should begin with the name of an account status notification type followed by a colon and the subject that should be used for the associated notification message. If an email message is generated for an account status notification type for which no subject is defined, then that message will be given a generic subject. </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-template-file" mandatory="true" multi-valued="true"> <adm:synopsis> Specifies the path to the file containing the message template that is to be used to generate the email notification messages. The values for this property should begin with the name of an account status notification type followed by a colon and the path to the template file that should be used for that notification type. If an account status notification has a notification type that is not associated with a message template file, then no email message will be generated for that notification. </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.478</ldap:oid> <ldap:name>ds-cfg-message-template-file</ldap:name> </ldap:attribute> </adm:profile> </adm:property> </adm:managed-object> opends/src/messages/messages/extension.properties
@@ -1733,3 +1733,48 @@ searchable and should not be included in otherwise unindexed search filters MILD_ERR_HASSUBORDINATES_VATTR_NOT_SEARCHABLE_542=The %s attribute is not \ searchable and should not be included in otherwise unindexed search filters MILD_ERR_SMTP_ASNH_NO_MAIL_SERVERS_CONFIGURED_543=The SMTP account status \ notification handler defined in configuration entry %s cannot be enabled \ unless the Directory Server is with information about one or more SMTP servers MILD_ERR_SMTP_ASNH_NO_RECIPIENTS_544=SMTP account status notification handler \ configuration entry '%s' does not include any email address attribute types \ or recipient addresses. At least one of these must be provided MILD_ERR_SMTP_ASNH_SUBJECT_NO_COLON_545=Unable to parse message subject value \ '%s' from configuration entry '%s' because the value does not contain a \ colon to separate the notification type from the subject MILD_ERR_SMTP_ASNH_SUBJECT_INVALID_NOTIFICATION_TYPE_546=Unable to parse \ message subject value '%s' from configuration entry '%s' because '%s' is not \ a valid account status notification type MILD_ERR_SMTP_ASNH_SUBJECT_DUPLICATE_TYPE_547=The message subject definitions \ contained in configuration entry '%s' have multiple subjects defined for \ notification type %s MILD_ERR_SMTP_ASNH_TEMPLATE_NO_COLON_548=Unable to parse message template \ file path value '%s' from configuration entry '%s' because the value does \ not contain a colon to separate the notification type from the template file \ path MILD_ERR_SMTP_ASNH_TEMPLATE_INVALID_NOTIFICATION_TYPE_549=Unable to parse \ message template file path value '%s' from configuration entry '%s' because \ '%s' is not a valid account status notification type MILD_ERR_SMTP_ASNH_TEMPLATE_DUPLICATE_TYPE_550=The message template file path \ definitions contained in configuration entry '%s' have multiple template \ file paths defined for notification type %s MILD_ERR_SMTP_ASNH_TEMPLATE_NO_SUCH_FILE_551=The message template file '%s' \ referenced in configuration entry '%s' does not exist MILD_ERR_SMTP_ASNH_TEMPLATE_UNCLOSED_TOKEN_552=An unclosed token was found \ starting at column %d of line %d MILD_ERR_SMTP_ASNH_TEMPLATE_UNDEFINED_ATTR_TYPE_553=The \ notification-user-attr token starting at column %d of line %d references \ undefined attribute type %s MILD_ERR_SMTP_ASNH_TEMPLATE_UNDEFINED_PROPERTY_554=The \ notification-property token starting at column %d of line %d references \ undefined notification property %s MILD_ERR_SMTP_ASNH_TEMPLATE_UNRECOGNIZED_TOKEN_555=An unrecognized token %s \ was found at column %d of line %d MILD_ERR_SMTP_ASNH_TEMPLATE_CANNOT_PARSE_556=An error occurred while \ attempting to parse message template file '%s' referenced in configuration \ entry '%s': %s INFO_SMTP_ASNH_DEFAULT_SUBJECT_557=Directory Account Status Notification SEVERE_ERR_SMTP_ASNH_CANNOT_SEND_MESSAGE_558=An error occurred while \ attempting to send an account status notification message for notification \ type %s for user entry %s: %s opends/src/server/org/opends/server/extensions/NotificationMessageNotificationMessageTemplateElement.java
New file @@ -0,0 +1,62 @@ /* * 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. */ package org.opends.server.extensions; import org.opends.messages.MessageBuilder; import org.opends.server.types.AccountStatusNotification; /** * This class implements a notification message template element that will * generate a value that is the message for the account status notification. */ public class NotificationMessageNotificationMessageTemplateElement extends NotificationMessageTemplateElement { /** * Creates a new notification message notification message template element. */ public NotificationMessageNotificationMessageTemplateElement() { // No implementation is required. } /** * {@inheritDoc} */ public void generateValue(MessageBuilder buffer, AccountStatusNotification notification) { buffer.append(notification.getMessage()); } } opends/src/server/org/opends/server/extensions/NotificationMessageTemplateElement.java
New file @@ -0,0 +1,54 @@ /* * 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. */ package org.opends.server.extensions; import org.opends.messages.MessageBuilder; import org.opends.server.types.AccountStatusNotification; /** * This class defines the base class for elements that may be used to generate * an account status notification message. */ public abstract class NotificationMessageTemplateElement { /** * Generates a value for this template element using the information contained * in the provided account status notification and appends it to the given * buffer. * * @param buffer The buffer to which the generated value should be * appended. * @param notification The account status notification to process. */ public abstract void generateValue(MessageBuilder buffer, AccountStatusNotification notification); } opends/src/server/org/opends/server/extensions/NotificationPropertyNotificationMessageTemplateElement.java
New file @@ -0,0 +1,78 @@ /* * 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. */ package org.opends.server.extensions; import java.util.List; import org.opends.messages.MessageBuilder; import org.opends.server.types.AccountStatusNotification; import org.opends.server.types.AccountStatusNotificationProperty; /** * This class implements a notification message template element that will * generate a value that is the value of a specified notification property. */ public class NotificationPropertyNotificationMessageTemplateElement extends NotificationMessageTemplateElement { // The account status notification property for which to obtain the value. private AccountStatusNotificationProperty property; /** * Creates a new notification property notification message template element. * * @param property The notification property for which to obtain the value. */ public NotificationPropertyNotificationMessageTemplateElement( AccountStatusNotificationProperty property) { this.property = property; } /** * {@inheritDoc} */ public void generateValue(MessageBuilder buffer, AccountStatusNotification notification) { List<String> propertyValues = notification.getNotificationProperty(property); if ((propertyValues != null) && (! propertyValues.isEmpty())) { buffer.append(propertyValues.get(0)); } } } opends/src/server/org/opends/server/extensions/NotificationTypeNotificationMessageTemplateElement.java
New file @@ -0,0 +1,62 @@ /* * 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. */ package org.opends.server.extensions; import org.opends.messages.MessageBuilder; import org.opends.server.types.AccountStatusNotification; /** * This class implements a notification message template element that will * generate a value that is the name of the account status notification type. */ public class NotificationTypeNotificationMessageTemplateElement extends NotificationMessageTemplateElement { /** * Creates a new notification type notification message template element. */ public NotificationTypeNotificationMessageTemplateElement() { // No implementation is required. } /** * {@inheritDoc} */ public void generateValue(MessageBuilder buffer, AccountStatusNotification notification) { buffer.append(notification.getNotificationType().getName()); } } opends/src/server/org/opends/server/extensions/SMTPAccountStatusNotificationHandler.java
New file @@ -0,0 +1,792 @@ /* * 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. */ package org.opends.server.extensions; import java.io.BufferedReader; import java.io.File; import java.io.FileReader; import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Properties; import java.util.Set; import org.opends.messages.Message; import org.opends.messages.MessageBuilder; import org.opends.server.admin.server.ConfigurationChangeListener; import org.opends.server.admin.std.server.AccountStatusNotificationHandlerCfg; import org.opends.server.admin.std.server. SMTPAccountStatusNotificationHandlerCfg; import org.opends.server.api.AccountStatusNotificationHandler; import org.opends.server.config.ConfigException; import org.opends.server.core.DirectoryServer; import org.opends.server.loggers.debug.DebugTracer; import org.opends.server.types.AccountStatusNotification; import org.opends.server.types.AccountStatusNotificationProperty; import org.opends.server.types.AccountStatusNotificationType; import org.opends.server.types.Attribute; import org.opends.server.types.AttributeType; import org.opends.server.types.AttributeValue; import org.opends.server.types.ConfigChangeResult; import org.opends.server.types.DebugLogLevel; import org.opends.server.types.Entry; import org.opends.server.types.InitializationException; import org.opends.server.types.ResultCode; import org.opends.server.util.EMailMessage; import static org.opends.messages.ExtensionMessages.*; import static org.opends.server.loggers.ErrorLogger.*; import static org.opends.server.loggers.debug.DebugLogger.*; import static org.opends.server.util.StaticUtils.*; /** * This class provides an implementation of an account status notification * handler that can send e-mail messages via SMTP to end users and/or * administrators whenever an account status notification occurs. The e-mail * messages will be generated from template files, which contain the information * to use to create the message body. The template files may contain plain * text, in addition to the following tokens: * <UL> * <LI>%%notification-type%% -- Will be replaced with the name of the * account status notification type for the notification.</LI> * <LI>%%notification-message%% -- Will be replaced with the message for the * account status notification.</LI> * <LI>%%notification-user-dn%% -- Will be replaced with the string * representation of the DN for the user that is the target of the * account status notification.</LI> * <LI>%%notification-user-attr:attrname%% -- Will be replaced with the value * of the attribute specified by attrname from the user's entry. If the * specified attribute has multiple values, then the first value * encountered will be used. If the specified attribute does not have any * values, then it will be replaced with an emtpy string.</LI> * <LI>%%notification-property:propname%% -- Will be replaced with the value * of the specified notification property from the account status * notification. If the specified property has multiple values, then the * first value encountered will be used. If the specified property does * not have any values, then it will be replaced with an emtpy * string.</LI> * </UL> */ public class SMTPAccountStatusNotificationHandler extends AccountStatusNotificationHandler <SMTPAccountStatusNotificationHandlerCfg> implements ConfigurationChangeListener <SMTPAccountStatusNotificationHandlerCfg> { /** * The tracer object for the debug logger. */ private static final DebugTracer TRACER = getTracer(); // A mapping between the notification types and the message template. private HashMap<AccountStatusNotificationType, List<NotificationMessageTemplateElement>> templateMap; // A mapping between the notification types and the message subject. private HashMap<AccountStatusNotificationType,String> subjectMap; // The current configuration for this account status notification handler. private SMTPAccountStatusNotificationHandlerCfg currentConfig; /** * Creates a new, uninitialized instance of this account status notification * handler. */ public SMTPAccountStatusNotificationHandler() { super(); } /** * {@inheritDoc} */ public void initializeStatusNotificationHandler( SMTPAccountStatusNotificationHandlerCfg configuration) throws ConfigException, InitializationException { currentConfig = configuration; currentConfig.addSMTPChangeListener(this); subjectMap = parseSubjects(configuration); templateMap = parseTemplates(configuration); // Make sure that the Directory Server is configured with information about // one or more mail servers. List<Properties> propList = DirectoryServer.getMailServerPropertySets(); if ((propList == null) || propList.isEmpty()) { throw new ConfigException(ERR_SMTP_ASNH_NO_MAIL_SERVERS_CONFIGURED.get( configuration.dn().toString())); } // Make sure that either an explicit recipient list or a set of email // address attributes were provided. Set<AttributeType> mailAttrs = configuration.getEmailAddressAttributeType(); Set<String> recipients = configuration.getRecipientAddress(); if (((mailAttrs == null) || mailAttrs.isEmpty()) && ((recipients == null) || recipients.isEmpty())) { throw new ConfigException(ERR_SMTP_ASNH_NO_RECIPIENTS.get( configuration.dn().toString())); } } /** * Examines the provided configuration and parses the message subject * information from it. * * @param configuration The configuration to be examined. * * @return A mapping between the account status notification type and the * subject that should be used for messages generated for * notifications with that type. * * @throws ConfigException If a problem occurs while parsing the subject * configuration. */ private HashMap<AccountStatusNotificationType,String> parseSubjects( SMTPAccountStatusNotificationHandlerCfg configuration) throws ConfigException { HashMap<AccountStatusNotificationType,String> map = new HashMap<AccountStatusNotificationType,String>(); for (String s : configuration.getMessageSubject()) { int colonPos = s.indexOf(':'); if (colonPos < 0) { throw new ConfigException(ERR_SMTP_ASNH_SUBJECT_NO_COLON.get(s, configuration.dn().toString())); } String notificationTypeName = s.substring(0, colonPos).trim(); AccountStatusNotificationType t = AccountStatusNotificationType.typeForName(notificationTypeName); if (t == null) { throw new ConfigException( ERR_SMTP_ASNH_SUBJECT_INVALID_NOTIFICATION_TYPE.get( s, configuration.dn().toString(), notificationTypeName)); } else if (map.containsKey(t)) { throw new ConfigException(ERR_SMTP_ASNH_SUBJECT_DUPLICATE_TYPE.get( configuration.dn().toString(), notificationTypeName)); } map.put(t, s.substring(colonPos+1).trim()); if (debugEnabled()) { TRACER.debugInfo("Subject for notification type " + t.getName() + ": " + map.get(t)); } } return map; } /** * Examines the provided configuration and parses the message template * information from it. * * @param configuration The configuration to be examined. * * @return A mapping between the account status notification type and the * template that should be used to generate messages for * notifications with that type. * * @throws ConfigException If a problem occurs while parsing the template * configuration. */ private HashMap<AccountStatusNotificationType, List<NotificationMessageTemplateElement>> parseTemplates( SMTPAccountStatusNotificationHandlerCfg configuration) throws ConfigException { HashMap<AccountStatusNotificationType, List<NotificationMessageTemplateElement>> map = new HashMap<AccountStatusNotificationType, List<NotificationMessageTemplateElement>>(); for (String s : configuration.getMessageTemplateFile()) { int colonPos = s.indexOf(':'); if (colonPos < 0) { throw new ConfigException(ERR_SMTP_ASNH_TEMPLATE_NO_COLON.get(s, configuration.dn().toString())); } String notificationTypeName = s.substring(0, colonPos).trim(); AccountStatusNotificationType t = AccountStatusNotificationType.typeForName(notificationTypeName); if (t == null) { throw new ConfigException( ERR_SMTP_ASNH_TEMPLATE_INVALID_NOTIFICATION_TYPE.get( s, configuration.dn().toString(), notificationTypeName)); } else if (map.containsKey(t)) { throw new ConfigException(ERR_SMTP_ASNH_TEMPLATE_DUPLICATE_TYPE.get( configuration.dn().toString(), notificationTypeName)); } String path = s.substring(colonPos+1).trim(); File f = new File(path); if (! f.exists()) { throw new ConfigException(ERR_SMTP_ASNH_TEMPLATE_NO_SUCH_FILE.get( path, configuration.dn().toString())); } map.put(t, parseTemplateFile(f)); if (debugEnabled()) { TRACER.debugInfo("Decoded template elment list for type " + t.getName()); } } return map; } /** * Parses the specified template file into a list of notification message * template elements. * * @param f A reference to the template file to be parsed. * * @return A list of notification message template elements parsed from the * specified file. * * @throws ConfigException If error occurs while attempting to parse the * template file. */ private List<NotificationMessageTemplateElement> parseTemplateFile(File f) throws ConfigException { LinkedList<NotificationMessageTemplateElement> elementList = new LinkedList<NotificationMessageTemplateElement>(); BufferedReader reader = null; try { reader = new BufferedReader(new FileReader(f)); int lineNumber = 0; while (true) { String line = reader.readLine(); if (line == null) { break; } if (debugEnabled()) { TRACER.debugInfo("Read message template line " + line); } lineNumber++; int startPos = 0; while (startPos < line.length()) { int delimPos = line.indexOf("%%", startPos); if (delimPos < 0) { if (debugEnabled()) { TRACER.debugInfo("No more tokens -- adding text " + line.substring(startPos)); } elementList.add(new TextNotificationMessageTemplateElement( line.substring(startPos))); break; } else { if (delimPos > startPos) { if (debugEnabled()) { TRACER.debugInfo("Adding text before token " + line.substring(startPos)); } elementList.add(new TextNotificationMessageTemplateElement( line.substring(startPos, delimPos))); } int closeDelimPos = line.indexOf("%%", delimPos+1); if (closeDelimPos < 0) { // There was an opening %% but not a closing one. throw new ConfigException( ERR_SMTP_ASNH_TEMPLATE_UNCLOSED_TOKEN.get( delimPos, lineNumber)); } else { String tokenStr = line.substring(delimPos+2, closeDelimPos); String lowerTokenStr = toLowerCase(tokenStr); if (lowerTokenStr.equals("notification-type")) { if (debugEnabled()) { TRACER.debugInfo("Found a notification type token " + tokenStr); } elementList.add( new NotificationTypeNotificationMessageTemplateElement()); } else if (lowerTokenStr.equals("notification-message")) { if (debugEnabled()) { TRACER.debugInfo("Found a notification message token " + tokenStr); } elementList.add( new NotificationMessageNotificationMessageTemplateElement()); } else if (lowerTokenStr.equals("notification-user-dn")) { if (debugEnabled()) { TRACER.debugInfo("Found a notification user DN token " + tokenStr); } elementList.add( new UserDNNotificationMessageTemplateElement()); } else if (lowerTokenStr.startsWith("notification-user-attr:")) { String attrName = lowerTokenStr.substring(23); AttributeType attrType = DirectoryServer.getAttributeType(attrName, false); if (attrType == null) { throw new ConfigException( ERR_SMTP_ASNH_TEMPLATE_UNDEFINED_ATTR_TYPE.get( delimPos, lineNumber, attrName)); } else { if (debugEnabled()) { TRACER.debugInfo("Found a user attribute token for " + attrType.getNameOrOID() + " -- " + tokenStr); } elementList.add( new UserAttributeNotificationMessageTemplateElement( attrType)); } } else if (lowerTokenStr.startsWith("notification-property:")) { String propertyName = lowerTokenStr.substring(22); AccountStatusNotificationProperty property = AccountStatusNotificationProperty.forName(propertyName); if (property == null) { throw new ConfigException( ERR_SMTP_ASNH_TEMPLATE_UNDEFINED_PROPERTY.get( delimPos, lineNumber, propertyName)); } else { if (debugEnabled()) { TRACER.debugInfo("Found a notification property token " + "for " + propertyName + " -- " + tokenStr); } elementList.add( new NotificationPropertyNotificationMessageTemplateElement( property)); } } else { throw new ConfigException( ERR_SMTP_ASNH_TEMPLATE_UNRECOGNIZED_TOKEN.get( tokenStr, delimPos, lineNumber)); } startPos = closeDelimPos + 2; } } } // We need to put a CRLF at the end of the line, as per the SMTP spec. elementList.add(new TextNotificationMessageTemplateElement("\r\n")); } return elementList; } catch (Exception e) { if (debugEnabled()) { TRACER.debugCaught(DebugLogLevel.ERROR, e); } throw new ConfigException(ERR_SMTP_ASNH_TEMPLATE_CANNOT_PARSE.get( f.getAbsolutePath(), currentConfig.dn().toString(), getExceptionMessage(e))); } finally { try { if (reader != null) { reader.close(); } } catch (Exception e) {} } } /** * {@inheritDoc} */ public boolean isConfigurationAcceptable( AccountStatusNotificationHandlerCfg configuration, List<Message> unacceptableReasons) { SMTPAccountStatusNotificationHandlerCfg config = (SMTPAccountStatusNotificationHandlerCfg) configuration; return isConfigurationChangeAcceptable(config, unacceptableReasons); } /** * {@inheritDoc} */ public void handleStatusNotification(AccountStatusNotification notification) { SMTPAccountStatusNotificationHandlerCfg config = currentConfig; HashMap<AccountStatusNotificationType,String> subjects = subjectMap; HashMap<AccountStatusNotificationType, List<NotificationMessageTemplateElement>> templates = templateMap; // First, see if the notification type is one that we handle. If not, then // return without doing anything. AccountStatusNotificationType notificationType = notification.getNotificationType(); List<NotificationMessageTemplateElement> templateElements = templates.get(notificationType); if (templateElements == null) { if (debugEnabled()) { TRACER.debugInfo("No message template for notification type " + notificationType.getName()); } return; } // It is a notification that should be handled, so we can start generating // the e-mail message. First, check to see if there are any mail attributes // that would cause us to send a message to the end user. LinkedList<String> recipients = new LinkedList<String>(); Set<AttributeType> addressAttrs = config.getEmailAddressAttributeType(); Set<String> recipientAddrs = config.getRecipientAddress(); if ((addressAttrs != null) && (! addressAttrs.isEmpty())) { Entry userEntry = notification.getUserEntry(); for (AttributeType t : addressAttrs) { List<Attribute> attrList = userEntry.getAttribute(t); if (attrList != null) { for (Attribute a : attrList) { for (AttributeValue v : a.getValues()) { if (debugEnabled()) { TRACER.debugInfo("Adding end user recipient " + v.getStringValue() + " from attr " + a.getNameWithOptions()); } recipients.add(v.getStringValue()); } } } } if (recipients.isEmpty()) { if ((recipientAddrs == null) || recipientAddrs.isEmpty()) { // There are no recipients at all, so there's no point in generating // the message. Return without doing anything. if (debugEnabled()) { TRACER.debugInfo("No end user recipients, and no explicit " + "recipients"); } return; } else { if (! config.isSendMessageWithoutEndUserAddress()) { // We can't send the message to the end user, and the handler is // configured to not send only to administrators, so we shouln't // do anything. if (debugEnabled()) { TRACER.debugInfo("No end user recipients, and shouldn't send " + "without end user recipients"); } return; } } } } // Next, add any explicitly-defined recipients. if (recipientAddrs != null) { if (debugEnabled()) { for (String s : recipientAddrs) { TRACER.debugInfo("Adding explicit recipient " + s); } } recipients.addAll(recipientAddrs); } // Get the message subject to use. If none is defined, then use a generic // subject. String subject = subjects.get(notificationType); if (subject == null) { subject = INFO_SMTP_ASNH_DEFAULT_SUBJECT.get().toString(); if (debugEnabled()) { TRACER.debugInfo("Using default subject of " + subject); } } else if (debugEnabled()) { TRACER.debugInfo("Using per-type subject of " + subject); } // Generate the message body. MessageBuilder messageBody = new MessageBuilder(); for (NotificationMessageTemplateElement e : templateElements) { e.generateValue(messageBody, notification); } // Create and send the e-mail message. EMailMessage message = new EMailMessage(config.getSenderAddress(), recipients, subject); message.setBody(messageBody); if (debugEnabled()) { TRACER.debugInfo("Set message body of " + messageBody.toString()); } try { message.send(); if (debugEnabled()) { TRACER.debugInfo("Successfully sent the message"); } } catch (Exception e) { if (debugEnabled()) { TRACER.debugCaught(DebugLogLevel.ERROR, e); } logError(ERR_SMTP_ASNH_CANNOT_SEND_MESSAGE.get(notificationType.getName(), notification.getUserDN().toString(), getExceptionMessage(e))); } } /** * {@inheritDoc} */ public boolean isConfigurationChangeAcceptable( SMTPAccountStatusNotificationHandlerCfg configuration, List<Message> unacceptableReasons) { boolean configAcceptable = true; // Make sure that the Directory Server is configured with information about // one or more mail servers. List<Properties> propList = DirectoryServer.getMailServerPropertySets(); if ((propList == null) || propList.isEmpty()) { unacceptableReasons.add(ERR_SMTP_ASNH_NO_MAIL_SERVERS_CONFIGURED.get( configuration.dn().toString())); configAcceptable = false; } // Make sure that either an explicit recipient list or a set of email // address attributes were provided. Set<AttributeType> mailAttrs = configuration.getEmailAddressAttributeType(); Set<String> recipients = configuration.getRecipientAddress(); if (((mailAttrs == null) || mailAttrs.isEmpty()) && ((recipients == null) || recipients.isEmpty())) { unacceptableReasons.add(ERR_SMTP_ASNH_NO_RECIPIENTS.get( configuration.dn().toString())); configAcceptable = false; } try { parseSubjects(configuration); } catch (ConfigException ce) { if (debugEnabled()) { TRACER.debugCaught(DebugLogLevel.ERROR, ce); } unacceptableReasons.add(ce.getMessageObject()); configAcceptable = false; } try { parseTemplates(configuration); } catch (ConfigException ce) { if (debugEnabled()) { TRACER.debugCaught(DebugLogLevel.ERROR, ce); } unacceptableReasons.add(ce.getMessageObject()); configAcceptable = false; } return configAcceptable; } /** * {@inheritDoc} */ public ConfigChangeResult applyConfigurationChange( SMTPAccountStatusNotificationHandlerCfg configuration) { try { HashMap<AccountStatusNotificationType,String> subjects = parseSubjects(configuration); HashMap<AccountStatusNotificationType, List<NotificationMessageTemplateElement>> templates = parseTemplates(configuration); currentConfig = configuration; subjectMap = subjects; templateMap = templates; return new ConfigChangeResult(ResultCode.SUCCESS, false); } catch (ConfigException ce) { if (debugEnabled()) { TRACER.debugCaught(DebugLogLevel.ERROR, ce); } LinkedList<Message> messageList = new LinkedList<Message>(); messageList.add(ce.getMessageObject()); return new ConfigChangeResult(ResultCode.UNWILLING_TO_PERFORM, false, messageList); } } } opends/src/server/org/opends/server/extensions/TextNotificationMessageTemplateElement.java
New file @@ -0,0 +1,70 @@ /* * 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. */ package org.opends.server.extensions; import org.opends.messages.MessageBuilder; import org.opends.server.types.AccountStatusNotification; /** * This class implements a notification message template element that will * generate a value using static text. */ public class TextNotificationMessageTemplateElement extends NotificationMessageTemplateElement { // The static text associated with this element. private final String text; /** * Creates a new text notification message template element from the provided * string. * * @param text The string to use as the text for this element. */ public TextNotificationMessageTemplateElement(String text) { this.text = text; } /** * {@inheritDoc} */ public void generateValue(MessageBuilder buffer, AccountStatusNotification notification) { buffer.append(text); } } opends/src/server/org/opends/server/extensions/UserAttributeNotificationMessageTemplateElement.java
New file @@ -0,0 +1,90 @@ /* * 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. */ package org.opends.server.extensions; import java.util.List; import org.opends.messages.MessageBuilder; import org.opends.server.types.AccountStatusNotification; import org.opends.server.types.Attribute; import org.opends.server.types.AttributeType; import org.opends.server.types.AttributeValue; import org.opends.server.types.Entry; /** * This class implements a notification message template element that will * generate a value that is the value of a specified attribute from the target * user's entry. */ public class UserAttributeNotificationMessageTemplateElement extends NotificationMessageTemplateElement { // The attribute type for which to obtain the value. private AttributeType attributeType; /** * Creates a new user DN notification message template element. * * @param attributeType The attribute type for which to obtain the value. */ public UserAttributeNotificationMessageTemplateElement(AttributeType attributeType) { this.attributeType = attributeType; } /** * {@inheritDoc} */ public void generateValue(MessageBuilder buffer, AccountStatusNotification notification) { Entry userEntry = notification.getUserEntry(); List<Attribute> attrList = userEntry.getAttribute(attributeType); if (attrList != null) { for (Attribute a : attrList) { for (AttributeValue v : a.getValues()) { buffer.append(v.getStringValue()); return; } } } } } opends/src/server/org/opends/server/extensions/UserDNNotificationMessageTemplateElement.java
New file @@ -0,0 +1,62 @@ /* * 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. */ package org.opends.server.extensions; import org.opends.messages.MessageBuilder; import org.opends.server.types.AccountStatusNotification; /** * This class implements a notification message template element that will * generate a value that is the string representation of the target user's DN. */ public class UserDNNotificationMessageTemplateElement extends NotificationMessageTemplateElement { /** * Creates a new user DN notification message template element. */ public UserDNNotificationMessageTemplateElement() { // No implementation is required. } /** * {@inheritDoc} */ public void generateValue(MessageBuilder buffer, AccountStatusNotification notification) { buffer.append(notification.getUserDN().toString()); } } opends/src/server/org/opends/server/types/AccountStatusNotification.java
@@ -180,6 +180,26 @@ /** * Retrieves the set of values for the specified account status * notification property. * * @param property The account status notification property for * which to retrieve the associated values. * * @return The set of values for the specified account status * notification property, or {@code null} if the specified * property is not defined for this account status * notification. */ public List<String> getNotificationProperty( AccountStatusNotificationProperty property) { return notificationProperties.get(property); } /** * Creates a set of account status notification properties from the * provided information. * @@ -259,7 +279,7 @@ (1000*timeToExpiration); propList = new ArrayList<String>(1); propList.add(new Date(expTime).toString()); props.put(ACCOUNT_UNLOCK_TIME, propList); props.put(PASSWORD_EXPIRATION_TIME, propList); } if ((oldPasswords != null) && (! oldPasswords.isEmpty())) opends/src/server/org/opends/server/workflowelement/localbackend/LocalBackendWorkflowElement.java
@@ -3526,11 +3526,6 @@ else if (pwPolicyState.shouldWarn()) { int numSeconds = pwPolicyState.getSecondsUntilExpiration(); Message timeToExpiration = secondsToTimeString(numSeconds); Message message = INFO_BIND_PASSWORD_EXPIRING.get( timeToExpiration); localOp.appendErrorMessage(message); if (pwPolicyWarningType == null) { @@ -3785,7 +3780,7 @@ int numSeconds = pwPolicyState.getSecondsUntilExpiration(); Message timeToExpiration = secondsToTimeString(numSeconds); Message message = INFO_BIND_PASSWORD_EXPIRING.get( Message message = WARN_BIND_PASSWORD_EXPIRING.get( timeToExpiration); pwPolicyState.generateAccountStatusNotification( @@ -4164,11 +4159,6 @@ else if (pwPolicyState.shouldWarn()) { int numSeconds = pwPolicyState.getSecondsUntilExpiration(); Message timeToExpiration = secondsToTimeString(numSeconds); Message message = INFO_BIND_PASSWORD_EXPIRING.get( timeToExpiration); localOp.appendErrorMessage(message); if (pwPolicyWarningType == null) { @@ -4204,7 +4194,7 @@ int numSeconds = pwPolicyState.getSecondsUntilExpiration(); Message timeToExpiration = secondsToTimeString(numSeconds); Message message = INFO_BIND_PASSWORD_EXPIRING.get( Message message = WARN_BIND_PASSWORD_EXPIRING.get( timeToExpiration); pwPolicyState.generateAccountStatusNotification(