If you need all the addresses from an A record, getaddrinfo()
is probably more useful:
>>> print "\n".join(repr(i) for i in socket.getaddrinfo("smtp.gmail.com", 587))
(2, 1, 6, '', ('173.194.68.108', 587))
(2, 2, 17, '', ('173.194.68.108', 587))
(2, 3, 0, '', ('173.194.68.108', 587))
(2, 1, 6, '', ('173.194.68.109', 587))
(2, 2, 17, '', ('173.194.68.109', 587))
(2, 3, 0, '', ('173.194.68.109', 587))
(10, 1, 6, '', ('2607:f8b0:400d:c01::6c', 587, 0, 0))
(10, 2, 17, '', ('2607:f8b0:400d:c01::6c', 587, 0, 0))
(10, 3, 0, '', ('2607:f8b0:400d:c01::6c', 587, 0, 0))
In general I would suggest always using this function instead of gethostbyname()
as really we should all be writing dual-stack compliant software (i.e. supporting both IPv4 and IPv6) in this day and age.
I didn't bother decoding the family and protocol identifiers as I thought it was fairly obvious from the address format - de-duplicating the addresses is left as an exercise to the reader! (^_^)
EDIT: Now I'm in the office and have a few spare minutes (and aren't feeding a baby with the other hand...) I thought I'd add for anybody unfamiliar with getaddrinfo()
, you can get the function to filter for you by supplying additional hints. For example, in Python you could call the following to get just a list of IPv4 endpoints suitable for TCP:
>>> print "\n".join(repr(i) for i in socket.getaddrinfo("smtp.gmail.com", 587, socket.AF_INET, socket.SOCK_STREAM))
(2, 1, 6, '', ('173.194.76.108', 587))
(2, 1, 6, '', ('173.194.76.109', 587))
And similarly for IPv6:
>>> print "\n".join(repr(i) for i in socket.getaddrinfo("smtp.gmail.com", 587, socket.AF_INET6, socket.SOCK_STREAM))
(10, 1, 6, '', ('2607:f8b0:400d:c01::6c', 587, 0, 0))
Typically, though, my preferred approach is to not provide any hints and iterate through all the results, picking out the ones that I need. This is generally because I want to support both IPv4 and IPv6 addresses and it's annoying to have to perform two DNS resolutions (even if many systems have a local caching resolver which will make the second query very fast).
The result tuple (on Python) consists of:
- Address family (common values:
AF_INET
for IPv4, AF_INET6
for IPv6)
- Socket type (common values:
SOCK_STREAM
for TCP, SOCK_DGRAM
for UDP)
- Protocol type (common values:
IPPROTO_TCP
for TCP, IPPROTO_UDP
for UDP)
- Canonical host name (only set if
AI_CANONNAME
was included in the flags
parameter)
- Address, probably what you want. In Python this is a tuple of
(addr, port)
where addr
is a string and port
is an integer.