Skip to main content

email via the command line on OS-X

I needed to email cron job output from my OS-X machine to off-site recipients. To do this, I had to configure the OS-X Mail Transfer Agent (MTA), postfix, to route outgoing mail through a working SMTP server, in this case, GMail. These are my notes about how to configure this on OS-X Yosemite 10.10.3.

Configure

My first configuration attempt was using my standard SMTP service at an ISP. But the ISP used a non-standard port, 465, and postfix complained about using it. postfix can be configured to use port 465, but it requires additional work and additional software, neither of which I wished to deal with. Therefore, I punted, and chose to use GMail's SMTP service (which uses the standard port 587) and a GMail account.

Here's what worked:

  1. Basic postfix configuration:

    $ cd /etc/postfix
    $ sudo cp main.cf main.cf.orig
    $ sudo cat >> main.cf <<EOF
    ############################################################
    # Everything below this line added by KHE
    
    alias_maps = hash:/etc/aliases
    
    # 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 with 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
    EOF
    
  2. This is optional. Tell postfix where to forward email originally sent to the the local accounts root and khe (i.e., mine).

    On unmodified OS-X email to root accumulates in the local root mailbox. It usually sits there unread. The same thing happens to email sent to user or user@machine.local; it just accumulates unless read.

    To remedy this, I created two aliases so that local email sent root and khe is delivered to an email address that I actually read. Specifically, in /etc/postfix/aliases, I replaced the line that looks like this:

    #root:      you
    

    with the following:

    root:     myemailid@gmail.com
    khe:      myemailid@gmail.com
    

    Here are all of the necessary steps:

    $ cd /etc/postfix
    $ sudo cp aliases aliases.orig
    $ sudo emacs aliases   # make the changes described above
    $ sudo newaliases      # update the alias database
    
  3. Give postfix the credentials necessary to connect to your SMTP server.

    When postfix attempts to send email to you, it must have the userid and password for your account on the target SMTP server, in this case, GMail. postfix uses the SASL (Simple Authentication and Security Layer) framework to transmit these credentials. You will store your GMail credentials in the /etc/postfix/sasl/passwd file.

    $ sudo mkdir -p /etc/postfix/sasl
    $ cd /etc/postfix/sasl
    
    $ CREDS="[smtp.gmail.com]:587  myemailid@gmail.com:mypassword"
    $ sudo -s -- "echo '$CREDS' > passwd"
    $ sudo postmap passwd
    $ sudo chmod 0600 passwd passwd.db
    
  4. Tell launchctl about the postfix configuration and fire it up:

    $ cd /System/Library/LaunchDaemons/
    $ sudo launchctl unload org.postfix.master.plist
    $ sudo launchctl load -w org.postfix.master.plist
    
  5. Testing

    It's easy enough to test your setup:

    $ echo "hello, world" | mail myemailid@gmail.com
    

    If you performed step 2, these emails should show up in your inbox as well:

    $ echo "are we consing yet?" | mail root
    $ echo "Yow!"                | mail khe