Sunday, April 14, 2013

Mountain Lion: Getting Postfix to work with outbound Google SMTP authentication

Problem

Recently I upgraded to Mountain Lion, and getting some things like Postfix to work out of the box has been a chore. Normally when you configure Outlook or Thunderbird email, you must provide separate settings for sending and receiving email. Generally you'll see imap.myisp.com for reading mail and smtp.myisp.com for sending. The standard mail port is 25, but with the exploitation of open mail relays and spamming, you'll need to configure some sort of authentication and/or encryption when transmitting your message.

Just for giggles, I tried to send a quick message via the builtin text mail program, and here's what I saw:

$ mail ladiesman@gmail.com
Subject: Testing
blah blah blah
.
EOT


In /var/log/mail.log:

Apr 13 23:53:37 poly.ftrdhcpuser.net postfix/smtp[23687]: connect to alt1.gmail-smtp-in.l.google.com[2607:f8b0:400d:c02::1a]:25: No route to host


This happens because gmail.com has an MX record (MX records specify other machines for mail delivery options):

$ nslookup
> set q=mx
> gmail.com
Server:  192.168.1.1
Address: 192.168.1.1#53

Non-authoritative answer:
gmail.com mail exchanger = 5 gmail-smtp-in.l.google.com.
gmail.com mail exchanger = 10 alt1.gmail-smtp-in.l.google.com.
gmail.com mail exchanger = 20 alt2.gmail-smtp-in.l.google.com.
gmail.com mail exchanger = 30 alt3.gmail-smtp-in.l.google.com.
gmail.com mail exchanger = 40 alt4.gmail-smtp-in.l.google.com.

And Google likely doesn't allow port 25 mail transmission for security purposes, so trying to telnet to port 25 of any of these hosts results in a timeout.

Getting Postfix to Run at Boot

MacOS uses this annoying launchctl tool rather than the old Bourne-shell based /etc/rc system we remember from our UNIX days. It's more powerful and uses noisy XML files. Anyway, to understand the various settings you will want to take a look at the manpage for it via: man 5 launchd.plist.

At any rate, here are the contents of my /System/Library/LaunchDaemons/org.postfix.master.plist

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
        <key>Label</key>
        <string>org.postfix.master</string>
        <key>Program</key>
        <string>/usr/libexec/postfix/master</string>
        <key>ProgramArguments</key>
        <array>
                <string>master</string>
        </array>
        <key>QueueDirectories</key>
        <array>
                <string>/Library/Server/Mail/Data/spool</string>
        </array>
        <key>AbandonProcessGroup</key>
        <true/>
        <key>RunAtLoad</key>
        <true/>
</dict>
</plist>


The key components to note here are the removal of the -e 60 that was there in the command-line for Postfix master or Postfix will exit after that specified amount of time and won't continue to deliver email. Also you will want the RunAtLoad setting enabled so that it launches at the time you load the file

$ sudo launchctl load /System/Library/LaunchDaemons/org.postfix.master.plist

Note that there are many examples floating around on the Internet using the OnDemand switch. According to the documentation, this has been deprecated, and I couldn't get it to work right by setting it to false anyway. If you want to dial in the behavior, they have a new KeepAlive switch for that. There are a couple of caveats with this plist file. If you try to stop Postfix using sudo postfix stop, launchctl will re-launch it automatically on your behalf. For fatal configuration problems, this will cause a re-launch loop until you unload the plist file. The problem is that if you relinquish control from launchctl and try to manually start/stop Postfix, you lose the process tracking feature of the tool.

Postfix Settings

Most of the settings that others provided were helpful, but there was one that cost me hours of aggravation. I'm hoping that by providing the correction I may save someone else the same pain. Postconf -n will show you the explicit settings you've put into main.cf. Here are the relevant ones for this problem.

relayhost = smtp.gmail.com:587
smtp_generic_maps = hash:/etc/postfix/generic
smtp_sasl_auth_enable = yes
smtp_sasl_password_maps = hash:/etc/postfix/sasl_passwd
smtp_sasl_security_options =
smtp_tls_security_level = encrypt
smtp_use_tls = yes

You don't have to use the generic maps, but what this does is give you is the ability to rewrite the from address to be your gmail address. Here's an example I snarfed by searching:

clint@poly.local ladiesman@gmail.com
@poly.local      ladiesman@gmail.com

The sasl_passwd should look like:

smtp.gmail.com ladiesman@gmail.com:<Googlepassword>

Remember to regenerate your databases using sudo postmap <mapfile> after you've edited sasl_passwd or generic.

NOTE: The relayhost specifies port 587, but the sasl_passwd does NOT. This is important. At first I followed all the instructions online saying that it needs to match exactly what you put in the relayhost. This is WRONG. Postfix refused to use SASL authentication until I tried this. I had stmp.gmail.com:587. I also tried using square brackets around the hostname to avoid MX lookups. I was up until 3am trying to debug this.

Also bear in mind that if you have enabled 2-step verification, you will need to use an application-specific password rather than your regular Google password.

Credits

Thanks to the following articles which helped me along this journey:

http://slashusr.wordpress.com/2012/02/14/enabling-postfix-for-outbound-relay-via-gmail-on-os-x-lion-11/
http://benjaminrojas.net/configuring-postfix-to-send-mail-from-mac-os-x-mountain-lion/

Feedback


Please leave a comment if you have any feedback, thanks...

Monday, October 24, 2011

An evening adventure

Every once in awhile, an incident occurs that will forever shape the way you look at life and people from that day forward. I had one of those incidents last Saturday.

Occasionally I'll go hang out with my buddy Sam who I used to work with at my previous employer. He and I will go out and play pool, get dessert, catch a movie. You know, man-date kind of stuff. He had mentioned that sometimes he likes to take his AWD car out on the back roads and adventure around - he calls it hooligan'ing. I thought it sounded like fun, so last night I told him we should do just that.

He mentioned that he'd been looking for a way to get to Hagg Lake using the forest service and other back roads, and that ATV'ers and mountain bikers have managed to make the connection from Hwy 8 (via Gales Creek Road). Our mission was to see if we could find such a path. He had already taken a cursory look at Google Maps and thought he may have found a way.

After a bit of meandering we managed to get on Dodson Road. I still had cell reception so I was trying to follow along a bit. It looked liked Dodson would dead-end eventually. We weren't sure. Google Maps doesn't always have completely accurate map data, so we kept going. Well, Dodson did come to an end - abruptly at someone's driveway! Oops, so, we made a U-turn and started backtracking. About 5 or 10 minutes we pulled over briefly to check the map on my phone and Sam noticed we needed to move over because there was someone coming up from behind us that needed to get around.

However, the guy pulled along side us and then he partially blocked our path by turning sideways in front of us. What the hell? Was this guy a cop or what? Some David Crosby-looking motherfucker jumps out of his SUV and greets us with, "What the fuck were you doing at my barn?" Actually, apologies to Crosby's family because this guy wasn't even as attractive as that (Dennis Franz perhaps?). Sam was trying to diffuse the situation best as possible by explaining that we didn't mean to trespass and that we were trying to find a path to Hagg Lake. The guy's response was, "This road hasn't gone through in thirty fucking years!"

"If I find anything fucking missing from my barn, there's going to be trouble!" His barn? We weren't on the property but for 20 seconds, so it was a far cry to have had any time to actually take anything. So, he looked at the license plate and said to hold on so he could write it down. He went back to his vehicle (a Mercedes SUV - a redneck with taste?) to get something to write with presumably. At this point I wanted to snap a cellphone pic or a movie in case the dude went all "Deliverance" on us. I could only assume that the jackhole had a gun in his car. He wasn't carrying it on his person because all he had on were shorts and a T-shirt. The guy was seriously unhinged.

He then took down the plate info and asked to see Sam's license. Sam recited his ODL from memory [Sam: Didn't give him my real #] to him and gave him his first name. Sam didn't offer his last and that he wouldn't need it anyway. His parting shot was, "Well SAM, it's not such a hot fucking idea to be heading to Hagg Lake at 10pm, now is it?!?" I don't know, what's so horrible about that? It's not like we had a midterm the next day or anything.


Here's a satellite view of what we think was the asshole's house. If you ever happen out Dodson Road and run across this piece of work, just tell him that you were trying to find Hagg Lake. Oh, and tell him that Sam sent ya!