package mireka.filter.misc;
import mireka.filter.AbstractFilter;
import mireka.filter.Filter;
import mireka.filter.FilterReply;
import mireka.filter.FilterType;
import mireka.filter.MailTransaction;
import mireka.filter.RecipientContext;
import mireka.smtp.RejectExceptionExt;
import mireka.smtp.UnknownUserException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* The TarpitOnGlobalRejections filter slows down replies to RCPT command on all
* connections if unknown recipients are submitted by a client.
*/
public class TarpitOnGlobalRejections implements FilterType {
private final Logger logger = LoggerFactory
.getLogger(TarpitOnGlobalRejections.class);
private final Tarpit tarpit = new Tarpit();
@Override
public Filter createInstance(MailTransaction mailTransaction) {
return new FilterImpl(mailTransaction);
}
private class FilterImpl extends AbstractFilter {
protected FilterImpl(MailTransaction mailTransaction) {
super(mailTransaction);
}
@Override
public FilterReply verifyRecipient(RecipientContext recipientContext)
throws RejectExceptionExt {
try {
return chain.verifyRecipient(recipientContext);
} catch (UnknownUserException e) {
tarpit.addRejection();
sleep();
throw e;
}
}
@Override
public void recipient(RecipientContext recipientContext)
throws RejectExceptionExt {
try {
chain.recipient(recipientContext);
} catch (UnknownUserException e) {
tarpit.addRejection();
throw e;
} finally {
sleep();
}
}
private void sleep() {
try {
long duration = tarpit.waitDuration();
if (duration > 0) {
logger.debug("Sleeping {} ms", duration);
Thread.sleep(duration);
}
} catch (InterruptedException e) {
// if something is so important, just continue
Thread.currentThread().interrupt();
}
}
}
}