Fixed issue 19545: 'Alerts' email system now uses POC 'Email Configuration' too
authorDavid Baz Fayos <david.baz@openbravo.com>
Wed, 25 Jan 2012 20:32:54 +0100
changeset 15332 145375d4a136
parent 15228 440693e24fec
child 15333 38a9d8bc9da3
Fixed issue 19545: 'Alerts' email system now uses POC 'Email Configuration' too
src-db/database/sourcedata/AD_FIELD.xml
src-util/modulescript/build/classes/org/openbravo/modulescript/UpgradeToPocEmail.class
src-util/modulescript/build/classes/org/openbravo/modulescript/UpgradeToPocEmailData.class
src-util/modulescript/src/org/openbravo/modulescript/UpgradeToPocEmail.java
src-util/modulescript/src/org/openbravo/modulescript/UpgradeToPocEmail_Data.xsql
src/org/openbravo/erpCommon/ad_process/AlertProcess.java
src/org/openbravo/erpCommon/businessUtility/EMail.java
src/org/openbravo/erpCommon/utility/poc/EmailManager.java
src/org/openbravo/erpCommon/utility/reporting/printing/PrintController.java
--- a/src-db/database/sourcedata/AD_FIELD.xml	Wed Jan 25 18:20:11 2012 +0100
+++ b/src-db/database/sourcedata/AD_FIELD.xml	Wed Jan 25 20:32:54 2012 +0100
@@ -46739,6 +46739,7 @@
 <!--3813-->  <AD_COLUMN_ID><![CDATA[4771]]></AD_COLUMN_ID>
 <!--3813-->  <AD_FIELDGROUP_ID><![CDATA[119]]></AD_FIELDGROUP_ID>
 <!--3813-->  <ISDISPLAYED><![CDATA[Y]]></ISDISPLAYED>
+<!--3813-->  <DISPLAYLOGIC><![CDATA[@SMTPHost@!null & @SMTPHost@!'']]></DISPLAYLOGIC>
 <!--3813-->  <DISPLAYLENGTH><![CDATA[20]]></DISPLAYLENGTH>
 <!--3813-->  <ISREADONLY><![CDATA[N]]></ISREADONLY>
 <!--3813-->  <SEQNO><![CDATA[80]]></SEQNO>
@@ -58096,6 +58097,7 @@
 <!--5161-->  <AD_COLUMN_ID><![CDATA[6557]]></AD_COLUMN_ID>
 <!--5161-->  <AD_FIELDGROUP_ID><![CDATA[119]]></AD_FIELDGROUP_ID>
 <!--5161-->  <ISDISPLAYED><![CDATA[Y]]></ISDISPLAYED>
+<!--5161-->  <DISPLAYLOGIC><![CDATA[@SMTPHost@!null & @SMTPHost@!'']]></DISPLAYLOGIC>
 <!--5161-->  <DISPLAYLENGTH><![CDATA[20]]></DISPLAYLENGTH>
 <!--5161-->  <ISREADONLY><![CDATA[N]]></ISREADONLY>
 <!--5161-->  <SEQNO><![CDATA[100]]></SEQNO>
@@ -58124,6 +58126,7 @@
 <!--5162-->  <AD_COLUMN_ID><![CDATA[6558]]></AD_COLUMN_ID>
 <!--5162-->  <AD_FIELDGROUP_ID><![CDATA[119]]></AD_FIELDGROUP_ID>
 <!--5162-->  <ISDISPLAYED><![CDATA[Y]]></ISDISPLAYED>
+<!--5162-->  <DISPLAYLOGIC><![CDATA[@SMTPHost@!null & @SMTPHost@!'']]></DISPLAYLOGIC>
 <!--5162-->  <DISPLAYLENGTH><![CDATA[20]]></DISPLAYLENGTH>
 <!--5162-->  <ISREADONLY><![CDATA[N]]></ISREADONLY>
 <!--5162-->  <SEQNO><![CDATA[110]]></SEQNO>
@@ -58152,6 +58155,7 @@
 <!--5163-->  <AD_COLUMN_ID><![CDATA[6559]]></AD_COLUMN_ID>
 <!--5163-->  <AD_FIELDGROUP_ID><![CDATA[119]]></AD_FIELDGROUP_ID>
 <!--5163-->  <ISDISPLAYED><![CDATA[Y]]></ISDISPLAYED>
+<!--5163-->  <DISPLAYLOGIC><![CDATA[@SMTPHost@!null & @SMTPHost@!'']]></DISPLAYLOGIC>
 <!--5163-->  <DISPLAYLENGTH><![CDATA[20]]></DISPLAYLENGTH>
 <!--5163-->  <ISREADONLY><![CDATA[N]]></ISREADONLY>
 <!--5163-->  <SEQNO><![CDATA[120]]></SEQNO>
@@ -58180,6 +58184,7 @@
 <!--5164-->  <AD_COLUMN_ID><![CDATA[6560]]></AD_COLUMN_ID>
 <!--5164-->  <AD_FIELDGROUP_ID><![CDATA[119]]></AD_FIELDGROUP_ID>
 <!--5164-->  <ISDISPLAYED><![CDATA[Y]]></ISDISPLAYED>
+<!--5164-->  <DISPLAYLOGIC><![CDATA[@SMTPHost@!null & @SMTPHost@!'']]></DISPLAYLOGIC>
 <!--5164-->  <DISPLAYLENGTH><![CDATA[20]]></DISPLAYLENGTH>
 <!--5164-->  <ISREADONLY><![CDATA[N]]></ISREADONLY>
 <!--5164-->  <SEQNO><![CDATA[130]]></SEQNO>
@@ -68276,6 +68281,7 @@
 <!--5887-->  <AD_COLUMN_ID><![CDATA[7792]]></AD_COLUMN_ID>
 <!--5887-->  <AD_FIELDGROUP_ID><![CDATA[119]]></AD_FIELDGROUP_ID>
 <!--5887-->  <ISDISPLAYED><![CDATA[Y]]></ISDISPLAYED>
+<!--5887-->  <DISPLAYLOGIC><![CDATA[@SMTPHost@!null & @SMTPHost@!'']]></DISPLAYLOGIC>
 <!--5887-->  <DISPLAYLENGTH><![CDATA[1]]></DISPLAYLENGTH>
 <!--5887-->  <ISREADONLY><![CDATA[N]]></ISREADONLY>
 <!--5887-->  <SEQNO><![CDATA[90]]></SEQNO>
Binary file src-util/modulescript/build/classes/org/openbravo/modulescript/UpgradeToPocEmail.class has changed
Binary file src-util/modulescript/build/classes/org/openbravo/modulescript/UpgradeToPocEmailData.class has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src-util/modulescript/src/org/openbravo/modulescript/UpgradeToPocEmail.java	Wed Jan 25 20:32:54 2012 +0100
@@ -0,0 +1,127 @@
+/*
+ *************************************************************************
+ * The contents of this file are subject to the Openbravo  Public  License
+ * Version  1.1  (the  "License"),  being   the  Mozilla   Public  License
+ * Version 1.1  with a permitted attribution clause; you may not  use this
+ * file except in compliance with the License. You  may  obtain  a copy of
+ * the License at http://www.openbravo.com/legal/license.html
+ * Software distributed under the License  is  distributed  on  an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
+ * License for the specific  language  governing  rights  and  limitations
+ * under the License.
+ * The Original Code is Openbravo ERP.
+ * The Initial Developer of the Original Code is Openbravo SLU
+ * All portions are Copyright (C) 2012 Openbravo SLU
+ * All Rights Reserved.
+ * Contributor(s):  ______________________________________.
+ ************************************************************************
+ */
+
+package org.openbravo.modulescript;
+
+import org.apache.log4j.Logger;
+import org.openbravo.database.ConnectionProvider;
+
+/**
+ * 
+ * @author dbaz
+ */
+public class UpgradeToPocEmail extends ModuleScript {
+
+  private static final Logger log4j = Logger.getLogger(UpdateEmailPasswords.class);
+
+  @Override
+  public void execute() {
+
+    // Updating email passwords required to fix issue 13688
+    // Nomenclature: "old implementation": email implementation done in the "AD_CLIENT" table
+    // ("Client" window)
+    // Nomenclature: "new implementation": email implementation done in the "C_POC_CONFIGURATION"
+    // table ("Email Configuration" tab child of "Client" window)
+    // This script moves the configuration of the old implementation (if it is valid) to the new
+    // implementation (if there is not a different configuration already there)
+
+    try {
+      ConnectionProvider cp = getConnectionProvider();
+
+      UpgradeToPocEmailData[] oldConfigurationData = UpgradeToPocEmailData.oldConfigurationData(cp);
+      if (oldConfigurationData.length == 0) {
+        return;
+      }
+      UpgradeToPocEmailData[] newConfigurationData = UpgradeToPocEmailData.newConfigurationData(cp);
+
+      boolean isFirstExecution = true; // For log4j purposes
+      boolean hasToCreateNew = true;
+      boolean hasToDeleteOld = true;
+
+      for (UpgradeToPocEmailData oldConfiguration : oldConfigurationData) {
+        // Try the upgrade process only if there is an email configuration in the old implementation
+        // (if not we are done, there is no functional email configuration running in the old
+        // implementation so nothing to upgrade)
+        if (oldConfiguration.server != null && !"".equals(oldConfiguration.server)) {
+          if (isFirstExecution) { // For log4j purposes
+            isFirstExecution = false;
+            log4j
+                .debug("Migrating old implementation email configurations to the new implementation");
+          }
+          hasToCreateNew = true;
+          hasToDeleteOld = true;
+          for (UpgradeToPocEmailData newConfiguration : newConfigurationData) {
+            // If there is already a configuration introduced in the new implementation, don't
+            // create a new one in the new implementation
+            if (oldConfiguration.adClientId.equals(newConfiguration.adClientId)) {
+              hasToCreateNew = false;
+              // ...and if the existing configuration of the new implementation is the same than the
+              // old implementation one and is active, delete the configuration of the old
+              // implementation
+              if (!hasToCreateNew && "Y".equals(newConfiguration.isactive)
+                  && oldConfiguration.server.equals(newConfiguration.server)
+                  && oldConfiguration.senderaddress.equals(newConfiguration.senderaddress)
+                  && oldConfiguration.accountname.equals(newConfiguration.accountname)) {
+                hasToDeleteOld = true;
+                // ...and ensure/force this existing configuration of the new implementation has
+                // "AD_ORG_ID" = "0" to avoid problems with organizations without access to the
+                // existing matched one.
+                UpgradeToPocEmailData.changeNewConfigurationDataOrg(cp,
+                    newConfiguration.cPocConfigurationId);
+                break; // If we already know that the existing old implementation and new
+                       // implementation configuration match, no need to continue iterating.
+              } else {
+                hasToDeleteOld = false;
+              }
+            }
+          }
+          if (hasToCreateNew) {
+            UpgradeToPocEmailData.insertNewConfigurationData(
+                cp.getConnection(),
+                cp,
+                oldConfiguration.adClientId,
+                oldConfiguration.server,
+                (oldConfiguration.senderaddress != null
+                    && !"".equals(oldConfiguration.senderaddress) ? oldConfiguration.senderaddress
+                    : "my@email.com"), oldConfiguration.auth, oldConfiguration.accountname,
+                oldConfiguration.accountpass);
+            log4j.debug("Server: \"" + oldConfiguration.server + "\" of adClientId: \""
+                + oldConfiguration.adClientId + "\" has been ported succesfully");
+          } else {
+            log4j.debug("Server: \"" + oldConfiguration.server + "\" of adClientId: \""
+                + oldConfiguration.adClientId + "\" has not been ported because "
+                + (hasToDeleteOld ? "the same" : "a different")
+                + " email configuration already exists in the new implementation");
+          }
+          if (hasToDeleteOld) {
+            UpgradeToPocEmailData.deleteOldConfigurationData(cp, oldConfiguration.adClientId);
+            log4j.debug("Deleted old implementation configuration of server: \""
+                + oldConfiguration.server + "\" of adClientId: \"" + oldConfiguration.adClientId
+                + "\" because the server "
+                + (hasToCreateNew ? "already has been ported to" : "already exists in")
+                + " the new implementation");
+          }
+        }
+      }
+
+    } catch (Exception e) {
+      handleError(e);
+    }
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src-util/modulescript/src/org/openbravo/modulescript/UpgradeToPocEmail_Data.xsql	Wed Jan 25 20:32:54 2012 +0100
@@ -0,0 +1,91 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!--
+ *************************************************************************
+ * The contents of this file are subject to the Openbravo  Public  License
+ * Version  1.1  (the  "License"),  being   the  Mozilla   Public  License
+ * Version 1.1  with a permitted attribution clause; you may not  use this
+ * file except in compliance with the License. You  may  obtain  a copy of
+ * the License at http://www.openbravo.com/legal/license.html
+ * Software distributed under the License  is  distributed  on  an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
+ * License for the specific  language  governing  rights  and  limitations
+ * under the License.
+ * The Original Code is Openbravo ERP.
+ * The Initial Developer of the Original Code is Openbravo SLU
+ * All portions are Copyright (C) 2012 Openbravo SLU
+ * All Rights Reserved.
+ * Contributor(s):  ______________________________________.
+ ************************************************************************
+-->
+<SqlClass name="UpgradeToPocEmailData" package="org.openbravo.modulescript">
+  <SqlClassComment></SqlClassComment>
+   <SqlMethod name="newConfigurationData" type="preparedStatement" return="multiple">
+    <SqlMethodComment></SqlMethodComment>
+    <Sql>
+      <![CDATA[
+      SELECT ad_client_id, ad_org_id, isactive, c_poc_configuration_id, smtpserver as server, smtpserversenderaddress as senderaddress, issmtpauthorization as auth, smtpserveraccount as accountname, smtpserverpassword as accountpass FROM c_poc_configuration
+      ]]>
+    </Sql>
+  </SqlMethod>
+  <SqlMethod name="oldConfigurationData" type="preparedStatement" return="multiple">
+    <SqlMethodComment></SqlMethodComment>
+    <Sql>
+      <![CDATA[
+      SELECT ad_client_id, ad_org_id, smtphost as server, requestemail as senderaddress, issmtpauthorization as auth, requestuser as accountname, requestuserpw as accountpass FROM ad_client
+      ]]>
+    </Sql>
+  </SqlMethod>
+  <SqlMethod name="deleteOldConfigurationData" type="preparedStatement" return="rowCount">
+    <SqlMethodComment></SqlMethodComment>
+    <Sql>
+      <![CDATA[
+        UPDATE ad_client SET
+           smtphost = NULL,
+           requestemail = NULL,
+           issmtpauthorization = 'N',
+           requestuser = NULL,
+           requestuserpw = NULL,
+           requestfolder = NULL,
+           updated = now(),
+           updatedby = '0'
+        WHERE
+           ad_client_id = ?
+      ]]>
+    </Sql>
+    <Parameter name="adClientId"/>
+  </SqlMethod>
+  <SqlMethod name="insertNewConfigurationData" type="preparedStatement" connection="true" return="rowCount">
+    <SqlMethodComment></SqlMethodComment>
+    <Sql>
+      <![CDATA[
+      INSERT INTO c_poc_configuration(
+            ad_client_id, ad_org_id, c_poc_configuration_id, smtpserver, smtpserversenderaddress,
+            issmtpauthorization, smtpserveraccount, smtpserverpassword, isactive,
+            created, createdby, updated, updatedby)
+      VALUES (?, '0', GET_UUID(), ?, ?,
+            ?, ?, ?, 'Y',
+            now(), '0', now(), '0')
+      ]]>
+    </Sql>
+    <Parameter name="adClientId"/>
+    <Parameter name="smtpserver"/>
+    <Parameter name="smtpserversenderaddress"/>    
+    <Parameter name="issmtpauthorization"/>
+    <Parameter name="smtpserveraccount"/>
+    <Parameter name="smtpserverpassword"/>
+  </SqlMethod>
+  <SqlMethod name="changeNewConfigurationDataOrg" type="preparedStatement" return="rowCount">
+    <SqlMethodComment></SqlMethodComment>
+    <Sql>
+      <![CDATA[
+        UPDATE c_poc_configuration SET
+           ad_org_id = '0',
+           updated = now(),
+           updatedby = '0'
+        WHERE
+           c_poc_configuration_id = ?
+      ]]>
+    </Sql>
+    <Parameter name="cPocConfigurationId"/>
+  </SqlMethod>
+</SqlClass>
\ No newline at end of file
--- a/src/org/openbravo/erpCommon/ad_process/AlertProcess.java	Wed Jan 25 18:20:11 2012 +0100
+++ b/src/org/openbravo/erpCommon/ad_process/AlertProcess.java	Wed Jan 25 20:32:54 2012 +0100
@@ -11,7 +11,7 @@
  * under the License. 
  * The Original Code is Openbravo ERP. 
  * The Initial Developer of the Original Code is Openbravo SLU 
- * All portions are Copyright (C) 2008-2010 Openbravo SLU 
+ * All portions are Copyright (C) 2008-2012 Openbravo SLU 
  * All Rights Reserved. 
  * Contributor(s):  ______________________________________.
  ************************************************************************
@@ -19,10 +19,29 @@
 
 package org.openbravo.erpCommon.ad_process;
 
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
+import javax.servlet.ServletException;
+
+import org.apache.log4j.Logger;
+import org.hibernate.criterion.Restrictions;
+import org.openbravo.dal.core.OBContext;
+import org.openbravo.dal.service.OBCriteria;
+import org.openbravo.dal.service.OBDal;
 import org.openbravo.database.ConnectionProvider;
 import org.openbravo.erpCommon.businessUtility.EMail;
 import org.openbravo.erpCommon.utility.SequenceIdData;
 import org.openbravo.erpCommon.utility.Utility;
+import org.openbravo.erpCommon.utility.poc.EmailManager;
+import org.openbravo.model.ad.access.User;
+import org.openbravo.model.ad.access.UserRoles;
+import org.openbravo.model.ad.alert.AlertRecipient;
+import org.openbravo.model.ad.alert.AlertRule;
+import org.openbravo.model.ad.system.Client;
+import org.openbravo.model.common.enterprise.EmailServerConfiguration;
 import org.openbravo.scheduling.Process;
 import org.openbravo.scheduling.ProcessBundle;
 import org.openbravo.scheduling.ProcessLogger;
@@ -31,6 +50,8 @@
 
 public class AlertProcess implements Process {
 
+  private static final Logger log4j = Logger.getLogger(AlertProcess.class);
+
   private static int counter = 0;
 
   private ConnectionProvider connection;
@@ -112,31 +133,220 @@
 
       if (insertions > 0) {
         // Send mail
-        AlertProcessData[] mail = AlertProcessData.prepareMails(conn, alertRule.adAlertruleId);
 
-        if (mail != null) {
-          for (int i = 0; i < mail.length; i++) {
-            String head = Utility.messageBD(conn, "AlertMailHead", mail[i].adLanguage) + "\n";
-            EMail email = new EMail(null, mail[i].smtphost, mail[i].mailfrom, mail[i].mailto,
-                "[OB Alert] " + alertRule.name, head + msg);
-            String pwd = "";
+        // There are two ways of sending the email, depending if the SMTP server is configured in
+        // the 'Client' tab or in the 'Email Configuration' tab.
+        // The SMTP server configured in 'Client' tab way is @Deprecated in 3.0
+
+        final String adClientId = alert[0].adClientId;
+        final String adOrgId = alert[0].adOrgId;
+        final String deprecatedMailHost = OBDal.getInstance().get(Client.class, adClientId)
+            .getMailHost();
+        boolean isDeprecatedMode = false;
+        if (deprecatedMailHost != null && !"".equals(deprecatedMailHost)) {
+          isDeprecatedMode = true;
+        }
+
+        if (!isDeprecatedMode) {
+          // Since it is a background process and each email sending takes some time (may vary
+          // depending on the server), they are sent at the end, once all data is recollected, in
+          // order to minimize problems/inconsistencies/NPE if the 'Alerts', 'AlertRecipient',
+          // 'User' or 'UserRoles' columns change in the middle of the process.
+          final List<Object[]> emailsToSendList = new ArrayList<Object[]>();
+          OBContext.setAdminMode();
+          try {
+            // Getting the SMTP server parameters
+            OBCriteria<EmailServerConfiguration> mailConfigCriteria = OBDal.getInstance()
+                .createCriteria(EmailServerConfiguration.class);
+            if (OBContext.getOBContext().isInAdministratorMode()) {
+              mailConfigCriteria.setFilterOnReadableClients(false);
+              mailConfigCriteria.setFilterOnReadableOrganization(false);
+            }
+            mailConfigCriteria.add(Restrictions.eq(EmailServerConfiguration.PROPERTY_CLIENT, OBDal
+                .getInstance().get(Client.class, adClientId)));
+            final List<EmailServerConfiguration> mailConfigList = mailConfigCriteria.list();
+
+            if (mailConfigList.size() == 0) {
+              log4j.error("No Poc configuration found for this client.");
+            } else {
+              // TODO: There should be a mechanism to select the desired Email server configuration
+              // for alerts, until then, first search for the current organization (and use the
+              // first returned one), then for organization '0' (and use the first returned one) and
+              // then for any other of the organization tree where current organization belongs to
+              // (and use the first returned one).
+              EmailServerConfiguration mailConfig = null;
+
+              for (EmailServerConfiguration currentOrgConfig : mailConfigList) {
+                if (adOrgId.equals(currentOrgConfig.getOrganization().getId())) {
+                  mailConfig = currentOrgConfig;
+                  break;
+                }
+              }
+              if (mailConfig == null) {
+                for (EmailServerConfiguration zeroOrgConfig : mailConfigList) {
+                  if ("0".equals(zeroOrgConfig.getOrganization().getId())) {
+                    mailConfig = zeroOrgConfig;
+                    break;
+                  }
+                }
+              }
+              if (mailConfig == null) {
+                mailConfig = mailConfigList.get(0);
+              }
+
+              OBCriteria<AlertRecipient> alertRecipientsCriteria = OBDal.getInstance()
+                  .createCriteria(AlertRecipient.class);
+              if (OBContext.getOBContext().isInAdministratorMode()) {
+                alertRecipientsCriteria.setFilterOnReadableClients(false);
+                alertRecipientsCriteria.setFilterOnReadableOrganization(false);
+              }
+              alertRecipientsCriteria.add(Restrictions.eq(AlertRecipient.PROPERTY_ALERTRULE, OBDal
+                  .getInstance().get(AlertRule.class, alertRule.adAlertruleId)));
+
+              final List<AlertRecipient> alertRecipientsList = alertRecipientsCriteria.list();
+
+              // Mechanism to avoid several mails are sent to the same email address for the same
+              // alert
+              List<String> alreadySentToList = new ArrayList<String>();
+              for (AlertRecipient currentAlertRecipient : alertRecipientsList) {
+                // If 'Send EMail' option is not checked, we are done for this alert recipient
+                if (!currentAlertRecipient.isSendEMail()) {
+                  continue;
+                }
+
+                final List<User> usersList = new ArrayList<User>();
+                // If there is a 'Contact' established, take it, if not, take all users for the
+                // selected 'Role'
+                if (currentAlertRecipient.getUserContact() != null) {
+                  usersList.add(currentAlertRecipient.getUserContact());
+                } else {
+                  OBCriteria<UserRoles> userRolesCriteria = OBDal.getInstance().createCriteria(
+                      UserRoles.class);
+                  if (OBContext.getOBContext().isInAdministratorMode()) {
+                    userRolesCriteria.setFilterOnReadableClients(false);
+                    userRolesCriteria.setFilterOnReadableOrganization(false);
+                  }
+                  userRolesCriteria.add(Restrictions.eq(AlertRecipient.PROPERTY_ROLE,
+                      currentAlertRecipient.getRole()));
+                  userRolesCriteria.add(Restrictions.eq(AlertRecipient.PROPERTY_CLIENT,
+                      currentAlertRecipient.getClient()));
+                  final List<UserRoles> userRolesList = userRolesCriteria.list();
+                  for (UserRoles currenUserRole : userRolesList) {
+                    usersList.add(currenUserRole.getUserContact());
+                  }
+                }
+
+                // If there are no 'Contact' for send the email, we are done for this alert
+                // recipient
+                if (usersList.size() == 0) {
+                  continue;
+                }
+
+                // For each 'User', get the email parameters (to, subject, body, ...) and store them
+                // to send the email at the end
+                for (User targetUser : usersList) {
+                  if (targetUser == null) {
+                    continue;
+                  }
+                  final Client targetUserClient = targetUser.getClient();
+                  final String targetUserClientLanguage = (targetUserClient.getLanguage() != null ? targetUserClient
+                      .getLanguage().getLanguage() : null);
+                  final String targetUserEmail = targetUser.getEmail();
+                  if (targetUserEmail == null) {
+                    continue;
+                  }
+
+                  boolean repeatedEmail = false;
+                  for (String alreadySentTo : alreadySentToList) {
+                    if (targetUserEmail.equals(alreadySentTo)) {
+                      repeatedEmail = true;
+                      break;
+                    }
+                  }
+                  if (repeatedEmail) {
+                    continue;
+                  }
+                  alreadySentToList.add(targetUserEmail);
+
+                  final String host = mailConfig.getSmtpServer();
+                  final Boolean auth = mailConfig.isSMTPAuthentification();
+                  final String username = mailConfig.getSmtpServerAccount();
+                  final String password = FormatUtilities.encryptDecrypt(
+                      mailConfig.getSmtpServerPassword(), false);
+                  final String connSecurity = mailConfig.getSmtpConnectionSecurity();
+                  final int port = mailConfig.getSmtpPort().intValue();
+                  final String senderAddress = mailConfig.getSmtpServerSenderAddress();
+                  final String recipientTO = targetUserEmail;
+                  final String recipientCC = null;
+                  final String recipientBCC = null;
+                  final String replyTo = null;
+                  final String subject = "[OB Alert] " + alertRule.name;
+                  final String content = Utility.messageBD(conn, "AlertMailHead",
+                      targetUserClientLanguage) + "\n" + msg;
+                  final String contentType = "text/plain; charset=utf-8";
+                  final List<File> attachments = null;
+                  final Date sentDate = null;
+                  final List<String> headerExtras = null;
+
+                  final Object[] email = { host, auth, username, password, connSecurity, port,
+                      senderAddress, recipientTO, recipientCC, recipientBCC, replyTo, subject,
+                      content, contentType, attachments, sentDate, headerExtras };
+                  emailsToSendList.add(email);
+                }
+              }
+            }
+          } catch (Exception e) {
+            throw new JobExecutionException(e.getMessage(), e);
+          } finally {
+            OBContext.restorePreviousMode();
+          }
+          // Send all the stored emails
+          for (Object[] emailToSend : emailsToSendList) {
             try {
-              pwd = FormatUtilities.encryptDecrypt(mail[i].requestuserpw, false);
-            } catch (Exception e) {
-              logger.log("Error getting user password to send the mail: " + e.getMessage() + "\n");
-              logger.log("Check email password settings in Client configuration.\n");
-              continue;
+              EmailManager.sendEmail((String) emailToSend[0], (Boolean) emailToSend[1],
+                  (String) emailToSend[2], (String) emailToSend[3], (String) emailToSend[4],
+                  ((Number) emailToSend[5]).intValue(), (String) emailToSend[6],
+                  (String) emailToSend[7], (String) emailToSend[8], (String) emailToSend[9],
+                  (String) emailToSend[10], (String) emailToSend[11], (String) emailToSend[12],
+                  (String) emailToSend[13], (List<File>) emailToSend[14], (Date) emailToSend[15],
+                  (List<String>) emailToSend[16]);
+            } catch (Exception exception) {
+              log4j.error(exception);
+              final String exceptionClass = exception.getClass().toString().replace("class ", "");
+              String exceptionString = "Problems while sending the email" + exception;
+              exceptionString = exceptionString.replace(exceptionClass, "");
+              throw new ServletException(exceptionString);
             }
-            if (!pwd.equals("")) {
-              email.setEMailUser(mail[i].requestuser, pwd);
-              if ("OK".equals(email.send())) {
-                logger.log("Mail sent ok.");
+          }
+        } else {
+          // @Deprecated : This full "else" statement is deprecated.
+          AlertProcessData[] mail = AlertProcessData.prepareMails(conn, alertRule.adAlertruleId);
+
+          if (mail != null) {
+            for (int i = 0; i < mail.length; i++) {
+              String head = Utility.messageBD(conn, "AlertMailHead", mail[i].adLanguage) + "\n";
+              EMail email = new EMail(null, mail[i].smtphost, mail[i].mailfrom, mail[i].mailto,
+                  "[OB Alert] " + alertRule.name, head + msg);
+              String pwd = "";
+              try {
+                pwd = FormatUtilities.encryptDecrypt(mail[i].requestuserpw, false);
+              } catch (Exception e) {
+                logger
+                    .log("Error getting user password to send the mail: " + e.getMessage() + "\n");
+                logger.log("Check email password settings in Client configuration.\n");
+                continue;
+              }
+              if (!pwd.equals("")) {
+                email.setEMailUser(mail[i].requestuser, pwd);
+                if ("OK".equals(email.send())) {
+                  logger.log("Mail sent ok.");
+                } else {
+                  logger.log("Error sending mail.");
+                }
               } else {
-                logger.log("Error sending mail.");
+                logger
+                    .log("Sending email skipped. Check email password settings in Client configuration.\n");
               }
-            } else {
-              logger
-                  .log("Sending email skipped. Check email password settings in Client configuration.\n");
             }
           }
         }
--- a/src/org/openbravo/erpCommon/businessUtility/EMail.java	Wed Jan 25 18:20:11 2012 +0100
+++ b/src/org/openbravo/erpCommon/businessUtility/EMail.java	Wed Jan 25 20:32:54 2012 +0100
@@ -43,6 +43,10 @@
 
 import com.sun.mail.smtp.SMTPMessage;
 
+/**
+ * Since Openbravo 3.0MP9, related to @deprecated code in PrintController.java
+ */
+@Deprecated
 public class EMail {
   static Logger log4j = Logger.getLogger(EMail.class);
   private String g_from;
--- a/src/org/openbravo/erpCommon/utility/poc/EmailManager.java	Wed Jan 25 18:20:11 2012 +0100
+++ b/src/org/openbravo/erpCommon/utility/poc/EmailManager.java	Wed Jan 25 20:32:54 2012 +0100
@@ -15,14 +15,20 @@
  */
 package org.openbravo.erpCommon.utility.poc;
 
+import java.io.File;
+import java.util.Date;
+import java.util.List;
 import java.util.Properties;
 
 import javax.activation.DataHandler;
 import javax.activation.DataSource;
 import javax.activation.FileDataSource;
+import javax.mail.Address;
+import javax.mail.Authenticator;
 import javax.mail.Message;
 import javax.mail.MessagingException;
 import javax.mail.Multipart;
+import javax.mail.PasswordAuthentication;
 import javax.mail.Session;
 import javax.mail.Transport;
 import javax.mail.internet.AddressException;
@@ -39,9 +45,152 @@
 public class EmailManager {
   private static Logger log4j = Logger.getLogger(EmailManager.class);
 
-  /*
-	 * 
-	 */
+  public static void sendEmail(String host, Boolean auth, String username, String password,
+      String connSecurity, int port, String senderAddress, String recipientTO, String recipientCC,
+      String recipientBCC, String replyTo, String subject, String content, String contentType,
+      List<File> attachments, Date sentDate, List<String> headerExtras) throws Exception {
+    try {
+      Properties props = new Properties();
+
+      if (log4j.isDebugEnabled()) {
+        props.put("mail.debug", "true");
+      }
+      props.put("mail.transport.protocol", "smtp");
+      props.put("mail.smtp.host", host);
+      props.put("mail.smtp.port", port);
+
+      if (connSecurity != null) {
+        connSecurity = connSecurity.replaceAll(", *", ",");
+        String[] connSecurityArray = connSecurity.split(",");
+        for (int i = 0; i < connSecurityArray.length; i++) {
+          if ("STARTTLS".equals(connSecurityArray[i])) {
+            props.put("mail.smtp.starttls.enable", "true");
+          }
+          if ("SSL".equals(connSecurityArray[i])) {
+            props.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
+            props.put("mail.smtp.socketFactory.fallback", "false");
+            props.put("mail.smtp.socketFactory.port", port);
+          }
+        }
+      }
+
+      Session mailSession = null;
+      if (auth) {
+        props.put("mail.smtp.auth", "true");
+        Authenticator authentification = new SMTPAuthenticator(username, password);
+        mailSession = Session.getInstance(props, authentification);
+      } else {
+        mailSession = Session.getInstance(props, null);
+      }
+
+      Transport transport = mailSession.getTransport();
+
+      MimeMessage message = new MimeMessage(mailSession);
+
+      message.setFrom(new InternetAddress(senderAddress));
+
+      if (recipientTO != null) {
+        recipientTO = recipientTO.replaceAll(";", ",");
+        message.setRecipients(Message.RecipientType.TO, InternetAddress.parse(recipientTO));
+      }
+      if (recipientCC != null) {
+        recipientCC = recipientCC.replaceAll(";", ",");
+        message.setRecipients(Message.RecipientType.CC, InternetAddress.parse(recipientCC));
+      }
+      if (recipientBCC != null) {
+        recipientBCC = recipientBCC.replaceAll(";", ",");
+        message.setRecipients(Message.RecipientType.BCC, InternetAddress.parse(recipientBCC));
+      }
+
+      if (replyTo != null) {
+        replyTo = replyTo.replaceAll(";", ",");
+        replyTo = replyTo.replaceAll(", *", ",");
+        String[] replyToArray = replyTo.split(",");
+
+        Address[] replyToAddresses = new InternetAddress[replyToArray.length];
+        for (int i = 0; i < replyToArray.length; i++) {
+          replyToAddresses[i] = new InternetAddress(replyToArray[i]);
+        }
+
+        message.setReplyTo(replyToAddresses);
+      }
+
+      if (subject != null) {
+        message.setSubject(subject);
+      }
+      if (sentDate != null) {
+        message.setSentDate(sentDate);
+      }
+
+      if (headerExtras != null && headerExtras.size() > 0) {
+        String[] headerExtrasArray = headerExtras.toArray(new String[headerExtras.size()]);
+        for (int i = 0; i < headerExtrasArray.length - 1; i++) {
+          message.addHeader(headerExtrasArray[i], headerExtrasArray[i + 1]);
+          i++;
+        }
+      }
+
+      if (attachments != null && attachments.size() > 0) {
+        Multipart multipart = new MimeMultipart();
+
+        if (content != null) {
+          MimeBodyPart messagePart = new MimeBodyPart();
+          if (contentType == null) {
+            contentType = "text/plain; charset=utf-8";
+          }
+          messagePart.setContent(content, contentType);
+          multipart.addBodyPart(messagePart);
+        }
+
+        MimeBodyPart attachmentPart = null;
+        for (File attachmentFile : attachments) {
+          attachmentPart = new MimeBodyPart();
+          if (attachmentFile.exists() && attachmentFile.canRead()) {
+            attachmentPart.attachFile(attachmentFile);
+            multipart.addBodyPart(attachmentPart);
+          }
+        }
+
+        message.setContent(multipart);
+      } else {
+        if (content != null) {
+          if (contentType == null) {
+            contentType = "text/plain; charset=utf-8";
+          }
+          message.setContent(content, contentType);
+        }
+      }
+
+      transport.connect();
+      transport.sendMessage(message, message.getRecipients(Message.RecipientType.TO));
+      transport.close();
+    } catch (final AddressException exception) {
+      log4j.error(exception);
+      throw new ServletException(exception);
+    } catch (final MessagingException exception) {
+      log4j.error(exception);
+      throw new ServletException(exception.getMessage(), exception);
+    }
+  }
+
+  private static class SMTPAuthenticator extends javax.mail.Authenticator {
+    private String _username;
+    private String _password;
+
+    public SMTPAuthenticator(String username, String password) {
+      _username = username;
+      _password = password;
+    }
+
+    public PasswordAuthentication getPasswordAuthentication() {
+      return new PasswordAuthentication(_username, _password);
+    }
+  }
+
+  /**
+   * Since Openbravo 3.0MP9 only {@link #sendEmail()} is used for the full email sending cycle
+   */
+  @Deprecated
   public static Session newMailSession(ConnectionProvider connectionProvider, String clientId,
       String adOrgId) throws PocException, ServletException {
     PocConfigurationData configurations[];
@@ -94,9 +243,10 @@
     return Session.getInstance(props, authenticator);
   }
 
-  /*
-	 * 
-	 */
+  /**
+   * Since Openbravo 3.0MP9 only {@link #sendEmail()} is used for the full email sending cycle
+   */
+  @Deprecated
   public void sendSimpleEmail(Session session, String from, String to, String bcc, String subject,
       String body, String attachmentFileLocations) throws PocException {
     try {
--- a/src/org/openbravo/erpCommon/utility/reporting/printing/PrintController.java	Wed Jan 25 18:20:11 2012 +0100
+++ b/src/org/openbravo/erpCommon/utility/reporting/printing/PrintController.java	Wed Jan 25 20:32:54 2012 +0100
@@ -26,23 +26,10 @@
 import java.util.Date;
 import java.util.HashMap;
 import java.util.Iterator;
+import java.util.List;
 import java.util.Map;
 import java.util.Vector;
 
-import javax.activation.DataHandler;
-import javax.activation.DataSource;
-import javax.activation.FileDataSource;
-import javax.mail.Address;
-import javax.mail.Message;
-import javax.mail.MessagingException;
-import javax.mail.Multipart;
-import javax.mail.Session;
-import javax.mail.Transport;
-import javax.mail.internet.AddressException;
-import javax.mail.internet.InternetAddress;
-import javax.mail.internet.MimeBodyPart;
-import javax.mail.internet.MimeMessage;
-import javax.mail.internet.MimeMultipart;
 import javax.servlet.ServletConfig;
 import javax.servlet.ServletException;
 import javax.servlet.ServletOutputStream;
@@ -56,15 +43,17 @@
 import org.apache.commons.fileupload.FileItem;
 import org.codehaus.jettison.json.JSONException;
 import org.codehaus.jettison.json.JSONObject;
+import org.hibernate.criterion.Restrictions;
 import org.openbravo.base.exception.OBException;
 import org.openbravo.base.secureApp.HttpSecureAppServlet;
 import org.openbravo.base.secureApp.VariablesSecureApp;
+import org.openbravo.dal.service.OBCriteria;
+import org.openbravo.dal.service.OBDal;
 import org.openbravo.erpCommon.utility.OBError;
 import org.openbravo.erpCommon.utility.SequenceIdData;
 import org.openbravo.erpCommon.utility.Utility;
 import org.openbravo.erpCommon.utility.poc.EmailManager;
 import org.openbravo.erpCommon.utility.poc.EmailType;
-import org.openbravo.erpCommon.utility.poc.PocException;
 import org.openbravo.erpCommon.utility.reporting.DocumentType;
 import org.openbravo.erpCommon.utility.reporting.Report;
 import org.openbravo.erpCommon.utility.reporting.Report.OutputTypeEnum;
@@ -74,6 +63,9 @@
 import org.openbravo.erpCommon.utility.reporting.TemplateInfo;
 import org.openbravo.erpCommon.utility.reporting.TemplateInfo.EmailDefinition;
 import org.openbravo.exception.NoConnectionAvailableException;
+import org.openbravo.model.ad.system.Client;
+import org.openbravo.model.common.enterprise.EmailServerConfiguration;
+import org.openbravo.utils.FormatUtilities;
 import org.openbravo.xmlEngine.XmlDocument;
 
 import com.lowagie.text.Document;
@@ -643,9 +635,8 @@
   }
 
   void sendDocumentEmail(Report report, VariablesSecureApp vars, Vector<Object> object,
-      PocData documentData, String senderAddess, HashMap<String, Boolean> checks)
+      PocData documentData, String senderAddress, HashMap<String, Boolean> checks)
       throws IOException, ServletException {
-    final String documentId = report.getDocumentId();
     final String attachmentFileLocation = report.getTargetLocation();
 
     final String ourReference = report.getOurReference();
@@ -715,113 +706,112 @@
     emailBody = emailBody.replaceAll("@cus_nam@", contactName);
     emailBody = emailBody.replaceAll("@sal_nam@", salesrepName);
 
-    try {
+    OBCriteria<EmailServerConfiguration> mailConfigCriteria = OBDal.getInstance().createCriteria(
+        EmailServerConfiguration.class);
+    mailConfigCriteria.add(Restrictions.eq(EmailServerConfiguration.PROPERTY_CLIENT, OBDal
+        .getInstance().get(Client.class, vars.getClient())));
+    final List<EmailServerConfiguration> mailConfigList = mailConfigCriteria.list();
 
-      final Session session = EmailManager
-          .newMailSession(this, vars.getClient(), report.getOrgId());
+    if (mailConfigList.size() == 0) {
+      throw new ServletException("No Poc configuration found for this client.");
+    }
 
-      final Message message = new MimeMessage(session);
+    // TODO: There should be a mechanism to select the desired Email server configuration, until
+    // then, first search for the current organization (and use the first returned one), then for
+    // organization '0' (and use the first returned one) and then for any other of the organization
+    // tree where current organization belongs to (and use the first returned one).
+    EmailServerConfiguration mailConfig = null;
 
-      Address[] address = new InternetAddress[1];
-      address[0] = new InternetAddress(salesrepEmail);
-      message.setReplyTo(address);
-      message.setFrom(new InternetAddress(senderAddess));
-      message.addRecipient(Message.RecipientType.TO, new InternetAddress(contactEmail));
-
-      // message.addRecipient(Message.RecipientType.BCC, new InternetAddress(salesrepEmail));
-
-      if (userEmail != null && userEmail.length() > 0)
-        message.addRecipient(Message.RecipientType.BCC, new InternetAddress(userEmail));
-
-      message.setSubject(emailSubject);
-
-      // Content consists of 2 parts, the message body and the attachment
-      // We therefor use a multipart message
-      final Multipart multipart = new MimeMultipart();
-
-      // Create the message part
-      MimeBodyPart messageBodyPart = new MimeBodyPart();
-      messageBodyPart.setText(emailBody);
-      multipart.addBodyPart(messageBodyPart);
-
-      // Create the attachment part
-      messageBodyPart = new MimeBodyPart();
-      final DataSource source = new FileDataSource(attachmentFileLocation);
-      messageBodyPart.setDataHandler(new DataHandler(source));
-      messageBodyPart.setFileName(attachmentFileLocation.substring(attachmentFileLocation
-          .lastIndexOf("/") + 1));
-      multipart.addBodyPart(messageBodyPart);
-
-      // Add aditional attached documents
-      if (object != null) {
-        final Vector<Object> vector = (Vector<Object>) object;
-        for (int i = 0; i < vector.size(); i++) {
-          final AttachContent content = (AttachContent) vector.get(i);
-          final File file = prepareFile(content);
-          messageBodyPart = new MimeBodyPart();
-          messageBodyPart.attachFile(file);
-          multipart.addBodyPart(messageBodyPart);
+    for (EmailServerConfiguration currentOrgConfig : mailConfigList) {
+      if (vars.getOrg().equals(currentOrgConfig.getOrganization().getId())) {
+        mailConfig = currentOrgConfig;
+        break;
+      }
+    }
+    if (mailConfig == null) {
+      for (EmailServerConfiguration zeroOrgConfig : mailConfigList) {
+        if ("0".equals(zeroOrgConfig.getOrganization().getId())) {
+          mailConfig = zeroOrgConfig;
+          break;
         }
       }
+    }
+    if (mailConfig == null) {
+      mailConfig = mailConfigList.get(0);
+    }
 
-      message.setContent(multipart);
+    final String host = mailConfig.getSmtpServer();
+    Boolean auth = true;
+    if ("N".equals(mailConfig.isSMTPAuthentification())) {
+      auth = false;
+    }
+    final String username = mailConfig.getSmtpServerAccount();
+    final String password = FormatUtilities.encryptDecrypt(mailConfig.getSmtpServerPassword(),
+        false);
+    final String connSecurity = mailConfig.getSmtpConnectionSecurity();
+    final int port = mailConfig.getSmtpPort().intValue();
+    final String recipientTO = contactEmail;
+    final String recipientCC = null;
+    String recipientBCC = null;
+    if (userEmail != null && userEmail.length() > 0) {
+      recipientBCC = userEmail;
+    }
+    final String replyTo = salesrepEmail;
+    final String contentType = "text/plain; charset=utf-8";
 
-      // Send the email
-      Transport.send(message);
+    List<File> attachments = new ArrayList<File>();
+    attachments.add(new File(attachmentFileLocation));
 
-      final String clientId = vars.getClient();
-      final String organizationId = vars.getOrg();
-      final String userId = vars.getUser();
-      final String from = salesrepEmail;
-      final String to = contactEmail;
-      final String cc = "";
-      String bcc = salesrepEmail;
-      if (userEmail != null && userEmail.length() > 0)
-        bcc = bcc + "; " + userEmail;
-      final String subject = emailSubject;
-      final String body = emailBody;
-      final String dateOfEmail = Utility.formatDate(new Date(), "yyyyMMddHHmmss");
-      final String bPartnerId = report.getBPartnerId();
+    if (object != null) {
+      final Vector<Object> vector = (Vector<Object>) object;
+      for (int i = 0; i < vector.size(); i++) {
+        final AttachContent objContent = (AttachContent) vector.get(i);
+        final File file = prepareFile(objContent);
+        attachments.add(file);
+      }
+    }
 
-      // Store the email in the database
-      Connection conn = null;
+    try {
+      EmailManager.sendEmail(host, auth, username, password, connSecurity, port, senderAddress,
+          recipientTO, recipientCC, recipientBCC, replyTo, emailSubject, emailBody, contentType,
+          attachments, null, null);
+    } catch (Exception exception) {
+      log4j.error(exception);
+      final String exceptionClass = exception.getClass().toString().replace("class ", "");
+      String exceptionString = "Problems while sending the email" + exception;
+      exceptionString = exceptionString.replace(exceptionClass, "");
+      throw new ServletException(exceptionString);
+    }
+
+    // Store the email in the database
+    Connection conn = null;
+    try {
+      conn = this.getTransactionConnection();
+
+      // First store the email message
+      final String newEmailId = SequenceIdData.getUUID();
+      if (log4j.isDebugEnabled())
+        log4j.debug("New email id: " + newEmailId);
+
+      EmailData.insertEmail(conn, this, newEmailId, vars.getClient(), vars.getOrg(),
+          vars.getUser(), EmailType.OUTGOING.getStringValue(), replyTo, recipientTO, recipientCC,
+          recipientBCC, Utility.formatDate(new Date(), "yyyyMMddHHmmss"), emailSubject, emailBody,
+          report.getBPartnerId(),
+          ToolsData.getTableId(this, report.getDocumentType().getTableName()),
+          documentData.documentId);
+
+      releaseCommitConnection(conn);
+    } catch (final NoConnectionAvailableException exception) {
+      log4j.error(exception);
+      throw new ServletException(exception);
+    } catch (final SQLException exception) {
+      log4j.error(exception);
       try {
-        conn = this.getTransactionConnection();
-
-        // First store the email message
-        final String newEmailId = SequenceIdData.getUUID();
-        if (log4j.isDebugEnabled())
-          log4j.debug("New email id: " + newEmailId);
-
-        EmailData.insertEmail(conn, this, newEmailId, clientId, organizationId, userId,
-            EmailType.OUTGOING.getStringValue(), from, to, cc, bcc, dateOfEmail, subject, body,
-            bPartnerId, ToolsData.getTableId(this, report.getDocumentType().getTableName()),
-            documentData.documentId);
-
-        releaseCommitConnection(conn);
-      } catch (final NoConnectionAvailableException exception) {
-        log4j.error(exception);
-        throw new ServletException(exception);
-      } catch (final SQLException exception) {
-        log4j.error(exception);
-        try {
-          releaseRollbackConnection(conn);
-        } catch (final Exception ignored) {
-        }
-
-        throw new ServletException(exception);
+        releaseRollbackConnection(conn);
+      } catch (final Exception ignored) {
       }
 
-    } catch (final PocException exception) {
-      log4j.error(exception);
       throw new ServletException(exception);
-    } catch (final AddressException exception) {
-      log4j.error(exception);
-      throw new ServletException(exception);
-    } catch (final MessagingException exception) {
-      log4j.error(exception);
-      throw new ServletException("problems with the SMTP server configuration: "
-          + exception.getMessage(), exception);
     }
   }