/**
* The contents of this file are subject to the OpenMRS Public License
* Version 1.0 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://license.openmrs.org
*
* 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.
*
* Copyright (C) OpenMRS, LLC. All Rights Reserved.
*/
package org.openmrs.module.sync;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.openmrs.GlobalProperty;
import org.openmrs.api.AdministrationService;
import org.openmrs.api.GlobalPropertyListener;
import org.openmrs.api.context.Context;
import org.openmrs.messagesource.MessageSourceService;
import org.openmrs.notification.MessageException;
import javax.mail.Authenticator;
import javax.mail.Message;
import javax.mail.Multipart;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;
import java.util.Arrays;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
/**
* Utility class for configuring and validating email settings, and sending emails
*/
public class SyncMailUtil implements GlobalPropertyListener {
private static final Log log = LogFactory.getLog(SyncMailUtil.class);
// ***** CONSTANTS *****
public static final String MAIL_TRANSPORT_PROTOCOL = "mail.transport_protocol";
public static final String MAIL_SMTP_HOST = "mail.smtp_host";
public static final String MAIL_SMTP_PORT = "mail.smtp_port";
public static final String MAIL_SMTP_AUTH = "mail.smtp_auth";
public static final String MAIL_SMTP_STARTTLS_ENABLE = "mail.smtp.starttls.enable";
public static final String MAIL_USER = "mail.user";
public static final String MAIL_PASSWORD = "mail.password";
public static final String MAIL_DEFAULT_CONTENT_TYPE = "mail.default_content_type";
public static final String MAIL_FROM = "mail.from";
public static final String MAIL_DEBUG = "mail.debug";
public static final String SYNC_ADMIN_EMAIL = "sync.admin_email";
public static List<String> getMailGlobalProperties() {
return Arrays.asList(
MAIL_TRANSPORT_PROTOCOL, MAIL_SMTP_HOST, MAIL_SMTP_PORT, MAIL_SMTP_AUTH, MAIL_SMTP_STARTTLS_ENABLE,
MAIL_USER, MAIL_PASSWORD, MAIL_DEFAULT_CONTENT_TYPE, MAIL_FROM, MAIL_DEBUG, SYNC_ADMIN_EMAIL
);
}
//***** UTILITY METHODS
/**
* Cached mail session. This is set to null and re-loaded anytime a mail global property changes
*/
private static Session mailSession = null;
/**
* @return the currently configured email settings
*/
public static Map<String, String> getCurrentlyConfiguredSettings() {
AdministrationService adminService = Context.getAdministrationService();
Map<String, String> settings = new LinkedHashMap<String, String>();
for (String s : getMailGlobalProperties()) {
settings.put(s, adminService.getGlobalProperty(s));
}
return settings;
}
/**
* @return the currently cached mail session, or a new mail session if any mail configuration is changed
*/
public static Session getMailSession() {
if (mailSession == null ) {
mailSession = createSession(getCurrentlyConfiguredSettings());
}
return mailSession;
}
public static Session createSession(Map<String, String> settings) {
Properties props = new Properties();
props.setProperty("mail.transport.protocol", settings.get(MAIL_TRANSPORT_PROTOCOL));
props.setProperty("mail.smtp.host", settings.get(MAIL_SMTP_HOST));
props.setProperty("mail.smtp.port", settings.get(MAIL_SMTP_PORT));
props.setProperty("mail.smtp.auth", settings.get(MAIL_SMTP_AUTH));
props.setProperty("mail.smtp.starttls.enable", settings.get(MAIL_SMTP_STARTTLS_ENABLE));
props.setProperty("mail.from", settings.get(MAIL_FROM));
props.setProperty("mail.debug", settings.get(MAIL_DEBUG));
final String mailUser = settings.get(MAIL_USER);
final String mailPw = settings.get(MAIL_PASSWORD);
Authenticator auth = new Authenticator() {
@Override
public PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(mailUser, mailPw);
}
};
return Session.getInstance(props, auth);
}
public static String validateSettings(Map<String, String> settings) {
MessageSourceService mss = Context.getMessageSourceService();
try {
Session session = createSession(settings);
Transport transport = session.getTransport();
transport.connect();
transport.close();
return mss.getMessage("sync.emailConfig.connectionSuccessful");
}
catch (Exception e) {
return mss.getMessage("sync.emailConfig.connectionFailed") + ": " + e.getMessage();
}
}
/**
* Sends a message using the current mail session
*/
public static void sendMessage(String recipients, String subject, String body) throws MessageException {
try {
Message message = new MimeMessage(getMailSession());
message.setSentDate(new Date());
if (StringUtils.isNotBlank(subject)) {
message.setSubject(subject);
}
if (StringUtils.isNotBlank(recipients)) {
for (String recipient : recipients.split("\\,")) {
message.addRecipient(MimeMessage.RecipientType.TO, new InternetAddress(recipient));
}
}
if (StringUtils.isNotBlank(body)) {
Multipart multipart = new MimeMultipart();
MimeBodyPart contentBodyPart = new MimeBodyPart();
contentBodyPart.setContent(body, "text/html");
multipart.addBodyPart(contentBodyPart);
message.setContent(multipart);
}
log.info("Sending email with subject <" + subject + "> to <"+recipients+">");
log.debug("Mail has contents: \n" + body);
Transport.send(message);
log.debug("Message sent without errors");
}
catch (Exception e) {
log.error("Message could not be sent due to " + e.getMessage(), e);
throw new MessageException(e);
}
}
@Override
public boolean supportsPropertyName(String s) {
return getMailGlobalProperties().contains(s);
}
@Override
public void globalPropertyChanged(GlobalProperty globalProperty) {
log.debug("Global property <" + globalProperty.getProperty() + "> changed, resetting mail session");
mailSession = null;
}
@Override
public void globalPropertyDeleted(String s) {
log.debug("Global property <" + s + "> deleted, resetting mail session");
mailSession = null;
}
}