=== modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/message/MessageSender.java' --- dhis-2/dhis-api/src/main/java/org/hisp/dhis/message/MessageSender.java 2015-01-17 07:41:26 +0000 +++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/message/MessageSender.java 2015-03-26 14:13:53 +0000 @@ -42,8 +42,9 @@ * * @param subject the message subject. * @param text the message text. + * @param footer the message footer. Optionally included by the implementation. * @param users the users to send the message to. * @param forceSend force sending the message despite potential user settings. */ - String sendMessage( String subject, String text, User sender, Set users, boolean forceSend ); + String sendMessage( String subject, String text, String footer, User sender, Set users, boolean forceSend ); } === modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/setting/SystemSettingManager.java' --- dhis-2/dhis-api/src/main/java/org/hisp/dhis/setting/SystemSettingManager.java 2015-02-13 12:51:17 +0000 +++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/setting/SystemSettingManager.java 2015-03-26 14:13:53 +0000 @@ -69,6 +69,7 @@ final String KEY_EMAIL_PASSWORD = "keyEmailPassword"; final String KEY_EMAIL_TLS = "keyEmailTls"; final String KEY_EMAIL_SENDER = "keyEmailSender"; + final String KEY_INSTANCE_BASE_URL = "keyInstanceBaseUrl"; final String KEY_SCHEDULED_PERIOD_TYPES = "keyScheduledPeriodTypes"; final String KEY_SCHEDULED_TASKS = "keySchedTasks"; final String KEY_ORGUNITGROUPSET_AGG_LEVEL = "orgUnitGroupSetAggregationLevel"; @@ -179,6 +180,8 @@ String getEmailSender(); + String getInstanceBaseUrl(); + boolean accountRecoveryEnabled(); boolean accountInviteEnabled(); === modified file 'dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/email/DefaultEmailService.java' --- dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/email/DefaultEmailService.java 2015-02-19 09:18:17 +0000 +++ dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/email/DefaultEmailService.java 2015-03-26 14:13:53 +0000 @@ -88,7 +88,7 @@ @Override public void sendEmail( Email email ) { - emailMessageSender.sendMessage( email.getSubject(), email.getText(), email.getSender(), email.getRecipients(), true ); + emailMessageSender.sendMessage( email.getSubject(), email.getText(), null, email.getSender(), email.getRecipients(), true ); } @Override @@ -122,7 +122,7 @@ sender.setFirstName( StringUtils.trimToEmpty( appTitle ) ); sender.setSurname( recipient ); - emailMessageSender.sendMessage( email.getSubject(), email.getText(), sender, Sets.newHashSet( user ), true ); + emailMessageSender.sendMessage( email.getSubject(), email.getText(), null, sender, Sets.newHashSet( user ), true ); return true; } === modified file 'dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/message/DefaultMessageService.java' --- dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/message/DefaultMessageService.java 2015-01-17 07:41:26 +0000 +++ dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/message/DefaultMessageService.java 2015-03-27 18:24:40 +0000 @@ -29,8 +29,10 @@ */ import java.util.Collection; +import java.util.HashMap; import java.util.HashSet; import java.util.List; +import java.util.Locale; import java.util.Set; import org.apache.commons.logging.Log; @@ -40,10 +42,14 @@ import org.hisp.dhis.dataset.DataSet; import org.hisp.dhis.email.Email; import org.hisp.dhis.email.EmailService; +import org.hisp.dhis.i18n.I18nManager; +import org.hisp.dhis.i18n.locale.LocaleManager; +import org.hisp.dhis.setting.SystemSettingManager; import org.hisp.dhis.system.velocity.VelocityManager; import org.hisp.dhis.user.CurrentUserService; import org.hisp.dhis.user.User; import org.hisp.dhis.user.UserGroup; +import org.hisp.dhis.user.UserSettingService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.transaction.annotation.Transactional; @@ -60,6 +66,8 @@ private static final String COMPLETE_TEMPLATE = "completeness_message"; + private static final String MESSAGE_EMAIL_FOOTER_TEMPLATE = "message_email_footer"; + // ------------------------------------------------------------------------- // Dependencies // ------------------------------------------------------------------------- @@ -92,6 +100,27 @@ this.emailService = emailService; } + private UserSettingService userSettingService; + + public void setUserSettingService( UserSettingService userSettingService ) + { + this.userSettingService = userSettingService; + } + + private I18nManager i18nManager; + + public void setI18nManager( I18nManager i18nManager ) + { + this.i18nManager = i18nManager; + } + + private SystemSettingManager systemSettingManager; + + public void setSystemSettingManager( SystemSettingManager systemSettingManager ) + { + this.systemSettingManager = systemSettingManager; + } + private List messageSenders; @Autowired @@ -164,8 +193,10 @@ int id = saveMessageConversation( conversation ); users.remove( sender ); - - invokeMessageSenders( subject, text, sender, users, forceNotifications ); + + String footer = getMessageFooter( conversation ); + + invokeMessageSenders( subject, text, footer, sender, users, forceNotifications ); return id; } @@ -195,7 +226,7 @@ updateMessageConversation( conversation ); - invokeMessageSenders( conversation.getSubject(), text, sender, new HashSet<>( conversation.getUsers() ), false ); + invokeMessageSenders( conversation.getSubject(), text, null, sender, new HashSet<>( conversation.getUsers() ), false ); } @Override @@ -244,7 +275,7 @@ { int id = saveMessageConversation( conversation ); - invokeMessageSenders( COMPLETE_SUBJECT, text, sender, new HashSet<>( conversation.getUsers() ), false ); + invokeMessageSenders( COMPLETE_SUBJECT, text, null, sender, new HashSet<>( conversation.getUsers() ), false ); return id; } @@ -374,13 +405,30 @@ // Supportive methods // ------------------------------------------------------------------------- - private void invokeMessageSenders( String subject, String text, User sender, Set users, boolean forceSend ) + private void invokeMessageSenders( String subject, String text, String footer, User sender, Set users, boolean forceSend ) { for ( MessageSender messageSender : messageSenders ) { log.debug( "Invoking message sender: " + messageSender.getClass().getSimpleName() ); - messageSender.sendMessage( subject, text, sender, new HashSet<>( users ), forceSend ); - } + messageSender.sendMessage( subject, text, footer, sender, new HashSet<>( users ), forceSend ); + } + } + + private String getMessageFooter( MessageConversation conversation ) { + HashMap values = new HashMap<>( 2 ); + String baseUrl = systemSettingManager.getInstanceBaseUrl(); + + if ( baseUrl == null ) + { + return ""; // No base url is configured for this instance. Cannot create a reply link. + } + + values.put( "responseUrl", baseUrl + "/dhis-web-dashboard-integration/readMessage.action?id=" + conversation.getUid() ); + + Locale locale = (Locale) userSettingService.getUserSettingValue( conversation.getUser(), UserSettingService.KEY_UI_LOCALE, LocaleManager.DHIS_STANDARD_LOCALE ); + values.put( "i18n", i18nManager.getI18n( locale ) ); + + return new VelocityManager().render( values , MESSAGE_EMAIL_FOOTER_TEMPLATE ); } } === modified file 'dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/message/EmailMessageSender.java' --- dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/message/EmailMessageSender.java 2015-03-07 19:33:58 +0000 +++ dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/message/EmailMessageSender.java 2015-03-27 17:49:54 +0000 @@ -31,18 +31,20 @@ import static org.apache.commons.lang3.StringUtils.defaultIfEmpty; import static org.hisp.dhis.user.UserSettingService.KEY_MESSAGE_EMAIL_NOTIFICATION; +import java.util.HashMap; import java.util.Set; +import com.google.common.base.Strings; import org.apache.commons.lang3.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.commons.mail.DefaultAuthenticator; -import org.apache.commons.mail.Email; import org.apache.commons.mail.EmailException; -import org.apache.commons.mail.SimpleEmail; +import org.apache.commons.mail.HtmlEmail; import org.hisp.dhis.configuration.ConfigurationService; import org.hisp.dhis.setting.SystemSettingManager; import org.hisp.dhis.system.util.DebugUtils; +import org.hisp.dhis.system.velocity.VelocityManager; import org.hisp.dhis.user.User; import org.hisp.dhis.user.UserSettingService; import org.springframework.scheduling.annotation.Async; @@ -54,12 +56,19 @@ implements MessageSender { private static final Log log = LogFactory.getLog( EmailMessageSender.class ); + private static final String FROM_ADDRESS = "noreply@dhis2.org"; + private static final String DEFAULT_APPLICATION_TITLE = "DHIS 2"; + private static final String DEFAULT_FROM_NAME = DEFAULT_APPLICATION_TITLE + " Message [No reply]"; + private static final String DEFAULT_SUBJECT_PREFIX = "[" + DEFAULT_APPLICATION_TITLE + "] "; + private static final String LB = System.getProperty( "line.separator" ); + private static final String MESSAGE_EMAIL_TEMPLATE = "message_email"; + // ------------------------------------------------------------------------- // Dependencies // ------------------------------------------------------------------------- @@ -94,7 +103,7 @@ */ @Async @Override - public String sendMessage( String subject, String text, User sender, Set users, boolean forceSend ) + public String sendMessage( String subject, String text, String footer, User sender, Set users, boolean forceSend ) { String hostName = systemSettingManager.getEmailHostName(); int port = systemSettingManager.getEmailPort(); @@ -108,30 +117,28 @@ return null; } - text = sender == null ? text : ( text + LB + LB + - sender.getName() + LB + - ( sender.getOrganisationUnitsName() != null ? ( sender.getOrganisationUnitsName() + LB ) : StringUtils.EMPTY ) + - ( sender.getEmail() != null ? ( sender.getEmail() + LB ) : StringUtils.EMPTY ) + - ( sender.getPhoneNumber() != null ? ( sender.getPhoneNumber() + LB ) : StringUtils.EMPTY ) ); - + String plainContent = renderPlainContent( text, sender ); + String htmlContent = renderHtmlContent( text, footer, sender ); + try { - Email email = getEmail( hostName, port, username, password, tls, from ); + HtmlEmail email = getHtmlEmail( hostName, port, username, password, tls, from ); email.setSubject( customizeTitle( DEFAULT_SUBJECT_PREFIX ) + subject ); - email.setMsg( text ); - + email.setTextMsg( plainContent ); + email.setHtmlMsg( htmlContent ); + boolean hasRecipients = false; - + for ( User user : users ) { boolean doSend = forceSend || (Boolean) userSettingService.getUserSettingValue( user, KEY_MESSAGE_EMAIL_NOTIFICATION, false ); - + if ( doSend && user.getEmail() != null && !user.getEmail().trim().isEmpty() ) { email.addBcc( user.getEmail() ); - + log.info( "Sending email to user: " + user.getUsername() + " with email address: " + user.getEmail() + " to host: " + hostName + ":" + port ); - + hasRecipients = true; } } @@ -154,23 +161,73 @@ return null; } - private Email getEmail( String hostName, int port, String username, String password, boolean tls, String sender ) + // ------------------------------------------------------------------------- + // Supportive methods + // ------------------------------------------------------------------------- + + private HtmlEmail getHtmlEmail( String hostName, int port, String username, String password, boolean tls, String sender ) throws EmailException { - Email email = new SimpleEmail(); + HtmlEmail email = new HtmlEmail(); email.setHostName( hostName ); email.setFrom( defaultIfEmpty( sender, FROM_ADDRESS ), customizeTitle( DEFAULT_FROM_NAME ) ); email.setSmtpPort( port ); email.setStartTLSEnabled( tls ); - + if ( username != null && password != null ) { email.setAuthenticator( new DefaultAuthenticator( username, password ) ); } - + return email; } + private String renderPlainContent( String text, User sender ) + { + return sender == null ? text : ( text + LB + LB + + sender.getName() + LB + + ( sender.getOrganisationUnitsName() != null ? ( sender.getOrganisationUnitsName() + LB ) : StringUtils.EMPTY ) + + ( sender.getEmail() != null ? ( sender.getEmail() + LB ) : StringUtils.EMPTY ) + + ( sender.getPhoneNumber() != null ? ( sender.getPhoneNumber() + LB ) : StringUtils.EMPTY ) ); + } + + private String renderHtmlContent( String text, String footer, User sender ) + { + HashMap content = new HashMap<>(); + + if ( !Strings.isNullOrEmpty( text ) ) + { + content.put( "text", text.replaceAll( "\\r?\\n", "
" ) ); + } + + if ( !Strings.isNullOrEmpty( footer ) ) + { + content.put( "footer", footer ); + } + + if ( sender != null ) + { + content.put( "senderName", sender.getName() ); + + if ( sender.getOrganisationUnitsName() != null ) + { + content.put( "organisationUnitsName", sender.getOrganisationUnitsName() ); + } + + if ( sender.getEmail() != null ) + { + content.put( "email", sender.getEmail() ); + } + + if ( sender.getPhoneNumber() != null ) + { + content.put( "phoneNumber", sender.getPhoneNumber() ); + } + } + + return new VelocityManager().render( content, MESSAGE_EMAIL_TEMPLATE ); + } + private String customizeTitle( String title ) { String appTitle = (String) systemSettingManager.getSystemSetting( SystemSettingManager.KEY_APPLICATION_TITLE ); === modified file 'dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/security/DefaultSecurityService.java' --- dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/security/DefaultSecurityService.java 2015-03-18 18:51:30 +0000 +++ dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/security/DefaultSecurityService.java 2015-03-26 14:13:53 +0000 @@ -260,8 +260,8 @@ // Send emails // ------------------------------------------------------------------------- - emailMessageSender.sendMessage( subject1, text1, null, users, true ); - emailMessageSender.sendMessage( subject2, text2, null, users, true ); + emailMessageSender.sendMessage( subject1, text1, null, null, users, true ); + emailMessageSender.sendMessage( subject2, text2, null, null, users, true ); return true; } === modified file 'dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/setting/DefaultSystemSettingManager.java' --- dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/setting/DefaultSystemSettingManager.java 2015-02-19 09:18:17 +0000 +++ dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/setting/DefaultSystemSettingManager.java 2015-03-26 14:13:53 +0000 @@ -175,6 +175,12 @@ } @Override + public String getInstanceBaseUrl() + { + return StringUtils.trimToNull( (String) getSystemSetting( KEY_INSTANCE_BASE_URL ) ); + } + + @Override public boolean accountRecoveryEnabled() { return (Boolean) getSystemSetting( KEY_ACCOUNT_RECOVERY, false ); === modified file 'dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/sms/SmsMessageSender.java' --- dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/sms/SmsMessageSender.java 2015-02-22 20:02:00 +0000 +++ dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/sms/SmsMessageSender.java 2015-03-26 14:13:53 +0000 @@ -74,7 +74,7 @@ // @Async @Override - public String sendMessage( String subject, String text, User sender, Set users, boolean forceSend ) + public String sendMessage( String subject, String text, String footer, User sender, Set users, boolean forceSend ) { String message = null; === modified file 'dhis-2/dhis-services/dhis-service-core/src/main/resources/META-INF/dhis/beans.xml' --- dhis-2/dhis-services/dhis-service-core/src/main/resources/META-INF/dhis/beans.xml 2015-03-24 18:54:44 +0000 +++ dhis-2/dhis-services/dhis-service-core/src/main/resources/META-INF/dhis/beans.xml 2015-03-26 14:13:53 +0000 @@ -633,6 +633,9 @@ + + + === modified file 'dhis-2/dhis-services/dhis-service-core/src/main/resources/i18n_global.properties' --- dhis-2/dhis-services/dhis-service-core/src/main/resources/i18n_global.properties 2015-03-19 15:03:55 +0000 +++ dhis-2/dhis-services/dhis-service-core/src/main/resources/i18n_global.properties 2015-03-27 18:24:40 +0000 @@ -926,6 +926,10 @@ iso8601=ISO 8601 coptic=Coptic +#-- Email message footer ------------------------------------------------------# + +respond_to_this_message=Respond to this message + #-- Restore emails ------------------------------------------------------------# email_restore_subject=User account restore confirmation at === added file 'dhis-2/dhis-services/dhis-service-core/src/main/resources/message_email.vm' --- dhis-2/dhis-services/dhis-service-core/src/main/resources/message_email.vm 1970-01-01 00:00:00 +0000 +++ dhis-2/dhis-services/dhis-service-core/src/main/resources/message_email.vm 2015-03-27 17:49:54 +0000 @@ -0,0 +1,11 @@ + + + + $!object.text

+ #if ( $object.senderName)${object.senderName}
#end + #if ( $object.organisationUnitsName )${object.organisationUnitsName}
#end + #if ( $object.email)${object.email}
#end + #if ( $object.phoneNumber)${object.phoneNumber}
#end + $!{object.footer} + + \ No newline at end of file === added file 'dhis-2/dhis-services/dhis-service-core/src/main/resources/message_email_footer.vm' --- dhis-2/dhis-services/dhis-service-core/src/main/resources/message_email_footer.vm 1970-01-01 00:00:00 +0000 +++ dhis-2/dhis-services/dhis-service-core/src/main/resources/message_email_footer.vm 2015-03-27 18:24:40 +0000 @@ -0,0 +1,1 @@ +$object.i18n.getString( "respond_to_this_message" ) \ No newline at end of file === modified file 'dhis-2/dhis-services/dhis-service-core/src/test/java/org/hisp/dhis/message/MockMessageSender.java' --- dhis-2/dhis-services/dhis-service-core/src/test/java/org/hisp/dhis/message/MockMessageSender.java 2015-01-17 07:41:26 +0000 +++ dhis-2/dhis-services/dhis-service-core/src/test/java/org/hisp/dhis/message/MockMessageSender.java 2015-03-26 14:13:53 +0000 @@ -36,7 +36,7 @@ implements MessageSender { @Override - public String sendMessage( String subject, String text, User sender, Set users, boolean forceSend ) + public String sendMessage( String subject, String text, String footer, User sender, Set users, boolean forceSend ) { // Do nothing return null; === modified file 'dhis-2/dhis-services/dhis-service-sms/src/main/java/org/hisp/dhis/sms/listener/DHISMessageAlertListener.java' --- dhis-2/dhis-services/dhis-service-sms/src/main/java/org/hisp/dhis/sms/listener/DHISMessageAlertListener.java 2015-02-19 09:18:17 +0000 +++ dhis-2/dhis-services/dhis-service-sms/src/main/java/org/hisp/dhis/sms/listener/DHISMessageAlertListener.java 2015-03-26 14:13:53 +0000 @@ -157,7 +157,7 @@ confirmMessage = SMSCommand.ALERT_FEEDBACK; } - smsMessageSender.sendMessage( smsCommand.getName(), confirmMessage, null, feedbackList, true ); + smsMessageSender.sendMessage( smsCommand.getName(), confirmMessage, null, null, feedbackList, true ); sms.setParsed( true ); sms.setStatus( SmsMessageStatus.PROCESSED ); === modified file 'dhis-2/dhis-services/dhis-service-sms/src/main/java/org/hisp/dhis/sms/listener/UnregisteredSMSListener.java' --- dhis-2/dhis-services/dhis-service-sms/src/main/java/org/hisp/dhis/sms/listener/UnregisteredSMSListener.java 2015-02-19 09:18:17 +0000 +++ dhis-2/dhis-services/dhis-service-sms/src/main/java/org/hisp/dhis/sms/listener/UnregisteredSMSListener.java 2015-03-26 14:13:53 +0000 @@ -161,7 +161,7 @@ sender.setPhoneNumber( senderPhoneNumber ); feedbackList.add( sender ); smsMessageSender.sendMessage( smsCommand.getName(), smsCommand.getReceivedMessage(), null, - feedbackList, true ); + null, feedbackList, true ); // update the status of the sms after process sms.setStatus( SmsMessageStatus.PROCESSED );