09.11.2016 Views

Foundations of Python Network Programming 978-1-4302-3004-5

You also want an ePaper? Increase the reach of your titles

YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.

CHAPTER 4 ■ SOCKET NAMES AND DNS<br />

<strong>of</strong>ten requires two round-trips, this record type is unpopular these days, but you still might run across it<br />

occasionally.<br />

That MX record is crucial, by the way, and is something that newcomers to network programming<br />

<strong>of</strong>ten get confused! Sending e-mail to a domain is a completely different act from trying to make an<br />

HTTP or SSH connection to a domain; if you want to send e-mail to someone @python.org, then do not<br />

try making an SMTP connection to the host named python.org! Always rely on MX records to point you to<br />

your destination, if they exist; try making an SMTP connection to an A record for the domain named in<br />

an e-mail address only if there are no MX records returned for that domain name.<br />

Resolving Mail Domains<br />

I mentioned previously that resolving an e-mail domain is a very legitimate use <strong>of</strong> raw DNS in most<br />

<strong>Python</strong> programs. The rules for doing this resolution are specified most recently in RFC 5321. They are,<br />

briefly, that if MX records exist, then you must try to contact those SMTP servers, and return an error to<br />

the user (or put the message on a re-try queue) if none <strong>of</strong> them will accept the message. If instead no MX<br />

records exist, but an A or AAAA record is provided for the domain, then you are allowed to try an SMTP<br />

connection to that address. If neither record exists, but a CNAME is specified, then the domain name it<br />

provides should be searched for MX or A records using the same rules.<br />

Listing 4–4 shows how you might implement this algorithm. By doing a series <strong>of</strong> DNS queries, it<br />

works its way through the possible destinations, printing out its decisions as it goes. By adjusting a<br />

routine like this to return addresses rather than just printing them out, you could power a <strong>Python</strong> mail<br />

dispatcher that needed to deliver e-mail to remote hosts.<br />

Listing 4–4. Resolving an E-mail Domain Name<br />

#!/usr/bin/env python<br />

# <strong>Foundations</strong> <strong>of</strong> <strong>Python</strong> <strong>Network</strong> <strong>Programming</strong> - Chapter 4 - dns_mx.py<br />

# Looking up a mail domain - the part <strong>of</strong> an email address after the `@`<br />

import sys, DNS<br />

if len(sys.argv) != 2:<br />

» print >>sys.stderr, 'usage: dns_basic.py '<br />

» sys.exit(2)<br />

def resolve_hostname(hostname, indent=0):<br />

» """Print an A or AAAA record for `hostname`; follow CNAMEs if necessary."""<br />

» indent = indent + 4<br />

» istr = ' ' * indent<br />

» request = DNS.Request()<br />

» reply = request.req(name=sys.argv[1], qtype=DNS.Type.A)<br />

» if reply.answers:<br />

» » for answer in reply.answers:<br />

» » » print istr, 'Hostname', hostname, '= A', answer['data']<br />

» » return<br />

» reply = request.req(name=sys.argv[1], qtype=DNS.Type.AAAA)<br />

» if reply.answers:<br />

» » for answer in reply.answers:<br />

» » » print istr, 'Hostname', hostname, '= AAAA', answer['data']<br />

» » return<br />

» reply = request.req(name=sys.argv[1], qtype=DNS.Type.CNAME)<br />

» if reply.answers:<br />

68

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!