package models.services;
import managers.NotificationManager;
import play.Configuration;
import play.api.i18n.Lang;
import play.db.jpa.JPAApi;
import play.i18n.MessagesApi;
import play.libs.mailer.Email;
import play.libs.mailer.MailerClient;
import javax.inject.Inject;
import javax.inject.Singleton;
import models.Account;
import models.Notification;
import play.Logger;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* This class handles sending of emails, e.g. for notification mails.
*/
@Singleton
public class EmailService {
Configuration configuration;
MailerClient mailerClient;
Email email;
NotificationManager notificationManager;
JPAApi jpaApi;
MessagesApi messagesApi;
@Inject
public EmailService(Configuration configuration,
MailerClient mailerClient,
Email email,
NotificationManager notificationManager,
JPAApi jpaApi,
MessagesApi messagesApi) {
this.configuration = configuration;
this.mailerClient = mailerClient;
this.email = email;
this.notificationManager = notificationManager;
this.jpaApi = jpaApi;
this.messagesApi = messagesApi;
this.EMAIL_SENDER = configuration.getString("htwplus.email.sender");
}
private String EMAIL_SENDER;
private String PLAIN_TEXT_TEMPLATE = "views.html.Emails.notificationsPlainText";
private String HTML_TEMPLATE = "views.html.Emails.notificationsHtml";
/**
* Sends an email.
*
* @param subject Subject of email
* @param recipient Recipient of email
* @param mailPlainText Plain text content of the mail (allowed to be null)
* @param mailHtml HTML content of the mail (allowed to be null)
*/
public void sendEmail(String subject, String recipient, String mailPlainText, String mailHtml) {
// since this instance is a singleton we need to ensure that there is no other recipient.
// email.addTo adds further recipients so we use email.setTo to pass a list with just one recipient.
List<String> recipientList = new ArrayList<>();
recipientList.add(recipient);
email.setSubject(subject);
email.setTo(recipientList);
email.setFrom(EMAIL_SENDER);
// send email either in plain text, HTML or both
if (mailPlainText != null) {
if (mailHtml != null) {
email.setBodyHtml(mailHtml);
email.setBodyText(mailPlainText);
} else {
email.setBodyText(mailPlainText);
}
} else if (mailHtml != null) {
email.setBodyHtml(mailHtml);
}
mailerClient.send(email);
}
/**
* Sends a list of notifications via email.
*
* @param notifications List of notifications
* @param recipient Recipient of the email notification
*/
public void sendNotificationsEmail(final List<Notification> notifications, Account recipient) {
try {
String subject = notifications.size() > 1
? messagesApi.get(Lang.defaultLang(), "notification.email_notifications.collected.subject", notifications.size())
: messagesApi.get(Lang.defaultLang(), "notification.email_notifications.single.subject_specific",
notifications.get(0).rendered.replaceAll("<[^>]*>", "").replaceAll("\\r?\\n|\\r", ", "));
// send the email
this.sendEmail(subject, recipient.name + " <" + recipient.email + ">",
TemplateService.getInstance().getRenderedTemplate(PLAIN_TEXT_TEMPLATE, notifications, recipient),
TemplateService.getInstance().getRenderedTemplate(HTML_TEMPLATE, notifications, recipient)
);
// mark notifications to be sent (JPA transaction required, as this is a async process)
jpaApi.withTransaction(() -> {
for (Notification notification : notifications) {
notification.isSent = true;
notificationManager.update(notification);
}
});
// log information
Logger.info("Successfully sent " + notifications.size() + " notification(s) to user " + recipient.id
+ " via email."
);
} catch (Exception e) {
Logger.error("Could not send notification(s) to recipient. " + e.getMessage());
}
}
/**
* Sends a single notification via email.
*
* @param notification Notification instance
*/
public void sendNotificationEmail(Notification notification) {
List<Notification> notifications = new ArrayList<>();
notifications.add(notification);
this.sendNotificationsEmail(notifications, notification.recipient);
}
/**
* Finds all users, who wants to receive daily or hourly notifications and sends them one
* email with all the new notifications (if any).
*/
public void sendDailyHourlyNotificationsEmails() {
try {
Logger.info("Start sending of hourly email notifications...");
// load map with recipients containing list of unread notifications and iterate over the map
Map<Account, List<Notification>> notificationsRecipients = notificationManager.findUsersWithDailyHourlyEmailNotifications();
for (Map.Entry<Account, List<Notification>> entry : notificationsRecipients.entrySet()) {
this.sendNotificationsEmail(entry.getValue(), entry.getKey());
}
} catch (Throwable throwable) {
throwable.printStackTrace();
}
}
}