Python

Sending emails with Python

Sending, checking and replying to emails is a time consuming task, especially when you are doing it for a large number of people or customers where you just have to change the recipient’s name, address, age and other small things. It would be a very difficult task for you to write a program that could handle all types of your personal/business emails but still you can automate a lot of stuff in this regard which will eventually save you a lot of time.

For example, you want to send  a reminder to your customers for their remaining bills and you have all customer related data like their phone numbers, address, age etc in an excel sheet or a database then instead of doing it manually, you can write a simple program in Python to automatically do that for you. In this tutorial, we’ll learn how email protocol works and how you can automate the process to save your precious time.

A word about SMTP

Simple Mail Transfer Protocol (SMTP) is computerized equivalent of your postal service. It is a protocol that works on Application layer of a TCP/IP Network. Its a standard protocol for sending and receiving emails over the internet. Mail Transfer process consists of Email Servers and Clients sending and receiving emails to each other.

For example, you have a GMAIL account and you want to send an email to your friend on his YAHOO account. You write an email and hit send, but the backend process is a little complicated, and to understand this process, you will have to understand SMTP first. Your SMTP  email client first sends HELO (or EHLO) to the GMAIL server, you can say this command or header is equivalent of Host header in HTTP protocol and is used to identify the server using domain name. After HELO or EHLO, the client authenticate itself to the server with the given username and password using AUTH command. Then it specifies sender’s and recipient’s email address and then the message body and sends email to the GMAIL Server. GMAIL server will first confirm that whether the recipient’s email address on YAHOO exists or not, then it will send the email to YAHOO Server where recipient can retrieve his emails from.

SMTPLIB

SMTPLIB is a python library that can be used as an SMTP client just like your GMAIL, YAHOO, Thunderbird or any other email client and can be used to send emails. We can perform all tasks using SMTPLIB client that we can do with those having Graphical User Interface.

It comes by default in Python, incase you don’t have it then you can install using the following command.

ubuntu@ubuntu:~$ pip install smtplib

OR in Python3

ubuntu@ubuntu:~$ pip install smtplib

Writing your first Email with Python

In this tutorial, I’ll use a GMAIL account as sender, also I’ll be making use of Python console, so It’ll be easier for me to explain each line of code step by step. To get started, we need to allow our GMAIL access to less secure apps.

So login to your GMAIL account and then go to account settings.

Now make sure that access for less secure apps is turned on.

Now open your python console and start writing your first email using Python

ubuntu@ubuntu:~$ python
Python 2.7.16 (default, Oct  7 2019, 17:36:04)
[GCC 8.3.0] on linux2

Type “help”, “copyright”, “credits” or “license” for more information.

//import the SMTP library
>>> import smtplib

//connect to the GMAIL Server with domain name and port number (This setting differs for
each email provider, please take a look at the table given below)
>>> mailobj = smtplib.SMTP('smtp.gmail.com',587)

//say hello to the server
>>> mailobj.ehlo()
(250, 'smtp.gmail.com at your service, [103.255.4.246]\nSIZE35882577\n8BITMIME\nSTARTTLS\
nENHANCEDSTATUSCODES\nPIPELINING\nCHUNKING\nSMTPUTF8'
)

//Port 587 means that we’re using encrypted TLS connection, so start encrypted TLS
communication using starttls(), so that our credentials and messages don’t get sniffed
>>> mailobj.starttls()
(220, '2.0.0 Ready to start TLS')

//login to your GMAIL account using email and password
>>> mailobj.login('sender@gmail.com','s3cr3t_p4ssw0rd')
(235, '2.7.0 Accepted')

//specify sender and recipient’s email address and email content
>>> mailobj.sendmail('sender@gmail.com','usamaazad13141@gmail.com','Subject:
Hello world! \n Hello world! this is my first hello world email in Python'
)
{}

// close connection to the GMAIL server
>>> mailobj.quit()
(221, '2.0.0 closing connection b6sm4519863lfi.72 - gsmtp')

In the above sample program, replace the given content with your own. If you’re not a GMAIL user, then you can use email server of your provider. Here is the list of Domain Names and ports of some common mail providers.

Name Server Domain Name Port
Gmail smtp.gmail.com 587
Outlook / Hotmail smtp-mail.outlook.com 587
YAHOO Mail smtp.mail.yahoo.com 587
Verizon smtp.verizon.net 465
Comcast smtp.comcast.net 587

Some Words about IMAP

So we just studied that SMTP is used to send emails, but what is IMAP (Internet Access Messaging Protocol) for? SMTP can’t be used to search and get emails from the server, IMAP or POP3 protocol is used for that purpose.

IMAPCLIENT, IMAPLIB and PYZMAIL

There are two major libraries in Python that can be used as an IMAP client to find, retrieve and delete emails from the mail server. Python has default imaplib library but another external library imapclient is more effective and easy to use. In this tutorial we’ll use imapclient to retrieve emails from mail server.

The problem with imapclient is that it retrieves emails from mail server in raw format. So, we’ll need pyzmail library as a parser for user friendly output. To install both libraries, type

ubuntu@ubuntu:~$ sudo pip install imapclient
ubuntu@ubuntu:~$ sudo pip install pyzmail

Getting your Emails from Mail Server

Now, we’ll learn how to search and download email from the mail server using imapclient. We’ll use imapclient to search and download emails from the server, then we’ll use pyzmail to parse this raw content. Let’s

// import imapclient library
>>> import imapclient

// Connect to GMAIL’s IMAP server
>>> obj = imapclient.IMAPClient('imap.gmail.com',ssl=True)

// Login to your email account using your credentials
>>> obj.login('secretaccount@gmail.com','s3cr4tp4ss')
'secretaccount@gmail.com authenticated (Success)'

// Select message folder to read i.e INBOX, DRAFTS, SENT mails
>>> obj.select_folder('INBOX', readonly=True)

{'EXISTS': 830, 'PERMANENTFLAGS': (), 'HIGHESTMODSEQ': 112999, 'UIDNEXT': 931,
 'FLAGS': ('\\Answered', '\\Flagged', '\\Draft', '\\Deleted', '\\Seen',
'$NotPhishing', '$Phishing'), 'UIDVALIDITY': 1, 'READ-ONLY': [''], 'RECENT': 0}

// Search your messages in your INBOX, or apply a filter, below filter will show
you the mails received after 25-Oct-2019
>>> mail_ids = obj.search(['SINCE', '25-Oct-2019'])
>>> mail_ids
[919, 920, 921, 922, 923, 924, 925, 926, 927, 928, 929, 930]

// The list “mail_ids” contains a list of email ids received since 25-Oct-2019,
you can download an email using imapclient fetch function.
>>> raw_mail = obj.fetch([919],['BODY[]','FLAGS'])

// Now, the content in raw_mail variable is in raw format, it can’t be displayed on the
screen directly, So we’d need a parser to parse this content for a user friendly output

>>> import pyzmail
>>> message = pyzmail.PyzMessage.factory(raw_mail[919]['BODY[]'])

// Now email is parsed and stored in message variable, to get the subject of
the email, use get_subject function
>>> message.get_subject()
u'Dress up your skills this Halloween with 25% off'

// Similarly, you can see sender details
>>> message.get_addresses('from')
[(u'Usama Azad', 'usamaazad13141@gmail.com')]

>>> message.get_addresses('to')
[(u'secretaccount@gmail.com', 'secretaccount@gmail.com')]

// To get the body of the email, type
>>> message.text_part.get_payload().decode(message.text_part.charset)

u”Hi! Enjoy flat 25% on our premium courses”

If you have an account in some other Email Service provider other than GMAIL, you can login to their IMAP server. Here is the IMAP domain name list of some famous mail providers.

Provider Domain Name for IMAP Server
YAHOO imap.mail.yahoo.com
Hotmail/Outlook imap-mail.outlook.com
Verizon incoming.verizon.net
Comcast imap.comcast.net
AT&T imap.mail.att.net

Deleting your Email from IMAP Server

Similar to searching and retrieving emails from the server, you can also delete emails from your mail server using their uid. Just follow the given steps

// To delete an email, you have to turn read only to ‘False’ to get write access to your
emails
>>> obj.select_folder('INBOX', readonly=False)
>>> mail_ids = obj.search(['SINCE', '25-Oct-2019'])
>>> mail_ids
[919, 920, 921, 922, 923, 924, 925, 926, 927, 928, 929, 930]
 
// Provide an email uid or a list of email uids, after running below command,
your email will get disappeared from INBOX.

>>> obj.delete_messages(919)
{919: ('\\Seen', '\\Deleted')}
 
// This command will permanently delete your emails from the Mail server
>>> obj.expunge()
('Success', [])

https://techtopz.com/build-a-birthday-reminder-application-in-python-on-mac/

Making up your own birthday reminder

You have birthdays of your friends in coming months and you want to wish them on their birthdays. But you have a lot of work in your office and there is a possibility that you will forget to wish them. So this task can be automatically performed using python. Following is the code to perform this task.

// importing Modules
import re
// os module is used to perform operating system tasks i.e accessing direcotories
import os
import datetime
import smtplib
 
// defining a function which will be sending emails
def send_mail(reciever_mail_address, name):
  sender_mail_address = "sendermailaddress@gmail.com"
  passwd = "senderPasswd"
  //connecting to gmail server with domain name and port number
  obj = smtplib.SMTP('smtp.gmail.com', 587)
  obj.ehlo()
  obj.starttls()
  // logging into your gmail account
  obj.login(sender_mail_address, passwd)
  // sending mail to ‘reciever_mail_address’.
  obj.sendmail(sender_mail_address, reciever_mail_address, "Subject: BirthDay Wishing Mail\n\n HappyBirthday "+name)

  // ending connection
  obj.quit()

// Main Body
// going to the directory in which file containing data is present
os.chdir("path_to_birthday_data_file")
while 1:
  // getting date and time of present moment
  today = datetime.datetime.today()
  today = str(today)
  // getting current year, month, day, hour, minute and second
  current_year = today[0:4]
  current_month = today[5:7]
  current_day = today[8:10]
  current_hour = today[11:13]
  current_minute = today[14:16]
  current_sec = today[17:19]
  // opening birthday file in ‘birthday_file’ object in read mode
  birthday_file = open('birthday_file','r')
  // saving all the lines of ‘birthday_file’ in lines list
  lines = birthday_file.readlines()
  // closing ‘birthday_file’ object
  birthday_file.close()
  // reading each line using for loop
  for line in lines:

    // making a regular expression to find a date in ‘birthday_file’
    dateEx = re.compile(r"\d{4}-\d{2}-\d{2}")
    findDate=dateEx.search(line)
    date = findDate.group()

    // getting birthday_month and birthday_day from file
    birthday_month = date[5:7]
    birthday_day = date[8:10]

    // making a regular expression to find mail address from birthday_file
    mailEx = re.compile(r"\w*@\w*.com")
    findMail = mailEx.search(line)
    reciever_mail = findMail.group()

    //making a regular expression to find the name of the person
    nameEx = re.compile(r"\w*")
    findName = nameEx.search(line)
    name = findName.group()
    // checking if someone’s birthday is coming or not
    if current_month == birthday_month and =current_day == birthday_day:

      // sending mail at exact 08:00
      if current_hour == '08' and current_minute == '00' and current_sec == '00':
        // calling ‘send_mail’ function
        send_mail(reciever_mail, name)

Now we make a ‘birthday_file’, in which we save names, email addresses and their date of birth. This is a simple text file and looks like this.

Explanation

We will read this file using python script and check whose birthday is coming and wish them. First of all we will import some Modules. DATETIME Module has functions which give us current date and time and many more. But we will only use this to find the current date and time. SMTPLIB module is used to send mail and has been explained above. RE module has functions which is used to find regular expression from a string.

In this script, we define ‘send_mail’ function, which sends mail to the ‘reciever_mail_address’, whose name is ‘name’. Both the arguments are passed to the function from main body of msg. In the main body of the script we will see how we find ‘reciever_mail_address’ and ‘name’.

Sending email using smtplib has been explained above, so you can read it and it will not be discussed here.

In the main body, we go to the directory where we have saved ‘birthday_file’ using ‘os.chdir()’. Then we have a ‘while loop’ which is always true so it will check the birthday continuously. Now we get current date and time and save it in ‘today’ variable. It looks like this.

2019-11-01 16:19:07.144925

We will extract year, month, day, hour, minutes and seconds using indices  of these quantities. After this, we will open birthday_file in an object ‘birthday_file’ in read mode, so we can only read it. Now we will save all the lines of this file in lines list. ‘birthday_file.readlines()’ will save each line in ‘lines’ list. After this we will close birthday_file using ‘birthday_file.close()’ function.

Now we will read each line one by one using for loop. In each line only one person’s data is available in ‘birthday_file’, so we are reading only one person’s data at one time in this loop.

After this, we will extract Date of birth, email address and name of person using RE module. As we have written the date in the following format

YYYY-MM-DD

So we will make a regular expression ‘dateEx’ which finds this format in the line.

re.compile(r”\d{4}-\d{2}-\d{2})

Above command find a string which has ‘4 digits’ followed by ‘-’ then ‘2 digits’ followed by ‘-’ and ‘2 digits’. This will give us the date of birth of the person so we will extract birth_day and birth_month from this expression.

Similarly we will find email address using regular expressions. After this, we will compare the birthday_month and current_month and birthday_day and current_day. If these conditions are satisfied, we will send the birthday email using ‘send_mail’ function at exact ‘08:00’.

Running Script Automatically via Cronjob

Now we will make sure that this python script runs every time. To do this, we will add this task to crontab. Crontab, in linux, is used to perform tasks automatically. What we have to do is just add the task to crontab. To do so, follow the given steps.

  1. Open crontab to add task in your terminal using following command
ubuntu@ubuntu:~$ crontab -e
  1. At the end of this file enter following command without #
@reboot python path_to_the_script

Above commands will enable your system to run the python script every time you restart your system. In this way, your system will run python script every time when your system is on.

About the author

Usama Azad

Usama Azad

A security enthusiast who loves Terminal and Open Source. My area of expertise is Python, Linux (Debian), Bash, Penetration testing, and Firewalls. I’m born and raised in Wazirabad, Pakistan and currently doing Undergraduation from National University of Science and Technology (NUST). On Twitter i go by @UsamaAzad14