From ffca70fbeaa38802ae08a773fa3e231e2a0df0ae Mon Sep 17 00:00:00 2001 From: Vova Perebykivskiy Date: Wed, 11 Nov 2015 15:45:24 +0200 Subject: [PATCH] Add documentation about E-mail sending functionality. Update JUnit version. Code refactoring. Imports optimizations. Changes to UI of E-mail Templates page. New values for i18n. Validations of E-mail functionality. --- HACKING.rst | 4 +- doc/src/user/en/18-connectors.rst | 69 +++++++++++++++- .../business/common/Configuration.java | 14 ++-- .../email/daos/EmailNotificationDAO.java | 1 - .../libreplan-business-spring-config.xml | 4 +- .../org/libreplan/importers/SendEmail.java | 80 +++++++++++++++++-- .../web/common/ConfigurationController.java | 42 +++++----- .../web/email/EmailNotificationModel.java | 1 + .../web/email/EmailTemplateController.java | 7 +- .../src/main/resources/i18n/keys.pot | 41 +++++++++- .../main/webapp/common/_editJobScheduling.zul | 2 +- .../src/main/webapp/email/email_templates.zul | 56 ++++++++++--- .../importers/TimSoapClientTest.java | 5 +- pom.xml | 4 +- 14 files changed, 267 insertions(+), 63 deletions(-) diff --git a/HACKING.rst b/HACKING.rst index 4e2d7efdf..c1e6e25ee 100644 --- a/HACKING.rst +++ b/HACKING.rst @@ -506,9 +506,9 @@ example: mvn -Ddefault.passwordsControl=false -Ddefault.exampleUsersDisabled=false clean install -* Set *default.emailSendingDisabled* to true:: +* Set *default.emailSendingEnabled* to false:: - mvn -Ddefault.emailSendingDisabled=true clean install + mvn -Ddefault.emailSendingEnabled=false clean install Tests ----- diff --git a/doc/src/user/en/18-connectors.rst b/doc/src/user/en/18-connectors.rst index 7206ec0fa..ca302cb57 100644 --- a/doc/src/user/en/18-connectors.rst +++ b/doc/src/user/en/18-connectors.rst @@ -4,7 +4,7 @@ Connectors .. contents:: Connectors are Libreplan client applications that could be used to communicate with (web) servers to get -data, process and store them. At this moment there are two connectors, JIRA connector and Tim Enterprise Connector. +data, process and store them. At this moment there are three connectors, JIRA connector, Tim Enterprise Connector and E-mail Connector. Configuration ============= @@ -171,9 +171,9 @@ in Tim Enterprise server. Scheduling export ------------------ -Export process can also take place through the scheduler. Go to ``Job scheduling`` screen. +Export process can also take place through the scheduler. Go to ``Job Scheduling`` screen. In that screen you can configure a Tim Export ``job``. The ``job`` searches for last exported -time sheets in the database and re-export them accordingly. see also the Scheduler manual. +time sheets in the database and re-export them accordingly. See also the Scheduler manual. Import ------ @@ -211,5 +211,66 @@ assumed to be a valid ``Exception type`` but the total duration is the sum of al Contrary to the Libreplan, in Tim Enterprise, the ``total duration`` in case that the worker is on holiday means the worker is not available for that ``total duration``. But in Libreplan if the worker is on holiday the total duration should be ``Zero``. -The Tim connector also takes care of this translation. +The Tim connector also takes care of this translation. + +E-mail connector +============== +E-mail is a method of exchanging digital messages from an author to one or more recipients. + +E-mail connector can be used to set Simple Main Transfer Protocol (SMTP) server connection properties. + +The *E-mail connector* should be configured properly before being used. + +Configuration +------------- + +From the configuration's ``Main Settings`` screen choose the tab ``Connectors``. +In the connectors screen select the E-mail connector from the ``pull-down`` list. A ``property editor screen`` +is displayed now. + +In this screen you can configure the following property values: + +* ``Activated``: Y/N, whether you want to use the E-mail connector or not. Default is ``N``. +* ``Protocol``: type of SMTP protocol. +* ``Host``: the absolute path to SMTP server. +* ``Port``: port of SMTP server. +* ``From address``: e-mail address of messages sender. +* ``Username``: username for SMTP server. +* ``Password``: password for SMTP server. + +Finally click the ``Test connection`` button to test if you are able to connect to +SMTP server and that your configurations are right. + +Edit E-mail template +-------------------- + +From the project window ``Configuration`` and then ``Edit E-mail Templates`` you are able to modify E-mail templates of +messages. + +You are able to choose: + +* Template language +* Template type +* E-mail subject +* Template contents + +You need to specify language because web application will send e-mail to user in language that user have chosen in +preferences. +You need to choose template type, type is user role, it means that this e-mail will be send only to users who are in\ +selected role (type). +You need to set e-mail subject. Subject - a brief summary of the topic of the message. +You need to set e-mail contents. Any information that you want to send to user. Also there are some keywords that you +may use in message; web application will parse it and set a new value instead of keyword. + +Scheduling e-mails +------------------ + +Sending e-mails process can take place only through the scheduler. Go to ``Configuration`` then ``Job Scheduling`` +screen. +In that screen you can configure a e-mail sending ``job``. The ``job`` is taking a list of e-mail notifications, +gathering data and sending it to user`s e-mail. See also the Scheduler manual. + + +.. NOTE:: +The success or failure information would be displayed in pop-up window. \ No newline at end of file diff --git a/libreplan-business/src/main/java/org/libreplan/business/common/Configuration.java b/libreplan-business/src/main/java/org/libreplan/business/common/Configuration.java index 680de01af..90709ff25 100644 --- a/libreplan-business/src/main/java/org/libreplan/business/common/Configuration.java +++ b/libreplan-business/src/main/java/org/libreplan/business/common/Configuration.java @@ -47,7 +47,7 @@ public class Configuration { private Boolean exampleUsersDisabled; - private Boolean emailSendingDisabled; + private Boolean emailSendingEnabled; private Configuration() { } @@ -89,14 +89,14 @@ public class Configuration { /** * Returns the value of E-mail sending disabled compilation option */ - public static boolean isEmailSendingDisabled(){ - return BooleanUtils.isNotFalse(singleton.getEmailSendingDisabled()); + public static boolean isEmailSendingEnabled(){ + return BooleanUtils.isNotFalse(singleton.getEmailSendingEnabled()); } - public Boolean getEmailSendingDisabled(){ - return emailSendingDisabled; + public Boolean getEmailSendingEnabled(){ + return emailSendingEnabled; } - public void setEmailSendingDisabled(Boolean emailSendingDisabled){ - this.emailSendingDisabled = emailSendingDisabled; + public void setEmailSendingEnabled(Boolean emailSendingEnabled){ + this.emailSendingEnabled = emailSendingEnabled; } } diff --git a/libreplan-business/src/main/java/org/libreplan/business/email/daos/EmailNotificationDAO.java b/libreplan-business/src/main/java/org/libreplan/business/email/daos/EmailNotificationDAO.java index 2aad7ebc9..e67a9047b 100644 --- a/libreplan-business/src/main/java/org/libreplan/business/email/daos/EmailNotificationDAO.java +++ b/libreplan-business/src/main/java/org/libreplan/business/email/daos/EmailNotificationDAO.java @@ -46,7 +46,6 @@ public class EmailNotificationDAO extends GenericDAOHibernate ${default.exampleUsersDisabled} - - ${default.emailSendingDisabled} + + ${default.emailSendingEnabled} diff --git a/libreplan-webapp/src/main/java/org/libreplan/importers/SendEmail.java b/libreplan-webapp/src/main/java/org/libreplan/importers/SendEmail.java index e8fdc57c2..d9ee56d32 100644 --- a/libreplan-webapp/src/main/java/org/libreplan/importers/SendEmail.java +++ b/libreplan-webapp/src/main/java/org/libreplan/importers/SendEmail.java @@ -47,6 +47,8 @@ import javax.mail.Session; import javax.mail.PasswordAuthentication; import javax.mail.internet.InternetAddress; import javax.mail.internet.MimeMessage; +import javax.mail.NoSuchProviderException; + import java.util.List; import java.util.Locale; @@ -78,13 +80,14 @@ public class SendEmail implements ISendEmail { private List notifications; private List emailTemplates; - @Override public void sendEmail() { - if ( !Configuration.isEmailSendingDisabled() ){ - notifications = emailNotificationModel.getAll(); - for (int i = 0; i < notifications.size(); i++) composeMessageForUser(notifications.get(i)); - deleteAllNotificationsAfterSending(); + if ( Configuration.isEmailSendingEnabled() == true ){ + if (validConnection() == true){ + notifications = emailNotificationModel.getAll(); + for (int i = 0; i < notifications.size(); i++) composeMessageForUser(notifications.get(i)); + deleteAllNotificationsAfterSending(); + } } } @@ -199,7 +202,9 @@ public class SendEmail implements ISendEmail { Transport.send(message); - }catch (MessagingException e){throw new RuntimeException(e);} + + + } catch (MessagingException e){throw new RuntimeException(e);} } @@ -231,4 +236,67 @@ public class SendEmail implements ISendEmail { return workerList.get(i); return null; } + + private boolean validConnection(){ + List emailConnectorProperties = getEmailConnectorProperties(); + + String protocol = null; + String host = null; + String port = null; + String usrnme = null; + String psswrd = null; + + for (int i = 0; i < emailConnectorProperties.size(); i++){ + switch (i){ + case 1: { + protocol = emailConnectorProperties.get(1).getValue(); + break; + } + case 2: { + host = emailConnectorProperties.get(2).getValue(); + break; + } + case 3: { + port = emailConnectorProperties.get(3).getValue(); + break; + } + case 5: { + usrnme = emailConnectorProperties.get(5).getValue(); + break; + } + case 6: { + psswrd = emailConnectorProperties.get(6).getValue(); + break; + } + } + } + + // Set properties of connection + Properties properties = new Properties(); + + Transport transport = null; + + try { + if (protocol.equals("SMTP")) { + properties.setProperty("mail.smtp.port", port); + properties.setProperty("mail.smtp.host", host); + Session session = Session.getInstance(properties, null); + + transport = session.getTransport("smtp"); + if (usrnme.equals("") && psswrd.equals("")) transport.connect(); + } else if (protocol.equals("STARTTLS")) { + properties.setProperty("mail.smtps.port", port); + properties.setProperty("mail.smtps.host", host); + Session session = Session.getInstance(properties, null); + + transport = session.getTransport("smtps"); + if (!usrnme.equals("") && psswrd != null) transport.connect(host, usrnme, psswrd); + } + if (transport.isConnected()) return true; + + } catch (NoSuchProviderException e) {} + catch (MessagingException e) {} + + return false; + } } diff --git a/libreplan-webapp/src/main/java/org/libreplan/web/common/ConfigurationController.java b/libreplan-webapp/src/main/java/org/libreplan/web/common/ConfigurationController.java index 791c43203..d2187e6cc 100644 --- a/libreplan-webapp/src/main/java/org/libreplan/web/common/ConfigurationController.java +++ b/libreplan-webapp/src/main/java/org/libreplan/web/common/ConfigurationController.java @@ -155,6 +155,8 @@ public class ConfigurationController extends GenericForwardComposer { private Textbox emailPasswordTextbox; + private Textbox emailSenderTextbox; + @Override public void doAfterCompose(Component comp) throws Exception { super.doAfterCompose(comp); @@ -240,8 +242,8 @@ public class ConfigurationController extends GenericForwardComposer { public void save() throws InterruptedException { - if ( getSelectedConnector().getName().equals("E-mail") && emailUsernamePasswordIsEmpty() == true) { - messages.showMessage(Level.ERROR, _("E-mail username/password - empty")); + if ( getSelectedConnector().getName().equals("E-mail") && isEmailFieldsValid() == false) { + messages.showMessage(Level.ERROR, _("Check username/password/sender fields")); } else { ConstraintChecker.isValid(configurationWindow); if (checkValidEntitySequenceRows()) { @@ -1208,13 +1210,16 @@ public class ConfigurationController extends GenericForwardComposer { textbox.setType("password"); } - // Need for method emailUsernamePasswordIsEmpty() + // Need for method validateEmailFields() if ( property.getKey().equals( PredefinedConnectorProperties.EMAIL_USERNAME) ) emailUsernameTextbox = textbox; if ( property.getKey().equals( PredefinedConnectorProperties.EMAIL_PASSWORD) ) emailPasswordTextbox = textbox; + if ( property.getKey().equals( + PredefinedConnectorProperties.EMAIL_SENDER) ) emailSenderTextbox = textbox; + row.appendChild(textbox); } @@ -1285,26 +1290,24 @@ public class ConfigurationController extends GenericForwardComposer { "Only {0} allowed", "Y/N")); } } else if ( key - .equals(PredefinedConnectorProperties.SERVER_URL) - || key.equals(PredefinedConnectorProperties.USERNAME) - || key.equals(PredefinedConnectorProperties.PASSWORD) - || key.equals(PredefinedConnectorProperties.JIRA_HOURS_TYPE) ) { + .equals(PredefinedConnectorProperties.SERVER_URL) || + key.equals(PredefinedConnectorProperties.USERNAME) || + key.equals(PredefinedConnectorProperties.PASSWORD) || + key.equals(PredefinedConnectorProperties.JIRA_HOURS_TYPE) || + key.equals(PredefinedConnectorProperties.HOST) || + key.equals(PredefinedConnectorProperties.PORT) || + key.equals(PredefinedConnectorProperties.EMAIL_SENDER) ) { ((InputElement) comp).setConstraint("no empty:" + _("cannot be empty")); } else if ( key - .equals(PredefinedConnectorProperties.TIM_NR_DAYS_TIMESHEET) - || key.equals(PredefinedConnectorProperties.TIM_NR_DAYS_ROSTER) ) { + .equals(PredefinedConnectorProperties.TIM_NR_DAYS_TIMESHEET) || + key.equals(PredefinedConnectorProperties.TIM_NR_DAYS_ROSTER) || + key.equals(PredefinedConnectorProperties.PORT) ) { if ( !isNumeric((String) value) ) { throw new WrongValueException(comp, _("Only digits allowed")); } } - - // Validate E-mail connector - if ( key.equals(PredefinedConnectorProperties.HOST) || - key.equals(PredefinedConnectorProperties.PORT) || - key.equals(PredefinedConnectorProperties.EMAIL_SENDER) ) - ((InputElement) comp).setConstraint("no empty:" + _("cannot be empty")); } }; } @@ -1321,16 +1324,17 @@ public class ConfigurationController extends GenericForwardComposer { }; } - private boolean emailUsernamePasswordIsEmpty(){ + private boolean isEmailFieldsValid(){ if ( protocolsCombobox.getSelectedItem().getLabel().equals("STARTTLS") && emailUsernameTextbox.getValue() != null && emailPasswordTextbox.getValue() != null && emailUsernameTextbox.getValue().length() != 0 && - emailPasswordTextbox.getValue().length() != 0 ) - return false; + emailPasswordTextbox.getValue().length() != 0 && + emailSenderTextbox.getValue().matches("^\\S+@\\S+\\.\\S+$") ) + return true; - else return true; + else return false; } } diff --git a/libreplan-webapp/src/main/java/org/libreplan/web/email/EmailNotificationModel.java b/libreplan-webapp/src/main/java/org/libreplan/web/email/EmailNotificationModel.java index 49d6c3a2a..d40b15a92 100644 --- a/libreplan-webapp/src/main/java/org/libreplan/web/email/EmailNotificationModel.java +++ b/libreplan-webapp/src/main/java/org/libreplan/web/email/EmailNotificationModel.java @@ -77,6 +77,7 @@ public class EmailNotificationModel implements IEmailNotificationModel { } @Override + @Transactional public boolean deleteAll() { return emailNotificationDAO.deleteAll(); } diff --git a/libreplan-webapp/src/main/java/org/libreplan/web/email/EmailTemplateController.java b/libreplan-webapp/src/main/java/org/libreplan/web/email/EmailTemplateController.java index 903207579..69e4b82aa 100644 --- a/libreplan-webapp/src/main/java/org/libreplan/web/email/EmailTemplateController.java +++ b/libreplan-webapp/src/main/java/org/libreplan/web/email/EmailTemplateController.java @@ -41,6 +41,7 @@ import java.util.List; import java.util.Arrays; import java.util.Collections; import java.util.Comparator; +import java.util.LinkedList; import static org.libreplan.web.I18nHelper._; @@ -69,9 +70,6 @@ public class EmailTemplateController extends GenericForwardComposer{ throws Exception { Language language = (Language) data; String displayName = language.getDisplayName(); - if (language.equals(Language.BROWSER_LANGUAGE)) { - displayName = _(language.getDisplayName()); - } item.setLabel(displayName); } }; @@ -117,7 +115,7 @@ public class EmailTemplateController extends GenericForwardComposer{ return languagesRenderer; } public List getLanguages() { - List languages = Arrays.asList(Language.values()); + List languages = new LinkedList(Arrays.asList(Language.values())); Collections.sort(languages, new Comparator() { @Override public int compare(Language o1, Language o2) { @@ -130,6 +128,7 @@ public class EmailTemplateController extends GenericForwardComposer{ return o1.getDisplayName().compareTo(o2.getDisplayName()); } }); + languages.remove(0); return languages; } diff --git a/libreplan-webapp/src/main/resources/i18n/keys.pot b/libreplan-webapp/src/main/resources/i18n/keys.pot index b50895554..8f39fce59 100644 --- a/libreplan-webapp/src/main/resources/i18n/keys.pot +++ b/libreplan-webapp/src/main/resources/i18n/keys.pot @@ -7764,6 +7764,7 @@ msgstr "" #: libreplan-webapp/src/main/webapp/orders/_orderElementDetails.zul:59 #: libreplan-webapp/src/main/webapp/qualityforms/_listQualityForm.zul:37 #: libreplan-webapp/src/main/webapp/qualityforms/_editQualityForm.zul:49 +#: libreplan-webapp/src/main/webapp/email/email_templates.zul:83 msgid "Description" msgstr "" @@ -9235,10 +9236,46 @@ msgstr "" msgid "Protocol" msgstr "" -#: libreplan-webapp/src/main/webapp/email/email_templates.zul:56 -msgid "Possible content values:" +#: libreplan-webapp/src/main/webapp/email/email_templates.zul:79 +msgid "Possible content keywords" msgstr "" #: libreplan-webapp/src/main/webapp/java/org/libreplan/web/planner/tabs/MultipleTabsPlannerController:90 msgid "-- no URL provided --" msgstr "" + +#: libreplan-webapp/src/main/java/org/libreplan/web/common/ConfigurationController.java:1307 +msgid "Not correct E-mail address" +msgstr "" + +#: libreplan-webapp/src/main/webapp/email/email_templates.zul:82 +msgid "Keyword" +msgstr "" + +#: libreplan-webapp/src/main/webapp/email/email_templates.zul:89 +msgid "Username of user" +msgstr "" + +#: libreplan-webapp/src/main/webapp/email/email_templates.zul:94 +msgid "First name of user" +msgstr "" + +#: libreplan-webapp/src/main/webapp/email/email_templates.zul:99 +msgid "Last name of user" +msgstr "" + +#: libreplan-webapp/src/main/webapp/email/email_templates.zul:104 +msgid "Name of project" +msgstr "" + +#: libreplan-webapp/src/main/webapp/email/email_templates.zul:109 +msgid "Name of resource" +msgstr "" + +#: libreplan-webapp/src/main/webapp/email/email_templates.zul:114 +msgid "Name of task" +msgstr "" + +#: libreplan-webapp/src/main/webapp/email/email_templates.zul:119 +msgid "Welcome page" +msgstr "" diff --git a/libreplan-webapp/src/main/webapp/common/_editJobScheduling.zul b/libreplan-webapp/src/main/webapp/common/_editJobScheduling.zul index 14a51777c..0ddcec9d6 100644 --- a/libreplan-webapp/src/main/webapp/common/_editJobScheduling.zul +++ b/libreplan-webapp/src/main/webapp/common/_editJobScheduling.zul @@ -97,7 +97,7 @@ - + diff --git a/libreplan-webapp/src/main/webapp/email/email_templates.zul b/libreplan-webapp/src/main/webapp/email/email_templates.zul index bf96c6eaa..2c4b8bb2e 100644 --- a/libreplan-webapp/src/main/webapp/email/email_templates.zul +++ b/libreplan-webapp/src/main/webapp/email/email_templates.zul @@ -74,17 +74,53 @@ - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/libreplan-webapp/src/test/java/org/libreplan/importers/TimSoapClientTest.java b/libreplan-webapp/src/test/java/org/libreplan/importers/TimSoapClientTest.java index 96cec183a..3f391a718 100644 --- a/libreplan-webapp/src/test/java/org/libreplan/importers/TimSoapClientTest.java +++ b/libreplan-webapp/src/test/java/org/libreplan/importers/TimSoapClientTest.java @@ -34,7 +34,6 @@ import org.joda.time.LocalDate; import org.junit.Before; import org.junit.Ignore; import org.junit.Test; -import org.libreplan.importers.TimSoapClient; import org.libreplan.importers.tim.DataDTO; import org.libreplan.importers.tim.DepartmentDTO; import org.libreplan.importers.tim.DurationDTO; @@ -95,7 +94,7 @@ public class TimSoapClientTest { return timeRegistrationDTO; } - private RosterRequestDTO createtRosterRequest() { + private RosterRequestDTO createRosterRequest() { RosterDTO rosterDTO = new RosterDTO(); rosterDTO.setStartDate(new LocalDate()); rosterDTO.setEndDate(new LocalDate().plusDays(7)); @@ -186,7 +185,7 @@ public class TimSoapClientTest { .sendRequestReceiveResponse(properties.getProperty("url"), properties.getProperty("username"), properties.getProperty("password"), - createtRosterRequest(), RosterResponseDTO.class); + createRosterRequest(), RosterResponseDTO.class); if (rosterResponseDTO == null) { fail("Roster Response is null"); } diff --git a/pom.xml b/pom.xml index 14a681dd9..7c94b0034 100644 --- a/pom.xml +++ b/pom.xml @@ -37,7 +37,7 @@ true true - false + true UTF-8 @@ -329,7 +329,7 @@ junit junit - 4.11 + 4.12 test