Search code examples
phpemaildnsimap

PHP imap only works with IP address, not with domain name - DNS issue?


I'm displaying a simple list of emails using the imap_* functions of PHP:

$connection = "{mail-server:993/ssl/novalidate-cert}INBOX";
$imap = imap_open($connection, 'my-login', 'my-pass');
$check = imap_check($imap);
$overview = imap_fetch_overview($imap, "1:{$check->Nmsgs}", 0);
foreach ($overview as $msg) {
    echo "{$msg->msgno} ({$msg->date}), from {$msg->from}: {$msg->subject}\n";
}
imap_close($imap);

I'm connecting to the same machine. This works perfectly fine and I see the list of emails. However, at the very bottom of the page, a notice is shown:

Notice: Unknown: Can't connect to mail-server,993: Connection refused (errflg=1) in Unknown on line 0

This notice is shown when I use my domain name or localhost(!) as mail-server. When I use my IP address or 127.0.0.1, everything works fine. I got that idea from this question.


I did an nslookup for both my domain name and localhost, from the machine itself. Both return the right IP address, however, both also show that it is a 'Non-authoritative answer'.

Here's the contents of /etc/hosts:

127.0.0.1   localhost
# The following lines are desirable for IPv6 capable hosts
::1     localhost ip6-localhost ip6-loopback
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters

I don't understand how nslookup localhost can give 127.0.0.1 as a non-authoritative answer if it's in the hosts file.


Anyway, am I right that PHP throwing this notice is because of the DNS being non-authoritative? If so, how can I fix it? If not, how can I fix it?

I don't experience any other issues with the DNS. I can access the machine from everywhere using its domain name. Also note that PHP actually can connect when I use the domain name - it just also spits out the notice.

Also, there's no problem using thunderbird on a remote computer using the same connection.

I'm running Ubuntu 14.04, PHP 5.5.9, and Dovecot 2.2.9 for the IMAP server.


Solution

  • This can happen when your lookup resolves to an IPv6 address, but your server isn't configured to support IPv6. The client will first try the IPv6 address, and then the IPv4 address when that fails.

    You can check if this is the case by removing localhost from the line:

    ::1     localhost ip6-localhost ip6-loopback
    

    in your hosts file.

    Authoritative/non-authoritative DNS queries don't make a difference here. See https://serverfault.com/q/413124/265582 for more information.

    You can also let dovecot accept ipv6 connections. How to do that depends on your configuration. If you have inet_listener blocks, make sure that the address line contains ::. For example:

    inet_listener {
      address = *, ::
      port = 143
    }
    inet_listener {
      address = *, ::
      port = 993
      ssl = yes
    }
    

    If you don't have inet_listener blocks, change the listen directive to:

    listen=[::]
    

    In both cases, this will make dovecot listen on both ipv4 and ipv6 connections.