Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

I am using gethostbyname() to check if the domain part of an email address has a valid DNS. Why is it that for some addresses like say <foo@bar.com> 'bar.com' has a DNS entry but for other addresses such as <foo@baz.com> 'baz.com' does not have a DNS entry but 'www.baz.com' does. In real life both these email addresses are valid and deliverable, its just that when you check the domain part with gethostbyname() you need to append the 'www.' prefix. I have settled on this:

for (keys %emails) { my ($domain) = $_ =~ m/<[^@]+@([^>]+)>/; my $dns = gethostbyname($domain) || gethostbyname("www.$domain"); $dns = $dns ? "OK DNS" : "No DNS"; print "$dns email: $_ page(s): $emails{$_}\n"; }

Can someone please explain this seemingly random requirement for 'www.' to me?

Thanks

Replies are listed 'Best First'.
Re: gethostbyname() and www prefix
by pjf (Curate) on Oct 08, 2001 at 03:49 UTC
    All the advice above is very good, but you're probably wondering "how do I check for an MX record in perl?" Well, it's pretty easy using Net::DNS.
    use Net::DNS; my $resolver = Net::DNS::Resolver->new; my $domain = "perlmonks.org"; my $query = $resolver->query($domain,"MX"); if ($query) { # They have an MX record, send the mail. } elsif (gethostbyname($domain)) { # No MX record, but the host exists. Send the # mail. } else { # No host, and no MX. No mail for you! }
    Update: If we don't find an MX record, we now check to see if that address exists using gethostbyname(), as it's valid to have hosts without MX records. Thanks to Kanji for spotting this.

    Cheers,
    Paul

      You can also do it like this to be a trifle more complete:

      use Net::DNS; $res = new Net::DNS::Resolver; warn "Net::DNS error $@\n" if $@; # on some systems without the required config files you will need to # direct Net::DNS to your DNS nameserver(s) or it will timeout $res->nameservers( $prinary_nameserver_ip_address, $secondary... ) if +$res; sub dns_query { return undef unless $res; my $domain = shift; $packet = $res->send($domain, 'MX') or warn $res->errorstring; return 1 if $packet->header->ancount; my $packet = $res->send($domain, 'A') or warn $res->errorstring; return 1 if $packet->header->ancount; return 0; } print "OK DNS $domain" if dns_query($domain);

      Kanji notes my slack duplication of identical code. It is more maintainable to do this:

      sub dns_query { return undef unless $res; my $domain = shift; for my $dns ( 'MX', 'A' ) { $packet = $res->send($domain, $dns ) or warn $res->errorstring +; return 1 if $packet->header->ancount; } return 0; }

      cheers

      tachyon

      s&&rsenoyhcatreve&&&s&n.+t&"$'$`$\"$\&"&ee&&y&srve&&d&&print

Re: gethostbyname() and www prefix
by mandog (Curate) on Oct 08, 2001 at 02:54 UTC
    It is possible that baz.com is not a host, that here is no machine called baz.com

    Mail can reach the baz.com domain if there is a Domain Name Service MX record defined for that domain. The MX record can point to any host. The host handling mail for baz.com doesn't have to be in the bax.com domain. It could be in the not-baz.net domain)

    You can verify this with the nslookup command.

    1. Type  nslookup at your UNIX / win2K or (?) NT command prompt
    2. At the new prompt enter  set type=ANY
    3. type  baz.com
    If there is nothing like a "internet address" in the output and there is something like a "MX preference", the mystery is solved. (Type  exit to leave nslookup. Type  help for more fun commands.



    email: mandog

Re: gethostbyname() and www prefix
by jj808 (Hermit) on Oct 08, 2001 at 03:17 UTC
    There are several types of DNS records, including the following:

    • A (address) records map a domain name to an IP address, e.g. the A record for jonallen.info is 212.69.202.117.
    • CNAME records are aliases - mail.jonallen.org.uk is an alias for www.jonallen.org.uk (they are physically the same machine).
    • MX (mail exchange) records indicate the host which handles email for that domain - this does not have to be related to any other servers (e.g. web). Normal convention is to use email in the form user@domain.tld wheras webservers are usually called www.domain.tld. It is possible to have MX records for domains without A or CNAME records (either of which is required for a name to resolve to an IP address), this is causing your problem with gethostbyname().
      Several MX records can be set for a domain name, each with a priority value. For example, if I have an MX 5 record and an MX 10 record, email will be sent through the MX 10 host if the MX 5 machine goes down.

    Have a look at http://www.dns.net/dnsrd/ for more information (try the 'DNS resource record types' link).

    Cheers,

    JJ

Re: gethostbyname() and www prefix
by rob_au (Abbot) on Oct 08, 2001 at 09:05 UTC
    At the risk of repeating oft-given advice, why don't you have a look at Email::Valid? - This module provides a means of performing email address validation and includes the option of performing domain mail exchanger checks on email addresses submitted for validation.

    The Examples section of POD documentation for this module even includes some notes on DNS checks on email addresses.

    From this POD ...

     

    Examples

    Let's see if the address 'maurice@hevanet.com' conforms to the RFC822 specification:

    print (Email::Valid->address('maurice@hevanet.com') ? 'yes' : 'no');

    Additionally, let's make sure there's a mail host for it:

    print (Email::Valid->address( -address => 'maurice@hevanet.com', -mxcheck => 1 ) ? 'yes' : 'no');

    Let's see an example of how the address may be modified:

    $addr = Email::Valid->address('Alfred Neuman <Neuman @ foo.bar>'); print "$addr\n"; # prints Neuman@foo.bar

    Need to determine why an address failed?

    unless(Email::Valid->address('maurice@hevanet')) { print "address failed $Email::Valid::Details check.\n"; }

    If an error is encountered, an exception is raised. This is really only possible when performing DNS queries. Trap any exceptions by wrapping the call in an eval block:

    eval { $addr = Email::Valid->address( -address => 'maurice@hevanet.com', -mxcheck => 1 ); }; warn "an error was encountered: $@" if $@;

     

    Ooohhh, Rob no beer function well without!

Re: gethostbyname() and www prefix
by converter (Priest) on Oct 08, 2001 at 03:01 UTC

    I'm no DNS expert, but in your example, baz.com probably has no record pointing to a server for 'baz.com'. There is an MX record that indicates the IP address of the default mail exchanger server, and that's probably what you'll have to query for if you want accurate results.

    Using nslookup, you can query the MX record for baz.com with the following command:

    nslookup -type=MX baz.com

    This should return something like the following:

    baz.com preference = 10, mail exchanger = mail.baz.com ... mail.baz.com internet address = xxx.xxx.xxx.xxx

    conv