Getting mail() function to work on PHP via OS X Server (Yosemite)

I wanted to figure out how to get the mail function of PHP to work on my OS X Server. After a lot of searching around, I got it working after reading these two sites: this and this. Of course, as with all these things, nothing is exactly how it is written in the posts, so I’ve written one for myself (with parts of the article ‘copied’ from the source articles! So the acknowledgement goes to them). Note that I used Gmail SMTP server. This is more out of necessity than want; I’m still in search of how to do it for a generic SMTP server… 

Postfix

So the majority of this article is taken almost straight from ‘enabling postfix for outbound relay via Gmail on OS X Lion‘. Postfix (wikipedia article) is a built-in SMTP server on the mac (I’m talking about OS X Mountain Lion here). But it seems more the article mentioned that you have to make a few changes…

Background knowledge

Unfortunately, the steps require some knowledge of Terminal. I know relatively little (only the other day, I realised that ‘su’ in the command ‘sudo’, stands for ‘superuser’!) so when the reference article said that I should use ‘vim‘, I thought I’ll find an easier way. So I did everything via TextWrangler (great text editor that’s free!).

For example, suppose I wish to open the file ‘php.ini’ that’s located in ‘/private/etc’. I couldn’t do it in TextEdit since the file is in a system folder. Here’s what I did:

1. Open Finder (to any folder) and press Shit + Cmd + G (or Go -> Go to folder), then type in ‘/private/etc’. That gets me to the right folder.
2. Then, right-click on the file (in this case, php.ini) then go Open With -> Other, and choose TextWrangler. Somewhat unsurprisingly, this opens up the file in TextWrangler.
3. When you try to edit it, you’ll be ask if you wish to ‘Unlock’ it, and of course, you do want to unlock it. Then, when you try to save, it’ll ask for your administrator password so type the details in and voila, you’re done.

Anyway, later on, you’ll see that you may have to create directories/files etc. This is best done in terminal since I’m not exactly sure of the permission you need to set if you create it, say, via TextWrangler. Don’t worry, I’ll walk you through everything.

Setting up Postfix

This is admittedly quite complicated, following my source article, I’m going to break it down into five distinctive steps. Before we move on, let’s list the five files that we’ll be editing, their location, and a summary. This is all taken from the source article.

NameLocationDescription
org.postfix.master.plist/System/Library/LaunchDaemonslaunchd Configuration for postfix
main.cf/etc/postfixThe main postfix configuration
aliases/etc/postfixLocal recipient aliases
generic/etc/postfixSender aliases (for external mail)
passwd/etc/postfix/saslRelay host authentication

Step 1: Updating launchd configuration

The org.postfix.master.plist file located at /System/Library/LaunchDaemons/ is used to start or stop postfix on demand, as and when any email is submitted to the mail system for processing. Open up the file in TextWrangler and make it match the following

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//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>
      <string>-e</string>
      <string>60</string>
    </array>
  <key>QueueDirectories</key>
    <array>
      <string>/var/spool/postfix/maildrop</string>
    </array>
  <key>AbandonProcessGroup</key>
    <true/>
  <key>OnDemand</key>
    <true/>
</dict>
</plist>

Note that the location of ‘maildrop’ may differ for you (for example, above is what I already had on my computer, which is different from what you’d find in the original article.  For example, in Mountain Lion, it used to be ‘/Library/Server/Mail/Data/spool/maildrop’.

Step 2: Editing the ‘main.cf’ file

Type the following in Terminal

cd /etc/postfix
sudo cp main.cf main.cf.orig

The first line ‘cd’ stands for ‘change directory’. ‘sudo’ tells it to run the following command with superuser permission. ‘cp’ stands for ‘copy’. So all in all, above says ‘change directory to /etc/postfix, then copy main.cf and paste it as main.cf.orig’. You might have figured it out already but basically this saves the original file as a backup.

Now open main.cf in TextWrangler, and copy and paste the following in at the end of the file:

# Set the relayhost to the Gmail Server.  Replace with your SMTP server as needed
relayhost = smtp.gmail.com:587
# Postfix 2.2 uses the generic(5) address mapping to replace local fantasy email
# addresses by valid Internet addresses. This mapping happens ONLY when mail
# leaves the machine; not when you send mail between users on the same machine.
smtp_generic_maps = hash:/etc/postfix/generic

# These settings (along with the relayhost setting above) will make
# postfix relay all outbound non-local email via Gmail using an
# authenticated TLS/SASL session.
smtp_tls_loglevel=1
smtp_tls_security_level=encrypt
smtp_sasl_auth_enable=yes
smtp_sasl_password_maps=hash:/etc/postfix/sasl/passwd
smtp_sasl_security_options = noanonymous
smtp_sasl_mechanism_filter = plain

The last line ‘smtp_sasl_mechanism_filter = plain’ is new for Yosemite (see here) and I did not have to have it under Mountain Lion.

Step 3: Editing the ‘aliases’ file

“We… need to allow mails sent to the root ID to your local user mailbox.” Fire up the Terminal, then type in the following commands.

cd /etc/postfix
whoami                # This will provide your local user name
sudo cp aliases aliases.orig

Open up ‘aliases’ (it has no extension) in TextWrangler and find the line that says

#root:              you

and replace the “you” with the username provided by the whoami command above.  Also, remove the “#” from beginning of the line. After saving the changes, go back to the Terminal, then type

sudo newaliases

Step 4: Editing the ‘generic’ file

“This file maps the local user address (usually of the form [email protected]) to a valid Internet email address you would like to use when sending mails to the outside world. In our case, it would basically map your Unix user name to the Gmail [username].”

Fire up the Terminal, and type in

cd /etc/postfix
whoami                # This will provide your local user name, <yourusername>
hostname              # This will provide your machine name, <machinename>
sudo cp generic generic.orig

“In the file, add the following lines at the end of the file (replacing the with the output of the whoami command, and with output of the hostname command):”

# Translate my primary email address to the Gmail address
# This is ONLY for the outbound email, and does not apply to
# local email.
<yourusername>@<machinename>  <gmailusername>
<machinename>                <gmailusername>

Note that <gmailusername> should include the @gmail.com; i.e. [email protected] Save the changes and go back to the terminal and run the following command

sudo postmap generic

Step 5: Editing the ‘passwd’ file

“In this step, we store the SMTP authentication (user ID and password) for Gmail, so that postfix can connect as any other SMTP client to Gmail via an authenticated session.”

Back to the Terminal, then

sudo mkdir -p /etc/postfix/sasl    # In case the directory does not exist
cd /etc/postfix/sasl
sudo vim passwd

The last command opens up the dreaded vim. Afterwards, type the following in

smtp.gmail.com:587    <gmailusername>:<gmailpassword>

Replace <gmailusername> with the ID you use for Gmail (with the “@gmail.com” added at the end), and <gmailpassword> with the password you use to login to Gmail. After making the edit, press Escape (to make sure that you’re not in ‘INSERT’ mode) and then type ‘:w’ and press Enter to write the file, and then type ‘:q’ and press Enter to close the VIM editor.

[Alternatively, if you want to use TextWrangler to create the passwd file, make sure to set the permission to 0600 by running

chmod 0600 /etc/postfix/sasl/*

Not doing this will mean that you’ll run into ‘postmap: fatal: open database passwd.db: Permission denied’ error when you run the command below.]
Save the changes and go back to the terminal and run the following command

sudo postmap passwd

Setting up your web server

This is the last step. You need to edit your php.ini (located at /private/etc/). Find the following bit (courtesy of this post)

; For Unix only. You may supply arguments as well (default: "sendmail -t -i").
; http://php.net/sendmail-path
;sendmail_path =

and change it to

; For Unix only. You may supply arguments as well (default: "sendmail -t -i").
; http://php.net/sendmail-path
sendmail_path = "sendmail -t -i"

Make sure you restart your web server after you make the changes to php.ini; i.e. go into the Server.app and then flick the On/Off switch for the Web server.

Testing

So to test, we can run the following commands in the Terminal:

# first to load things up
cd /System/Library/LaunchDaemons
sudo launchctl load -w org.postfix.master.plist
cd ~ # as recommended in the original article, just to be safe

# Let's try sending email out
mail 
# It'll first ask you to type in the Subject
# Pressing Enter would let you enter the body of the email
# Pressing Ctrl + D at a blank line (press Enter after your last line of text)
# to send the email

If it did work, you should see the email in your Gmail. Note that it often gets put into the Spam box so be sure to check there.

One important thing which puzzled me at this stage is that, when you send a test message, make sure you give the test email a proper title and a body text. Otherwise, Google’s SMTP server will consider your test message to be a spam and not send it… If you’re unsure if it’s sending it or not just open up ‘/var/log/mail.log’ and have a look. It’s also worth running the ‘mail’ command in Terminal again to see the inbox. In my case, I had a message titled ”Undelivered Mail Return” which told me that something was going wrong…

4 Comments Add Yours

  1. Gerardo

    Hi, your tutorial helped me a lot. But I still have a problem. When I enter the “sudo postmap generic” the terminal tells me I have no permission. So I change the permission to “chmod 777 generic” but I still get the same message of permissions denied. Do you know why?

    Reply
    • Takuma

      I think you’re not logged in as an administrator account. It’s easiest if you logged in as an administrator and ran it.

  2. S Daniels

    Hello. I followed all instructions. When I typed “mail” into Terminal, the reply was “no mail”. My log file shows no entry. What do I need to do?

    Reply
    • Takuma

      Sorry, I hadn’t seen the message until now. Has this been resolved?

Leave a Reply