Postfix 554 5.7.1 error: Relay access denied from localhost!

I had to troubleshoot a mail relaying problem with postfix. A CentOS6 server had postfix enabled and an application was using "localhost" as its SMTP mail relay. The problem turned out to be the IPv6 address ::1 for localhost. One workaround is to disable ipv6 in the postfix configuration. We did this because this virtual machine has no ipv6 connection so it doesn't matter. The java application that was trying to send mail was throwing this error message:

SEVERE: Failed sending to Someone <emailaddress>
javax.mail.SendFailedException: Invalid Addresses;
  nested exception is:
        com.sun.mail.smtp.SMTPAddressFailedException: 554 5.7.1 <emailaddress>: Relay access denied
        at com.sun.mail.smtp.SMTPTransport.rcptTo(SMTPTransport.java:1862)
        at com.sun.mail.smtp.SMTPTransport.sendMessage(SMTPTransport.java:1118)
        at javax.mail.Transport.send0(Transport.java:195)
        at javax.mail.Transport.send(Transport.java:124)

I tested sending mail through localhost from the command line and it did the same thing:

554 5.7.1 <emailaddress>: Relay access denied

I did the usual googling, looked at a few server fault links, and the consensus seemed to be that the problem was in the smtpd_recipient_restrictions. This was true but didn't directly lead me to the problem. The smtpd_recipient_restrictions were not directly specified in the configuration, but postconf indicated what the setting was:

# postconf | grep smtpd_recipient_restrictions
smtpd_recipient_restrictions = permit_mynetworks, reject_unauth_destination

So the problem must by mynetworks, right? I looked at mynetworks in main.cf:

# grep ^mynetworks main.cf
mynetworks = 10.0.0.0/8, 127.0.0.0/8

That looks OK too, right? Still no dice on the mail relaying. I looked at the /var/log/maillog and noticed that the logfile indicated the connection was to ipv6 [::1] for localhost:

Jun  5 14:47:52 hostname postfix/smtpd[12148]: connect from localhost[::1]
Jun  5 14:48:01 hostname postfix/smtpd[12148]: NOQUEUE: reject: RCPT from localhost[::1]: 554 5.7.1 <emailaddress>: Relay access denied
Jun  5 14:48:07 hostname postfix/smtpd[12148]: lost connection after RCPT from localhost[::1]
Jun  5 14:48:07 hostname postfix/smtpd[12148]: disconnect from localhost[::1]

Looking at the /etc/hosts (which was still the default CentOS6 hosts file with no changes) I saw that localhost is listed twice, one for IPv4 and one for IPv6:

# cat /etc/hosts
127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6

It would take a sharp eye to catch the connection to ::1 when telnetting to localhost on port 25 to test mail:

# telnet localhost 25
Trying ::1...

I disabled ipv6 in the Postfix configuration by changing inet_protocols in main.cf from all to ipv4, like so:

# grep ^inet_protocols main.cf
inet_protocols = ipv4

Then I restarted postfix. Now when I connect to localhost on port 25 it tries the ipv6 address first but postfix is not listening on the ipv6 address, so that connection is refused. Then telnet retries on the ipv4 address, which is allowed for mail relaying because it's listed in the /etc/postfix/main.cf mynetworks line.

# telnet localhost 25
Trying ::1...
telnet: connect to address ::1: Connection refused
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
220 hostname.domain.com ESMTP Postfix

Alternatively, if you wanted to leave ipv6 enabled for postfix you could add the ipv6 address for localhost to mynetworks in main.cf.