Configure Postfix to Send Email with Gmail's SMTP From the Terminal
Tags: ubuntu, postfix, smtp, devops
Published: 2024-04-10 13:15:51

Open a tab on your browser, head to Gmail or yahoo mail or whatever other mail agent you use and then compose an email. This is the normal method of sending email from our computer that almost everyone is familiar with, but what if I told you you can send emails directly from your Linux terminal?

There are various ways to go about this but I will be using Mailx and Postfix on an ubuntu OS. Follow along and in no time you would have successfully sent your first mail from your Linux terminal.

## Install Mailx and Postfix

Mailx is a UNIX utility program for sending and receiving mail, also known as a Mail User Agent program.

The mailx command in Linux is a powerful tool that lets you send emails directly from your command line. It’s simple, efficient, and incredibly flexible.

It needs to be installed

![mailx not found](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/resce5eld8e4i9bsdeso.png)

First update your apt package

```sh
sudo apt update
```

Then use this command to install mailx:

```sh
sudo apt install mailutils
```

Email is sent and received using Postfix, a mail transfer agent (MTA). When you install mailx with the above command postfix is automatically installed as well if you didn't already have it installed.

After successful installation you will see the postfix configuration dialog (as shown below), you can choose the `internet site` option highlighted below.

![postfix config](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/30fr3sfjs80v4hvna7rn.png)

Like I said, installing mailx will install postfix automatically however if you want to install postfix manually, use the below command:

```sh
sudo apt install postfix
```

## Generate an Application Specific Password

We will need to save our gmail password in a file for this configuration but for security purposes I do not want to save my password in a file and this is why we will be generating an app specific password that we will use for this purpose.

This password will be unique and can only be used by postfix.

This password will be used by Postfix for SMTP authentication instead of your actual Gmail password. Even if someone were to get hold of this password it wouldn't work if it weren't from postfix. 

Follow these steps to generate the password:

:bulb: **TIP**
You must enable two factor authentication to be able to generate an app specific password on gmail.

:zap: Go to your Google Account settings (https://myaccount.google.com/).

:zap: Navigate to the "Security" section.

:zap: Under "Signing in to Google", select 2-Step Verification.

:zap: At the bottom of the page, select App passwords

:zap: Type a name for the password.

:zap: Click on "Create".

:zap: Copy the generated application-specific password and keep it handy, we will make use of it. 

This password will be used in the Postfix configuration.

## Create Your `sasl_passwd` File

sasl is simple authentication and security layer.

We will create a `sasl_passwd` file in the `/etc/postfix/sasl` directory

```sh
sudo vi /etc/postfix/sasl/sasl_passwd
```

In this file we will add the app specific password that we generated above.

Enter the below code into the file, what you're basically doing here is saving your gmail authentication (username and password) so that it can be used by postfix for authenticating.

>:bulb: **Expert Tip**
>
>The regular port used for postfix is 587, I started out using port 587 but it turned out that for some reasons my port 587 was closed (either that or my ISP was blocking communication from that port) and so my mails weren't sending so I had to switch to port 465 as you will see me use in this walkthrough.
>
In the same light, if you follow through this post and your mails do not make it out of the mail queue, try other posts such as 587 and 995.

Enter your password in the format below:

```sh
[smtp.gmail.com]:465 <your gmail email address>:<the app specific password>

eg [smtp.gmail.com]:465 example@abc.com:yourAPPspecificpassword 
```

:warning: **NOTE**
This is the email address that will be sender for all your outgoing emails.

The next thing to do is to create a hash database file for the password because postfix will only read the hash.

Do this with the command below:

```sh
sudo postmap /etc/postfix/sasl/sasl_passwd
```

This will create a `sasl_passwd.db` file in the `/etc/postfix/sasl` directory. You can `ls` that directory to confirm that it was correctly created.

At this point, for security purposes we will change the permissions of these two files above to ensure that only root (which is the owner of the files) can read them.

Use the command below:

```sh
sudo chmod 600 /etc/postfix/sasl/sasl_passwd /etc/postfix/sasl/sasl_passwd.db
```

## Configure Postfix to Use the Gmail Server

If you have your own custom smtp server you would be using it here but we will use the Gmail smtp server instead.

Open the postfix `main.cf` file:

```sh
sudo vi /etc/postfix/main.cf
```

Locate the `relayhost` and enter Gmail smtp there

```sh
relayhost = [smtp.gmail.com]:465
```

Add the following to the end of `/etc/postfix/main.cf` to enable SASL authentication for Postfix.

```sh
# Enable SASL authentication
smtp_use_tls = yes
smtp_sasl_auth_enable = yes
smtp_sasl_security_options = noanonymous
smtp_sasl_password_maps = hash:/etc/postfix/sasl/sasl_passwd
smtp_tls_security_level = encrypt
smtp_tls_CAfile = /etc/ssl/certs/ca-certificates.crt
smtp_tls_wrappermode = yes
```

Confirm that the certificate file exists. If it doesn't, you can install it using the below command:

```sh
sudo apt install ca-certificates
```

## Restart Postfix

To ensure that all these changes take effect, we need to restart Postfix.

Do this with the command below:

```sh
sudo systemctl restart postfix
```

## Firewall

Depending on your firewall configurations your firewall could block communications and cause the emails to not be sent so check your firewall status and if need be add rules to ensure that smtp is allowed.

```sh
sudo ufw status
```

If your firewall is inactive you can proceed along without adding any new rules.

To add new rules to allow smtp, use the below commands:

```sh
sudo ufw allow "Postfix"
sudo ufw allow "postfix SMTP"
sudo ufw allow "Postfix Submission"
```

![postfix firewall rule](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qytcwnhdkfb4b9sokb10.png)

## Export SSL Cert File

This step is optional, you might have no need for it. 

I needed to do this because I discovered that my openssl in my env could not find the path to my SSL certificate and so my connections kept dropping before the TLS handshake could be completed.

To solve this issue and successfully send a mail from my terminal, I have to export my CAFile path so openssl knows where to look.

Use the command below:

```sh
export SSL_CERT_FILE=/etc/ssl/certs/ca-certificates.crt
```

To persist it so that every time you boot up your system the changes remain, enter the above command in the `~/.bashrc` file or the `~/.bash_profile` file.

```sh
sudo vi ~/.bashrc
export SSL_CERT_FILE=/etc/ssl/certs/ca-certificates.crt
```

To apply the changes immediately, you can close your terminal and open another one or use the below command to apply the change to that same terminal.

```sh
source ~/.bashrc
```

## Send Mail

There are various ways you can send a mail from your terminal, I will show a few of them below.

### Method 1

The first method is using the echo command with mailx.

```sh
echo "Message 1 sent through the terminal" | mailx -s "Echo command mail 1" <email address of recipient>
```

![terminal mail1](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ctpi8sl4c0hk61cifinm.png)

We do not need to specify the sender as we have already done that in our `sasl_passwd` file.

The `s` flag indicates the subject of the mail.

![sent mail1](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/h6uxxzssk2vgugreriz5.png)

### Method 2

In an instance when you want to write an email with a very full body containing multiple lines you can write the body directly in the terminal without the echo command.

Start with the `mailx` command, the subject and the recipient then click enter. At this point mailx will wait for you to type the body of your email.

Go ahead and write the body of your email.

When you are done, enter a new line and press `ctrl D` to signify the end of the email and send it.

```sh
mailx -s "Terminal email number 2" <recipient's email address>
This is a mail trying out another method of sending an email from the terminal.
This method we are typing multiple times.
You can type multiple lines with the echo command as well.
But when you want multiple lines I prefer to use this method.
That's it for this example.

Thanks guys.
```

![terminal mail2](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3mlnwf6pmup94qio51gl.png)

You can see that the message was received.

![sent mail2](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3wp827j24gfib49stuwt.png)

### Method 3 

It is equally possible for the body of your mail to be gotten from the contents of a file.

To do this you will redirect the contents of the file to the command to send the mail like so:

```sh
mailx -s "Mail body from a file, mail 3" firstperson@mail.com, person2@mail.com, person3@mail.com < path/to/file
```

You can also send the mail to several people at the same time as shown in the code snippet above.

To demonstrate this, the first thing I will do is to create the file and then add some text to it. I'll do this with one command. Shown below:

```sh
echo "This is the body of our mail that will be gotten from this file mail.txt >> mail.txt
```

![mail text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gp9qh9dnwyh8hd1uh8uu.png)

Next I will send my mail

```sh
mailx -s "Mail body from a file, mail 3" [recipient email address] < ./mail.txt
```

![terminal mail3](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7bq4h6mmfpca5r1x9er7.png)

We can see that the content of the file has now been translated into the body of our mail.

![sent mail3](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/owseo0i293o2pjhvjers.png)

## Useful mailx flags

| Flag | Description | Example |
| ----- | ------------------------------------- | -------------------------------------|
| `-s` | Subject of the mail | echo 'Hello' &#124; mailx -s 'Subject' user@mail.com |
| `-c` | Add a CC to the mail, this will add the email address specified after the flag as CC (carbon copy) to the mail | echo 'Hello' &#124; mailx -s 'Subject' -c user2@mail.com user@mail.com |
| `-b` | Add a BCC to the mail, this will add the email address specified after the flag as BCC (blind carbon copy) to the mail | echo 'Hello' &#124; mailx -s 'Subject' -b user2@mail.com user@mail.com |
| `-r` | Specify recipient email address to the mail | echo 'Hello' &#124; mailx -r from@mail.com -s 'Subject' user@mail.com |
| `-a` | Add attachment to the mail | echo 'Hello' &#124; mailx -s   'Subject' -a file.txt user@mail.com |

And there you have it, don't forget to share this post if you found it helpful.