/**
* The contents of this file are subject to the license and copyright
* detailed in the LICENSE file at the root of the source
* tree and available online at
*
* https://github.com/keeps/roda
*/
package org.roda.core.common.notifications;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.mail.MessagingException;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.roda.core.RodaCoreFactory;
import org.roda.core.common.ConfigurableEmailUtility;
import org.roda.core.common.HandlebarsUtility;
import org.roda.core.data.common.RodaConstants;
import org.roda.core.data.exceptions.GenericException;
import org.roda.core.data.v2.notifications.Notification;
import org.roda.core.data.v2.notifications.Notification.NOTIFICATION_STATE;
import org.roda.core.data.v2.user.User;
import org.roda.core.model.ModelService;
import org.roda.core.util.IdUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class EmailNotificationProcessor implements NotificationProcessor {
private static final String FROM = "from";
private static final String RECIPIENT = "recipient";
private static final Logger LOGGER = LoggerFactory.getLogger(EmailNotificationProcessor.class);
private Map<String, Object> scope;
private String templateName;
private String localeString;
public EmailNotificationProcessor(String templateName) {
this.scope = new HashMap<>();
this.templateName = templateName;
}
public EmailNotificationProcessor(String templateName, Map<String, Object> scope) {
this.templateName = templateName;
this.scope = scope;
}
public EmailNotificationProcessor(String templateName, Map<String, Object> scope, String localeString) {
this.templateName = templateName;
this.scope = scope;
this.localeString = localeString;
}
@Override
public Notification processNotification(ModelService model, final Notification notification) {
Notification processedNotification = new Notification(notification);
try {
List<String> recipients = processedNotification.getRecipientUsers();
String templatePath = RodaCoreFactory.getRodaConfigurationAsString("core", "notification", "template_path");
String templateCompletePath = templatePath + templateName;
InputStream templateStream;
if (localeString != null) {
String localeTemplateCompletePath = templateCompletePath.replace(RodaConstants.EMAIL_TEMPLATE_EXTENSION,
"_" + localeString + RodaConstants.EMAIL_TEMPLATE_EXTENSION);
templateStream = RodaCoreFactory.getConfigurationFileAsStream(localeTemplateCompletePath, templateCompletePath);
} else {
templateStream = RodaCoreFactory.getConfigurationFileAsStream(templateCompletePath);
}
String template = IOUtils.toString(templateStream, RodaConstants.DEFAULT_ENCODING);
IOUtils.closeQuietly(templateStream);
if (!scope.containsKey(FROM)) {
scope.put(FROM, processedNotification.getFromUser());
}
if (recipients.size() == 1) {
scope.put(RECIPIENT, recipients.get(0));
} else {
scope.put(RECIPIENT, RodaConstants.NOTIFICATION_VARIOUS_RECIPIENT_USERS);
}
String strippedTemplate = template.replace("<a href=\"{{acknowledge}}\">", "").replace("</a>", "");
try {
processedNotification.setBody(HandlebarsUtility.executeHandlebars(strippedTemplate, scope));
} catch (GenericException e) {
LOGGER.error("Error processing notification body", e);
processedNotification.setBody(strippedTemplate);
}
scope.remove(RECIPIENT);
ConfigurableEmailUtility emailUtility = new ConfigurableEmailUtility(processedNotification.getFromUser(),
processedNotification.getSubject());
for (String recipient : recipients) {
String modifiedBody = getUpdatedMessageBody(model, notification, recipient, template, scope);
String host = RodaCoreFactory.getRodaConfigurationAsString("core", "email", "host");
if (StringUtils.isNotBlank(host)) {
LOGGER.debug("Sending email ...");
emailUtility.sendMail(recipient, modifiedBody);
LOGGER.debug("Email sent");
processedNotification.setState(NOTIFICATION_STATE.COMPLETED);
} else {
processedNotification.setState(NOTIFICATION_STATE.FAILED);
LOGGER.debug("SMTP not defined, cannot send emails");
}
}
} catch (IOException | MessagingException | GenericException e) {
processedNotification.setState(NOTIFICATION_STATE.FAILED);
LOGGER.debug("Error sending e-mail: {}", e.getMessage());
}
return processedNotification;
}
private String getUpdatedMessageBody(ModelService model, Notification notification, String recipient, String template,
Map<String, Object> scopes) throws GenericException {
// update body message with the recipient user and acknowledge URL
String userUUID = IdUtils.createUUID(recipient);
String ackUrl = RodaCoreFactory.getRodaConfigurationAsString("core", "notification", "acknowledge");
ackUrl = ackUrl.replaceAll("\\{notificationId\\}", notification.getId());
ackUrl = ackUrl.replaceAll("\\{token\\}", notification.getAcknowledgeToken() + userUUID);
ackUrl = ackUrl.replaceAll("\\{email\\}", recipient);
scopes.put("acknowledge", ackUrl);
scopes.put(RECIPIENT, recipient);
try {
User user = model.retrieveUserByEmail(recipient);
if (user != null) {
scopes.put(RECIPIENT, user.getName());
}
} catch (GenericException e) {
// do nothing
}
return HandlebarsUtility.executeHandlebars(template, scopes);
}
}