/*******************************************************************************
* Copyright (c) 2013 Hani Naguib.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the GNU Public License v3.0
* which accompanies this distribution, and is available at
* http://www.gnu.org/licenses/gpl.html
*
* Contributors:
* Hani Naguib - initial API and implementation
******************************************************************************/
package com.gvmax.smtp;
import java.io.IOException;
import java.io.InputStream;
import javax.mail.MessagingException;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;
import org.apache.log4j.Logger;
import org.subethamail.smtp.TooMuchDataException;
import org.subethamail.smtp.helper.SimpleMessageListener;
import org.subethamail.smtp.helper.SimpleMessageListenerAdapter;
import org.subethamail.smtp.server.SMTPServer;
import com.gvmax.common.model.Email;
import com.gvmax.common.util.MetricsUtil;
import com.gvmax.data.queue.QueueDAO;
public class SMTPServerImpl {
private static final Logger logger = Logger.getLogger(SMTPServerImpl.class);
private SMTPServer server;
private QueueDAO<Email> smtpQueue;
public SMTPServerImpl(int port, QueueDAO<Email> smtpQueue) {
this.smtpQueue = smtpQueue;
server = new SMTPServer(new SimpleMessageListenerAdapter(new SMTPListener()));
server.setPort(port);
server.setHideTLS(true);
}
public void start() {
server.start();
logger.info("SMTPServerImpl started on port: " + server.getPort());
}
public void stop() {
server.stop();
logger.info("SMTPServerImpl at port: " + server.getPort() + " stopped.");
}
class SMTPListener implements SimpleMessageListener {
@Override
public void deliver(String from, String recipient, InputStream data) throws IOException {
logger.debug("email received from:" + from + " to:" + recipient);
MetricsUtil.getCounter(SMTPListener.class,"received").inc();
// Extract Email
Email email = null;
try {
email = extractEmail(from, recipient, data);
} catch (Exception e) {
logger.error("error processing email from: " + from + " error: " + e.getMessage(), e);
MetricsUtil.getCounter(SMTPListener.class,"error").inc();
return;
}
if (from.contains("thehealingmind")) {
logger.warn("rejected: " + from + " TEXT =\n" + email.getText());
MetricsUtil.getCounter(SMTPListener.class,"rejected").inc();
return;
}
if (from.endsWith("amazonaws.com")) {
logger.warn("rejected: " + from + " TEXT =\n" + email.getText());
MetricsUtil.getCounter(SMTPListener.class,"rejected").inc();
throw new TooMuchDataException("rejected");
}
// Queue email
MetricsUtil.getCounter(SMTPListener.class,"delivered").inc();
smtpQueue.enqueue(email);
}
private Email extractEmail(String from, String recipient, InputStream data) throws IOException, MessagingException {
Email email = new Email();
email.setTimestamp(System.currentTimeMillis());
email.setFrom(from);
email.setTo(recipient);
// Create message
MimeMessage msg = new MimeMessage(null, data);
// Extract message text
if (msg.getContent() instanceof MimeMultipart) {
MimeMultipart t = (MimeMultipart) msg.getContent();
email.setText(t.getBodyPart(0).getContent().toString());
} else {
email.setText(msg.getContent().toString());
}
String[] froms = msg.getHeader("From");
if (froms != null && froms.length > 0) {
email.setOriginalFrom(froms[0]);
}
email.setSubject(msg.getSubject());
return email;
}
@Override
public boolean accept(String from, String recipient) {
boolean ok = recipient.toLowerCase().endsWith("my.gvmax.com");
if (!ok) {
logger.warn("rejected, from: " + from + " to: " + recipient);
}
return ok;
}
}
}