Use Python to send personalised mass emails

My first task in Python – sending mass emails to my tutorial students. I have an excel sheet with all the emails of the students’ who’ve selected my tutorial timeslots and I am trying to send the same emails to them. Should be simple.


First installed Atom as a text editor to write Python scripts. No particular reason just because the author of Learn Python the Hard Way recommended it.

Modules used: openpyxl and smtplib

Installation: openpyxl To do this need to run

sudo pip install openpyxl

Note 1 – after sudo, terminal prompts you to type passwords but it won’t show! Just type the correct passwork and hit enter.

Note 2- Before openpyxl need to install pip (package manager for python) first. According to this post, type

sudo easy_install pip

directly in my terminal and it worked.

Note 3- To exit sudo, type exit or sudo -k or command + D. See this post.

Note 4 – to run my script, change directory to where the file exists and type this in terminal –


Note 5- Python 2 and 3 seems to have different ways of installing modules.

Note 6 – for loop in Python is close at beginning and open in the end. for i in range (2,9) shows i = 2, 3, 4, 5, 6, 7, 8.

Note 7 – starttls() has be to put before ehlo() and the reason is here

My first attempt to log in through failed because google blocked the attempt. I then received an email in my mailbox confessing it blocked the attempt because of security settings. I changed the setting to “less secure apps” and it then worked.

Note 8- Python data structure: list, tuples and dictionaries. Compare to arrays in C++ and variables, lists in R. In R everything is automatically a list but just appear in different ways? In that sense it’s simpler and built for statistics as in dealing with sequences of data.

  • lists [] methods on lists- append, extend, insert, pop…
  • tuples () seperated by comma, immutable cannot change values; also faster than list; methods only index and count
  • dictionaries {}

Note 9- The smtplib documentation for Python 2.7 offers a fancier example (a technical documentation) with prompt for senders and receivers, as well as messages. There are three arguments for SMTP.sendmail() method.

Email headers need careful formatting and this requires detailed knowledge of arguments of sendmail method. Exerptions from the documentation above –

Send mail. The required arguments are an RFC 822 from-address string, a list of RFC 822 to-address strings (a bare string will be treated as a list with 1 address), and a message string. The caller may pass a list of ESMTP options (such as 8bitmime) to be used in MAIL FROM commands as mail_options. ESMTP options (such as DSN commands) that should be used with all RCPT commands can be passed as rcpt_options. (If you need to use different ESMTP options to different recipients you have to use the low-level methods such as mail(), rcpt() and data() to send the message.)

A simple solution here

Note 10- def defines a function


I tried simple text instead of html type of body message as the latter seem to be unnecessary at the moment.

Note 11 – this example   has a prompt in writing the body of email. It uses triple quotes to enclose a doc string (?what is that?)

To do personalization I have a “list” of names and emails paired together. one example put them in a dictionary and for loop through it.

Note 12 – use %s to replace and format strings this post illustrates. an example

"Hello %s, my name is %s." % ('Mike', 'Yuqiong') /n
"Today is %s %d." % ('Feb', 21)

Note 13 – when testing multiple instances in a dictionary with the same name, Python appends the later values to the same dictionary. In serious scenarios this will create bugs. use del to delete an unwanted varible.

Final codes 
Used SyntaxHighlighter Evolved to insert the code. Just wrap codes with [name-of-language] [/name-of-language] in the text editor without escaping html environment.

import openpyxl, pprint, smtplib
# smtplib and pprint seems to be pre-installed modules?

# Read tables into a Python object
print ('Opening workbook...')
wb = openpyxl.load_workbook('tutorials.xlsx')
# Get all sheet names
# Get a particular sheet - in this workbook, only one sheet "response"
response = wb.get_sheet_by_name('Responses') # Note here name is case sensitive
response['A1'] # Select a cell as an object
response['A1'].value # show the value of the cell

# Start the real work
emaillist = {} # email list is an empty obejct to be stored with email values
print ('Reading rows...')
for row in range(2, 60+1): # for loop is open in the end
    name = response['C'+str(row)].value # Note here how to manipulate strings in Python
    email = response['E'+str(row)].value
    emaillist[name] = email

import smtplib
from email.MIMEMultipart import MIMEMultipart
from email.MIMEText import MIMEText

smtpObj = smtplib.SMTP('', 587)
smtpObj.starttls() # Upgrade the connection to a secure one using TLS (587)
# If using SSL encryption (465), can skip this step
smtpObj.ehlo() # To start the connection
smtpObj.login('', 'psw')

nlist = 'name1', 'name2'
elist = '', ''

for i in range(0, len(elist)):
    msg = MIMEMultipart()
    msg['From'] = 'Yuqiong Li <>' # Note the format
    msg['To'] = '%s <' % nlist[i] +elist[i] + '>'
    msg['Subject'] = 'Testing email for %s' % nlist[i]
    message = '%s here is the email' % nlist[i]



Share this post

2 thoughts on “Use Python to send personalised mass emails

    1. Yuqli Post author

      谢谢毕娘娘指正!我不知道,网上随便扒来的代码,看来需要仔细看下 string format 的内容 lol



Leave a Reply

Your email address will not be published. Required fields are marked *