package mireka.filter.local;
import mireka.ConfigurationException;
import mireka.address.Recipient;
import mireka.destination.AliasDestination;
import mireka.destination.Destination;
import mireka.filter.AbstractDataRecipientFilter;
import mireka.filter.DataRecipientFilterAdapter;
import mireka.filter.Filter;
import mireka.filter.FilterBase;
import mireka.filter.FilterReply;
import mireka.filter.FilterType;
import mireka.filter.MailTransaction;
import mireka.filter.RecipientContext;
import mireka.filter.local.table.RecipientDestinationMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.subethamail.smtp.RejectException;
/**
* The LookupDestination filter assigns a destination to recipients in the
* {@link FilterBase#verifyRecipient(RecipientContext)} phase. It does nothing
* if a destination is already assigned, except if it is an
* {@link AliasDestination}, in which case it tries to resolve the alias.
*/
public class LookupDestinationFilter implements FilterType {
private RecipientDestinationMapper recipientDestinationMapper;
@Override
public Filter createInstance(MailTransaction mailTransaction) {
FilterImpl filterInstance = new FilterImpl(mailTransaction);
return new DataRecipientFilterAdapter(filterInstance, mailTransaction);
}
/**
* @category GETSET
*/
public RecipientDestinationMapper getRecipientDestinationMapper() {
return recipientDestinationMapper;
}
/**
* @category GETSET
*/
public void setRecipientDestinationMapper(
RecipientDestinationMapper recipientDestinationMapper) {
this.recipientDestinationMapper = recipientDestinationMapper;
}
private class FilterImpl extends AbstractDataRecipientFilter {
private Logger logger = LoggerFactory.getLogger(FilterImpl.class);
public FilterImpl(MailTransaction mailTransaction) {
super(mailTransaction);
}
@Override
public FilterReply verifyRecipient(RecipientContext recipientContext)
throws RejectException {
Destination currentDestination =
recipientContext.isDestinationAssigned() ? recipientContext
.getDestination() : null;
if (currentDestination == null) {
Destination destination =
lookupDestinationByResolvingAliases(recipientContext.recipient);
recipientContext.setDestination(destination);
} else if (currentDestination instanceof AliasDestination) {
Destination destination =
lookupDestinationByResolvingAliases(((AliasDestination) currentDestination)
.getRecipient());
recipientContext.setDestination(destination);
}
return FilterReply.NEUTRAL;
}
private Destination lookupDestinationByResolvingAliases(
Recipient recipient) {
Destination destination;
Recipient canonicalRecipient = recipient;
int lookups = 0;
while (true) {
if (lookups > 10) {
throw new ConfigurationException(
"Recipient aliases may created a loop for "
+ recipient);
}
destination =
recipientDestinationMapper.lookup(canonicalRecipient);
lookups++;
if (destination instanceof AliasDestination) {
canonicalRecipient =
((AliasDestination) destination).getRecipient();
} else {
if (lookups > 1)
logger.debug("Final recipient is " + canonicalRecipient);
break;
}
}
return destination;
}
}
}