package eu.dnetlib.broker.events.output; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.nio.charset.StandardCharsets; import java.util.Arrays; import java.util.Date; import java.util.Map; import java.util.Properties; import javax.mail.Authenticator; import javax.mail.Message; import javax.mail.MessagingException; import javax.mail.PasswordAuthentication; import javax.mail.Session; import javax.mail.Transport; import javax.mail.internet.AddressException; import javax.mail.internet.InternetAddress; import javax.mail.internet.MimeMessage; import org.antlr.stringtemplate.StringTemplate; import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.core.io.Resource; import org.springframework.stereotype.Component; import com.google.common.base.Splitter; import eu.dnetlib.broker.common.elasticsearch.Event; import eu.dnetlib.broker.common.subscriptions.NotificationMode; import eu.dnetlib.broker.common.subscriptions.Subscription; import eu.dnetlib.broker.properties.EmailProperties; @Component public class EmailDispatcher extends AbstractNotificationDispatcher { @Autowired private EmailProperties props; @Value("${lbs.mail.message.template}") private Resource emailTemplate; public static final int MAX_NUMBER_OF_EVENTS = 20; private static final Log log = LogFactory.getLog(EmailDispatcher.class); @Override protected Message prepareAction(final Subscription subscription, final Event... events) throws Exception { if (subscription == null || StringUtils.isBlank(subscription.getSubscriber())) { log.warn("Invalid subscription"); throw new IllegalArgumentException("Invalid subscription"); } if (events.length == 0) { log.warn("Event list is empty"); } final String content = generateMailContent(subscription, null, events); return prepareMimeMessage(subscription, content); } @Override protected Message prepareAction(final Subscription subscription, final Map params) throws Exception { if (subscription == null || StringUtils.isBlank(subscription.getSubscriber())) { log.warn("Invalid subscription"); throw new IllegalArgumentException("Invalid subscription"); } final String content = generateMailContent(subscription, params); return prepareMimeMessage(subscription, content); } private String generateMailContent(final Subscription subscription, final Map params, final Event... events) throws IOException { final StringTemplate st = new StringTemplate(IOUtils.toString(emailTemplate.getInputStream(), StandardCharsets.UTF_8)); st.setAttribute("sub", subscription); st.setAttribute("total", events.length); st.setAttribute("max", MAX_NUMBER_OF_EVENTS); if (events.length > MAX_NUMBER_OF_EVENTS) { st.setAttribute("events", Arrays.copyOfRange(events, 0, MAX_NUMBER_OF_EVENTS)); } else { st.setAttribute("events", events); } if (params != null) { params.entrySet().forEach(e -> st.setAttribute(e.getKey(), e.getValue())); } return st.toString(); } private Message prepareMimeMessage(final Subscription subscription, final String content) throws MessagingException, UnsupportedEncodingException, AddressException { final Session session = Session.getInstance(obtainProperties(), obtainAuthenticator()); final MimeMessage mimeMessage = new MimeMessage(session); mimeMessage.setFrom(new InternetAddress(props.getFrom(), props.getFromName())); mimeMessage.setSubject("Notification for topic: " + subscription.getTopic()); mimeMessage.setContent(content, "text/html; charset=utf-8"); mimeMessage.setSentDate(new Date()); mimeMessage.addRecipient(Message.RecipientType.TO, new InternetAddress(subscription.getSubscriber())); if (StringUtils.isNotBlank(props.getCc())) { for (final String aCC : Splitter.on(",").omitEmptyStrings().trimResults().split(props.getCc())) { mimeMessage.addRecipient(Message.RecipientType.CC, new InternetAddress(aCC)); } } log.info("Created mail, to: " + subscription.getSubscriber()); return mimeMessage; } @Override protected void performAction(final Message message) throws Exception { log.info("Sending mail to " + Arrays.toString(message.getAllRecipients()) + "..."); Transport.send(message); log.info("...sent"); } private Properties obtainProperties() { final Properties p = new Properties(); p.put("mail.transport.protocol", "smtp"); p.put("mail.smtp.host", props.getSmtpHost()); p.put("mail.smtp.port", props.getSmtpPort()); p.put("mail.smtp.auth", Boolean.toString(StringUtils.isNotBlank(props.getSmtpUser()))); return p; } private Authenticator obtainAuthenticator() { if (StringUtils.isBlank(props.getSmtpUser())) { return null; } return new Authenticator() { private final PasswordAuthentication authentication = new PasswordAuthentication(props.getSmtpUser(), props.getSmtpPassword()); @Override protected PasswordAuthentication getPasswordAuthentication() { return authentication; } }; } @Override public NotificationMode getMode() { return NotificationMode.EMAIL; } }