Dave Perrett

Sending Mail With SendGrid on Ubuntu

email, miscellaneous, ubuntu

I keep forgetting how to do this, so purely for my own benefit - how to set up Ubuntu to send via sendmail and SendGrid.

First install the necessary packages:

1
> apt-get install sendmail sendmail-cf

If you try and start the sendmail service as is, you’ll more than likely run into an error:

1
2
3
> service sendmail restart
* Restarting Mail Transport Agent (MTA) sendmail
451 4.0.0 /etc/mail/sendmail.cf: line 104: fileclass: cannot open '/etc/mail/local-host-names': World writable directory

sendmail is pretty particular about folder permissions, and it doesn’t like the /etc/ folder permissions on a default Ubuntu install.

If we make the permissions a little stricter:

1
> chmod 0755 /etc

… and restart sendmail:

1
2
3
> service sendmail restart
* Restarting Mail Transport Agent (MTA) sendmail
[ OK ]

… then we’re in business!

Now that sendmail is running, we need to tell it how to connect to SendGrid.

Add the four lines marked by Add this below to /etc/mail/sendmail.mc just above the MAILER_DEFINITIONS line at the end of the file:

/etc/mail/sendmail.mc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
.....
dnl #

# ======== Add this ========
define(`SMART_HOST', `smtp.sendgrid.net')dnl
FEATURE(`access_db')dnl
define(`RELAY_MAILER_ARGS', `TCP $h 587')dnl
define(`ESMTP_MAILER_ARGS', `TCP $h 587')dnl
# ======== End Add ========

dnl # Default Mailer setup
MAILER_DEFINITIONS
MAILER(`local')dnl
MAILER(`smtp')dnl

The sendmail.mc file is a collection of macros that can be expanded into the real (and more complex) sendmail.cf config file. To Make your changes accessible to sendmail, we need to re-generate sendmail.cf using the m4 command:

1
> m4 /etc/mail/sendmail.mc > /etc/mail/sendmail.cf

Next, we need to set up the username and password we’ll be connecting to SendGrid with. Add the following line to the bottom of /etc/mail/access:

1
AuthInfo:smtp.sendgrid.net "U:<YOUR_SENDGRID_USER>" "P:<YOUR_SENDGRID_PASSWORD>" "M:PLAIN"

The role of /etc/mail/access is beyond the scope of this article, but suffice it to say that it needs to be used to generate the /etc/mail/access.db database map:

1
> makemap hash /etc/mail/access.db < /etc/mail/access

With both sendmail.cf and access.db in place, sendmail should be good to go after another restart:

1
2
3
> service sendmail restart
* Restarting Mail Transport Agent (MTA) sendmail
[ OK ]

Sending mail from the command line

To actually test the setup and send an email from the command line, you need a package that provides the mail command. There are a couple of these, but I like Heirloom mailx:

1
> apt-get install heirloom-mailx

With mailx in place, you should now be able to send yourself an email:

1
>  echo "mail body here" | mail -s "mail subject here" [email protected]

If you haven’t received the mail in a couple of minutes, /var/log/mail.err usually gives some pretty good clues to aid troubleshooting.

If this all sounds like too much hard work…

… and you’re as lazy as I am, just run the script below. Note that you’ll need to replace youruser and yourpassword with your actual SendGrid credentials!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#!/bin/sh

# Add your SendGrid credentials here.
SENDGRID_USER=youruser
SENDGRID_PASSWORD=yourpassword

# Install packages.
apt-get -y install sendmail sendmail-cf heirloom-mailx

# Sendgrid is very finicky about permissions.
chmod 0755 /etc

# Add SendGrid details to sendmail.mc.
grep smtp.sendgrid.net /etc/mail/sendmail.mc
if [ $? -ne 0 ]; then
  sed -i "s|dnl . Default Mailer setup|\n\
define(\`SMART_HOST', \`smtp.sendgrid.net')dnl\n\
FEATURE(\`access_db')dnl\n\
define(\`RELAY_MAILER_ARGS', \`TCP \$h 587')dnl\n\
define(\`ESMTP_MAILER_ARGS', \`TCP \$h 587')dnl\n\
\n\
dnl # Default Mailer setup|" /etc/mail/sendmail.mc

  m4 /etc/mail/sendmail.mc > /etc/mail/sendmail.cf
fi

# Add SendGrid details to access.db.
grep smtp.sendgrid.net /etc/mail/access
if [ $? -ne 0 ]; then
  cat >> /etc/mail/access <<EOF

#sendgrid auth credentials
AuthInfo:smtp.sendgrid.net "U:${SENDGRID_USER}" "P:${SENDGRID_PASSWORD}" "M:PLAIN"
EOF
  makemap hash /etc/mail/access.db < /etc/mail/access
fi

# Good to go!
service sendmail restart