Saturday, September 6, 2008

DNS query in Perl

As mentioned before, I'm doing a project which involves email spam research. Part of the project requires me to query DNS servers for their TXT and SPF records, since they contain valuable information regarding which servers from a specific domain are allowed to send mail.

When we (my partner and I) started coding the project, we decided Python would be our primary language, since we both know it, and it makes life easy. This was true, even on the difficult parts of using a database (MySQL), connecting to SMTP/IMAP/POP3 server, etc.

Last week I stumbled into a block, when querying a DNS server was required. Usually, I'd use the output of 'dig' or 'host', but I cannot be sure the project would run on a platform that has those tools. My second try was to use Python modules (pydns etc.) which should solve this problem, but they were all buggy/undocumented/not-working/too-complicated-to-use.

The annoying part is that I know how to do what I want in Perl:

use Net::DNS;
my $res = Net::DNS::Resolver->new;
my $answer = $res->search('', 'TXT');
print $answer->string;

And that's it. 4 lines of code. Still I hadn't found a decent Python-way to do this. So now I'm using Pydig to query DNS servers. Over 1200 lines of code. Pretty big hammer to solve a tiny problem.

If any of you know a better way to do this in Python, I'd love to hear about it.


  1. a. Why, of all records, did you choose TXT record? :)

    b. In most cases I find it smarter to use gethostbyname(). It's much nicer (higher level, takes into account /etc/hosts, etc etc)
    But, of course, maybe in your cases you needed direct DNS access.

  2. thanks for the comment.
    while gethostbyname would return the IP address of a host, this wouldn't suffice. the TXT record of mail domains contain valuable information (read about SPF, DKIM etc.) which i must get.
    as for now, i run system command. on windows it's nslookup and on linux it's host/dig.

  3. Use dnspython ( and then do something like this:

    import dns.resolver

    answers = dns.resolver.query(hostname, 'TXT')
    text = str(answers[0])
    if text and len(text) > 2:
    text = text[1:-1]