package mireka.filter.dnsbl;
import java.net.InetAddress;
import java.net.UnknownHostException;
import mireka.smtp.SmtpReplyTemplate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xbill.DNS.Address;
import org.xbill.DNS.Lookup;
import org.xbill.DNS.Record;
import org.xbill.DNS.TXTRecord;
import org.xbill.DNS.TextParseException;
import org.xbill.DNS.Type;
public class Dnsbl {
private final Logger logger = LoggerFactory.getLogger(getClass());
private final String EOL = System.getProperty("line.separator");
public String domain;
public SmtpReplyTemplate smtpReplyTemplate = new SmtpReplyTemplate();
public DnsblResult check(InetAddress address) {
return new Checker(address).check();
}
@Override
public String toString() {
return domain.toString();
}
/**
* @category GETSET
*/
public String getDomain() {
return domain;
}
/**
* @category GETSET
*/
public void setDomain(String domain) {
this.domain = domain;
}
/**
* @category GETSET
*/
public SmtpReplyTemplate getSmtpReply() {
return smtpReplyTemplate;
}
/**
* @category GETSET
*/
public void setSmtpReply(SmtpReplyTemplate smtpReplyTemplate) {
this.smtpReplyTemplate = smtpReplyTemplate;
}
private class Checker {
private final InetAddress address;
private String queryDomain;
public Checker(InetAddress address) {
this.address = address;
}
public DnsblResult check() {
queryDomain = reversedOctets(address) + "." + domain;
InetAddress replyAddress = queryARecord();
if (replyAddress == null) {
logger.debug(
"DNSBL checked: NOT LISTED, dnsbl={}, address: {}",
domain, address);
return DnsblResult.NOT_LISTED;
}
String reason = queryReason();
DnsblResult result =
new DnsblResult(Dnsbl.this, replyAddress, reason);
logger.debug("DNSBL checked: {}; address: {}", result, address);
return result;
}
private String reversedOctets(InetAddress address) {
StringBuilder buffer = new StringBuilder();
for (byte octet : address.getAddress()) {
int octetInt = octet & 0xFF;
if (buffer.length() != 0)
buffer.insert(0, '.');
buffer.insert(0, octetInt);
}
return buffer.toString();
}
/**
* @return null if the host is not listed
*/
private InetAddress queryARecord() {
try {
return Address.getByName(queryDomain);
} catch (UnknownHostException e) {
return null;
}
}
private String queryReason() {
Lookup lookup;
try {
lookup = new Lookup(queryDomain, Type.TXT);
} catch (TextParseException e) {
throw new RuntimeException(e);
}
Record[] records = lookup.run();
if (lookup.getResult() != Lookup.SUCCESSFUL
&& lookup.getResult() != Lookup.TYPE_NOT_FOUND) {
logger.warn("Error while looking up TXT record for "
+ "address {} in DNSBL {}: {}", new Object[] { address,
domain, lookup.getErrorString() });
}
String reason = concatenateTxtRecordValues(records);
return reason;
}
private String concatenateTxtRecordValues(Record[] records) {
if (records == null || records.length == 0)
return null;
StringBuilder builder = new StringBuilder();
for (Record record : records) {
TXTRecord txtRecord = (TXTRecord) record;
if (builder.length() != 0)
builder.append(EOL);
for (Object string : txtRecord.getStrings()) {
if (builder.length() != 0)
builder.append(EOL);
builder.append(string);
}
}
return builder.toString();
}
}
}