Skip to content
Related Articles

Related Articles

Improve Article
Save Article
Like Article

Send mails using a Bash Script

  • Difficulty Level : Hard
  • Last Updated : 15 Nov, 2021

Sending email via the command line can be quite a great feature to have especially on Linux which will allow some users to avoid using the GUI and installing all of the dependencies. We will look into the following article on how to write a BASH (shell) script that can send a custom email to any other email using the SMTP server.

Creating Google App

The sender’s email must be a Gmail account.  The 2FA should be enabled on this account. You will have to create an app on your Gmail id that will handle the email sending, permissions, and the rest of the stuff for you. It’s quite simple to do that, visit the Google App Password page. 

  1. Log in with your credentials from the above link
  2. Create an App  category-> Other give it any name(call it anything you like eg. mailterminal, bashmail)
  3. Now copy the password and store it securely somewhere.

Google App passwords.

Entering the app type

Entering the add name

Copy the code generated from the app and save it in a secure place, we will need this password later,

Copying the password for the app.

After the Google app is created we can finally move on to the script creation part. We will use cURL to fetch the server and post the email content on the particular route provided by the SMTP server.



User Input

We will first input the requirements from the input, these will be sender email, receiver email, google ap password, subject, body, and attachments if any. So it’s quite simple to take input in BASH We’ll use the read command along with the -p as an argument to prompt the user with an info message prompt for better understanding.

#!usr/bin/env bash

# Input for sender email 
read -p "Enter your email : " sender

# Input for recipient email
read -p "Enter recipient email : " receiver

# Input for google app password
read -p "Enter your Google App password : " gapp

# Input for subject of the mail
read -p "Enter the subject of mail : " sub

Taking input of body text in a file

So the sender email, receiver email, google app password, and the subject are taken care of but how we will input the body and the attachment. Well, for that we will use the cat command to first input into a file and copy all the content from that file into a variable like this:

# Using cat command to input multiline text to a variable (from file)

echo "Enter the body of mail : "
cat > tempfile.txt
body=$(cat tempfile.txt)

The cat command used with > can redirect the inputs to the file provided after the operator. You have to press CTRL + D to save the multi-line content which you have written and to quit from the cat command. Finally, we store the output of the cat command to a variable. We have used the cat command both ways to write to the file and also for reading from the file. Thus, we have the body variable to work with later. 

Adding an attachment file

Now comes the attachment part, we need to provide the positional argument as the file name to specify the attached file. 

# set file variable to the 1st positional parameter
file="$1"

# MIME type for multiple type of input file extensions
MIMEType=`file --mime-type "$file" | sed 's/.*: //'`

This will store the name of the file and next, we will also need the type of file.  we are extracting the file extension or its type from using the mime fields in the file. We are piping the filename with the sed editor and filtering the text after the ‘:’ in the output of the file command. The demonstration of the code is shown below:

adding attachments

So, the filename is stored in the file variable and the filetype is stored in the MIMEType variable. After this, we move on to the cURL command.

CURL command

The CURL command is one of the most useful and widely popular commands when it comes to its functionality. We will use the command to fetch the SMTP server i.e. smtps://smtp.gmail.com:465.  We are basically opening a connection to the Gmail server at a particular port and thereafter we will pass in some arguments and variables to make the body of the email.

SSL Requirement for SMTP Server

We are passing the URL as the SMTP server which is smtps://smtp.gmail.com:465 and we will send the email using the SSL connection as it is secure to send mail via the google server. For that, we will pass –ssl-reqd which will allow using the google account email. 



Adding Mail Sender, Receiver, and User Info

 We will start the mail body by adding the mail from the field which will be the sender in our case so we will use –mail-from as the value of the variable sender i.e $sender. We use a \ in a shell script to ignore everything after it in that line and move on to the next line just for better visibility and readability. After the mail sender argument is taken care of, we have the mail recipient argument which takes in the receiver mail address. We will use –mail-rcpt which will be assigned the value of the variable receiver as $receiver

# cURL command to send requests to SMTP server with arguments of given credentials
 
curl -s --url 'smtps://smtp.gmail.com:465' --ssl-reqd \
    --mail-from $sender \
    --mail-rcpt $receiver\
    --user $sender:$gapp \

The next bit of information is the user email and the password of the app which we generated before. We have to pass the argument as –user which takes two values separated by : as the email and password, we will simply pass the user email i.e the sender and gap variables.  

The main body of Mail

Thereafter we pass the argument -T for uploading a file but here we are not uploading any file for content in the mail, we will simply add it manually then the user types in the formatted file for simplifying things for the user. 

Inside the argument to the file we are writing the Header information as the sender, To field, subject, and finally the content of the mail i.e the body. 

# Creating the structure of mail using previously defined variables

-T <(echo -e "From: ${sender}
To: ${receiver}
Subject:${sub}

${body}")

File attachment

We also need to pass in the file attachment, we need to handle this independently now but if the user has not specified any file then we need to take care of that we don’t mess up the curl command. We can change the cURL command a bit for the attachment,  the header sections remain the same i.e till the password entry of the user.  We need to use the –F attribute to have a form for the attachment as well as the body. We will initialize the form with the multipart option that will allow us to embed the body as well as the file in a simple manner. We will then specify what goes in the form, firstly we will include the body as plain text and then add the attachment file into the file option provided and also encode it as per the file type which was initialized into MIMEType as a variable.  This ends the part of the form, we now can add the metadata like To, form, and subject to the mail.

For the meta-data, we will simply use the -H as the header to input the To, From, and Subject fields from the variables. Thus we have added an attachment to the mail, the gist for the mail attachment will look like this:

# cURL command for attachment file with extra parameters

curl -s --url 'smtps://smtp.gmail.com:465' --ssl-reqd \
    --mail-from $sender \
    --mail-rcpt $receiver\
    --user $sender:$gapp \
     -H "Subject: $sub" -H "From: $sender" -H "To: $receiver" -F \
    '=(;type=multipart/mixed' -F "=$body;type=text/plain" -F \
      "file=@$file;type=$MIMEType;encoder=base64" -F '=)'

Making the script logical

Now to avoid breaking the script when no attachment is passed we need to check for the positional parameter if the value is not assigned, we will simply not add the form and if it exists, we will add the form and change the flow accordingly.

To check for the positional parameters are assigned or not, we can use the -z condition in the if statement. this will check for any NULL or empty value, if the value is empty we will have simple cURL command otherwise, we will include a form in the cURL command. 

The full script is shown below:

Script

#!usr/bin/env bash

# User input
read -p "Enter your email : " sender
read -p "Enter recipient email : " receiver
read -p "Enter your Google App password : " gapp

read -p "Enter the subject of mail : " sub

echo "Enter the body of mail : "
cat > tempfile.txt                # using cat command for multiline input
body=$(cat tempfile.txt)          # storing the content of file in a variable

rm tempfile.txt


# check for provided attachment file as a positional parameter
# -z indicating an empty positional parameter
# attachment doesn't exist condition

if [ -z "$1" ]; then 


# curl command for accessing the smtp server

    curl -s --url 'smtps://smtp.gmail.com:465' --ssl-reqd \
    --mail-from $sender \
    --mail-rcpt $receiver\
    --user $sender:$gapp \
     -T <(echo -e "From: ${sender}
To: ${receiver}
Subject:${sub}

 ${body}")


# attachment exists condition
else

    file="$1"           # set file as the 1st positional parameter
    
    # MIME type for multiple type of input file extensions
    
    MIMEType=`file --mime-type "$file" | sed 's/.*: //'`
    curl -s --url 'smtps://smtp.gmail.com:465' --ssl-reqd \
    --mail-from $sender \
    --mail-rcpt $receiver\
    --user $sender:$gapp \
     -H "Subject: $sub" -H "From: $sender" -H "To: $receiver" -F \
    '=(;type=multipart/mixed' -F "=$body;type=text/plain" -F \
      "file=@$file;type=$MIMEType;encoder=base64" -F '=)'
     
fi

Mail sent from the terminal using the script

Mail appeared in the inbox with an attachment

You can attach only one file and mail can only be sent to one recipient in this script. You can extend the functionality by adding multiple recipients as well.  We were able to send emails from the terminal on a Gmail account using tools like cURL, sed, BASH programming language, and the SMTP server. 




My Personal Notes arrow_drop_up
Recommended Articles
Page :

Start Your Coding Journey Now!