All Downloads are FREE. Search and download functionalities are using the official Maven repository.

pl.edu.icm.unity.engine.notifications.email.EmailChannel Maven / Gradle / Ivy

/*
 * Copyright (c) 2019 Bixbit - Krzysztof Benedyczak. All rights reserved.
 * See LICENCE.txt file for licensing information.
 */
package pl.edu.icm.unity.engine.notifications.email;

import java.io.IOException;
import java.io.StringReader;
import java.security.GeneralSecurityException;
import java.util.Date;
import java.util.Properties;
import java.util.concurrent.Future;

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.MimeMessage;
import javax.net.ssl.SSLSocketFactory;

import com.sun.mail.util.MailSSLSocketFactory;

import eu.emi.security.authn.x509.X509CertChainValidator;
import eu.emi.security.authn.x509.impl.SocketFactoryCreator2;
import eu.unicore.util.httpclient.HostnameMismatchCallbackImpl;
import eu.unicore.util.httpclient.ServerHostnameCheckingMode;
import pl.edu.icm.unity.engine.api.PKIManagement;
import pl.edu.icm.unity.engine.api.notification.NotificationStatus;
import pl.edu.icm.unity.engine.api.utils.ExecutorsService;
import pl.edu.icm.unity.engine.notifications.MessageTemplateParams;
import pl.edu.icm.unity.engine.notifications.NotificationChannelInstance;
import pl.edu.icm.unity.types.basic.MessageTemplate;

class EmailChannel implements NotificationChannelInstance
{
	private final Session session;
	private final ExecutorsService executorsService;
	
	
	EmailChannel(String configuration, ExecutorsService executorsService, PKIManagement pkiManagement)
	{
		this.executorsService = executorsService;
		Properties props = new Properties();
		try
		{
			props.load(new StringReader(configuration));
		} catch (IOException e)
		{
			//really shouldn't happen
			throw new IllegalStateException("Bug: can't load email properties " +
					"for the channel instance", e);
		}
		String smtpUser = props.getProperty(EmailFacility.CFG_USER);
		String smtpPassword = props.getProperty(EmailFacility.CFG_PASSWD);
		Authenticator smtpAuthn = (smtpUser != null && smtpPassword != null) ? 
				new SimpleAuthenticator(smtpUser, smtpPassword) : null;
		String trustAll = props.getProperty(EmailFacility.CFG_TRUST_ALL);
		if (trustAll != null && "true".equalsIgnoreCase(trustAll))
		{
			MailSSLSocketFactory trustAllSF;
			try
			{
				trustAllSF = new MailSSLSocketFactory();
			} catch (GeneralSecurityException e)
			{
				//really shouldn't happen
				throw new IllegalStateException("Can't init trust-all SSL socket factory", e);
			}
			trustAllSF.setTrustAllHosts(true);
			props.put("mail.smtp.ssl.socketFactory", trustAllSF);
		} else
		{
			X509CertChainValidator validator = pkiManagement.getMainAuthnAndTrust().getValidator();
			SSLSocketFactory factory = new SocketFactoryCreator2(validator, 
					new HostnameMismatchCallbackImpl(ServerHostnameCheckingMode.FAIL)).getSocketFactory();
			props.put("mail.smtp.ssl.socketFactory", factory);
		}
		session = Session.getInstance(props, smtpAuthn);
	}
	
	@Override
	public Future sendNotification(final String recipientAddress, 
			final MessageTemplate.Message message)
	{
		NotificationStatus retStatus = new NotificationStatus();
		return executorsService.getExecutionService().submit(() -> 
		{
			try
			{
				sendEmail(message, recipientAddress);
			} catch (Exception e)
			{
				EmailFacility.log.error("E-mail notification failed", e);
				retStatus.setProblem(e);
			}
		}, retStatus);
	}
	
	private void sendEmail(MessageTemplate.Message message, String to) throws MessagingException
	{
		EmailFacility.log.info("Sending e-mail message to '" + to +"' with subject: " + message.getSubject());
		MimeMessage msg = new MimeMessage(session);
		msg.setFrom();
		msg.setRecipients(Message.RecipientType.TO, to);
		msg.setSubject(message.getSubject());
		msg.setSentDate(new Date());
		msg.setContent(message.getBody(), getContentType(message));
		Transport.send(msg);
	}

	private String getContentType(MessageTemplate.Message message)
	{
		switch (message.getType())
		{
		case HTML:
			return "text/html; charset=utf-8";
		case PLAIN:
			return "text/plain; charset=utf-8";
		}
		throw new IllegalStateException("BUG: missing conversion of type " 
				+ message.getType() + " to mail content type");
	}

	@Override
	public String getFacilityId()
	{
		return EmailFacility.NAME;
	}
	
	@Override
	public boolean providesMessageTemplatingFunctionality()
	{
		return false;
	}
	
	static class SimpleAuthenticator extends Authenticator
	{
		private String user;
		private String password;
		
		public SimpleAuthenticator(String user, String password)
		{
			this.user = user;
			this.password = password;
		}

		@Override
		protected PasswordAuthentication getPasswordAuthentication() 
		{
			return new PasswordAuthentication(user, password);
		}
	}

	@Override
	public Future sendExternalTemplateMessage(String recipientAddress,
			MessageTemplateParams templateParams)
	{
		throw new UnsupportedOperationException();
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy