package com.mockmock.mail;
import com.google.common.eventbus.EventBus;
import com.mockmock.Settings;
import org.joda.time.DateTime;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.subethamail.smtp.MessageContext;
import org.subethamail.smtp.MessageHandler;
import org.subethamail.smtp.MessageHandlerFactory;
import org.subethamail.smtp.RejectException;
import javax.mail.BodyPart;
import javax.mail.MessagingException;
import javax.mail.Multipart;
import javax.mail.Session;
import javax.mail.internet.MimeMessage;
import java.io.*;
import java.util.Properties;
@Service
public class MockMockMessageHandlerFactory implements MessageHandlerFactory
{
private EventBus eventBus;
private Settings settings;
@Autowired
public MockMockMessageHandlerFactory(EventBus eventBus)
{
this.eventBus = eventBus;
}
@Autowired
public void setSettings(Settings settings)
{
this.settings = settings;
}
@Override
public MessageHandler create(MessageContext messageContext)
{
return new MockMockHandler(messageContext);
}
class MockMockHandler implements MessageHandler
{
MessageContext context;
MockMail mockMail;
/**
* Constructor
* @param context MessageContext
*/
public MockMockHandler(MessageContext context)
{
this.context = context;
this.mockMail = new MockMail();
// give the mockmail a unique id (currently its just a timestamp in ms)
this.mockMail.setId(DateTime.now().getMillis());
}
/**
* Called first, after the MAIL FROM during a SMTP exchange.
* @param from String
* @throws RejectException
*/
@Override
public void from(String from) throws RejectException
{
this.mockMail.setFrom(from);
if(settings.getShowEmailInConsole())
{
System.out.println("FROM:" + from);
}
else
{
System.out.println("Email from " + from + " received.");
}
}
/**
* Called once for every RCPT TO during a SMTP exchange.
* This will occur after a from() call.
* @param recipient String
* @throws RejectException
*/
@Override
public void recipient(String recipient) throws RejectException
{
this.mockMail.setTo(recipient);
if(settings.getShowEmailInConsole())
{
System.out.println("RECIPIENT:" + recipient);
}
}
/**
* Called when the DATA part of the SMTP exchange begins.
* @param data InputStream
* @throws RejectException
* @throws IOException
*/
@Override
public void data(InputStream data) throws RejectException, IOException
{
String rawMail = this.convertStreamToString(data);
mockMail.setRawMail(rawMail);
Session session = Session.getDefaultInstance(new Properties());
InputStream is = new ByteArrayInputStream(rawMail.getBytes());
try
{
MimeMessage message = new MimeMessage(session, is);
mockMail.setSubject(message.getSubject());
mockMail.setMimeMessage(message);
Object messageContent = message.getContent();
if(messageContent instanceof Multipart)
{
Multipart multipart = (Multipart) messageContent;
for (int i = 0; i < multipart.getCount(); i++)
{
BodyPart bodyPart = multipart.getBodyPart(i);
String contentType = bodyPart.getContentType();
if(contentType.matches("text/plain.*"))
{
mockMail.setBody(convertStreamToString(bodyPart.getInputStream()));
}
else if(contentType.matches("text/html.*"))
{
mockMail.setBodyHtml(convertStreamToString(bodyPart.getInputStream()));
}
}
}
else if(messageContent instanceof InputStream)
{
InputStream mailContent = (InputStream) messageContent;
mockMail.setBody(convertStreamToString(mailContent));
}
else if(messageContent instanceof String)
{
String contentType = message.getContentType();
if(contentType.matches("text/plain.*"))
{
mockMail.setBody(messageContent.toString());
}
else if(contentType.matches("text/html.*"))
{
mockMail.setBodyHtml(messageContent.toString());
}
}
}
catch (MessagingException e)
{
e.printStackTrace();
}
if(settings.getShowEmailInConsole())
{
System.out.println("MAIL DATA");
System.out.println("= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =");
System.out.println(mockMail.getRawMail());
System.out.println("= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =");
}
}
@Override
public void done()
{
// check if this email's "from" address matches one in the filtered list
if(settings.getFilterFromEmailAddresses().contains(mockMail.getFrom()))
{
System.out.println("Skipping email, because From address '" + mockMail.getFrom() + "' matches filter");
return;
}
// check if this email's "to" address matches one in the filtered list
if(settings.getFilterToEmailAddresses().contains(mockMail.getTo()))
{
System.out.println("Skipping email, because To address '" + mockMail.getTo() + "' matches filter");
return;
}
// set the received date
mockMail.setReceivedTime(DateTime.now().getMillis());
if(settings.getShowEmailInConsole())
{
System.out.println("Finished");
}
eventBus.post(mockMail);
}
/**
* Converts given input stream to String
* @param is InputStream
* @return String
*/
protected String convertStreamToString(InputStream is)
{
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
StringBuilder stringBuilder = new StringBuilder();
String line;
try
{
while ((line = reader.readLine()) != null)
{
stringBuilder.append(line);
stringBuilder.append("\n");
}
}
catch (IOException e)
{
e.printStackTrace();
}
return stringBuilder.toString();
}
}
}