How to create a bulk emailing script with Python

By | June 11, 2016

gmailHello. In this post we are going to cover how to use Python’s SMTPLib to send emails. The library interfaces with your mail provider’s smtp servers, so this is by no means a tutorial on how to create your own mail server. Those are far more complicated. Instead, we will connect to the mail provider by specifying the domain, commonly “smtp.gmail.com” or “smtp.mail.yahoo.com”, as well as the port number and your login information. For your convenience, here is a list of the most popular mail providers SMTP servers:

 

Authentication for the following is SSL (port 465)

  • smtp.gmail.com
  • smtp.mail.yahoo.com
  • smtp.mail.yahoo.co.uk
  • smtp.att.yahoo.com
  • smtp.live.com (hotmail)
  • outgoing.verizon.net

And these are StartTLS (port 587)

  • smtp.aol.com
  • smtp.comcast.net

Your mail provider should have a webpage with this information, just Google “___ smtp server”. Without further delay, here is the code:
initialization
This sets up a connection to the gmail account and initializes some variables that will be needed to generate unique emails.
main method
This is the meat of the code.



The plain English translation of the above code is as follows: create a connection to the SMTP servers and identify ourselves. Try logging in, if that doesn’t work, print the error. Initialize some lists with strings (variation0-3). Create a generic message template named “template”. Initialize the variables sender, recipients, and names so they can be populated later. Open the text file containing the email addresses. For each email address, strip the newline character (\n) from each address/name pair and add them to the lists we created.

For each item in “recipients”, create a pseudo-random message using the choice() method. Enter in the recipient, sender, then try sending the mail. If that fails, try to reconnect to the SMTP server and continue with the next address.

But if the sending worked, write the message to “log.txt”. Create log.txt if it does not exist. Use append mode (‘a’). If that fails, try casting the message as unicode and note that there was an error. Sleep for 75 seconds. Repeat for each recipient. Close the file. Close the SMTP connection. End of file.

That, in addition to the comments in the source code, should be enough to understand what is going on. This is a very generic template, but the focus is working code that can easily be adapted to the individual’s need. For instance, there could easily be better error handling, debugging, and logging. The bulk of the code should probably live inside a main method, with a few functions defined above. Being able to launch the script with additional parameters, or the ability to read user input, is oftentimes more desirable. However if you just want a quick and dirty script, this will work as it stands (you’ll need to edit it, though). Here is a link to the SMTPlib documentation if you would like to know more details.

open mail

Why bother saving every email you send to a log file? While you are using an email account that you can log into via a web browser, many mail providers won’t display a record of your sent mails if you send them via this method. Furthermore, don’t you want to know which messages are more likely to generate responses? Apart from avoiding spam detection, this pseudo-random message generator I have built into the script offers another great advantage: the ability to test which messages are most effective once you know who ended up clicking a link, making a purchase, etc. You would need further scripts to create the data files for analysis, though. This is simply a solution for the individual or small group. If you are less experienced with Python and are trying to carry out a mailing list for your company, I strongly advise that you seek out MailChimp or one of their competitors for this important task.

To do: We also want to absolutely avoid any possibility of sending to emails that don’t exist. This will flag you as a spam sender if you fail too many sends. Say we have a list of thousands of emails. I don’t want to remove emails that were typed incorrectly by hand, so I wrote this short script to detect anything undesirable and create a new, cleaner list.


# run in same directory as your list file
# removes unwanted emails based on them containing a listed string
# fill in the list with strings of your choice

# example typos and usages are enumerated below in the list "bads"
bads = ["@unwanteddomain.com", "mial.", "@yaho."]
addrs = []

# reads input file "emails.txt" and loads entries into a list "addrs"
with open('emails.txt', 'r') as f:
     for k in f:
	addrs.append(k)

print "There are " +str(len(addrs)) + " emails to begin with."
for l in addrs:
	for m in bads:
		if m in l:
			break
	else:
		with open("emailsCleaned.txt",'a') as p:
			p.write(l)

print "DONE! " + str(len(addrs)) + " total adresses after applying the filter."

You’d be surprised at how many people mistype or “almost” type their email addresses. For example, “mial” instead of “mail”. You may exclude certain domains if you wish. Maybe add a few lines that detects duplicates. Run the script a few times, adding more definitions as you go, until it no longer removes any entries. Note: the script writes with append mode (‘a’), so it will add lines after any existing lines in the file. Write mode (‘w’) will overwrite the previous file contents.

Limits – Make sure you aren’t sending too many mails per hour/day. It depends on your mail provider, and also your internet service provider. For example, Comcast will allow 1,000 emails to be sent from your residence per day, but if you have a business class account, that number increases to 24,000. Also, you can send a message with up to 500 recipients in the Gmail web GUI, but if you are sending it via software like this, that number drops to 100. Here is some information on the sending rate limits based on mail provider:

  • Gmail, 500 per day, 20 per hour
  • Yahoo 500 per day, 100 per hour
  • Hotmail 100 per day

Most free services are around 500/day and 20/hour. Make sure to set the sleep on the script to 180 before you run the script. You can gradually decrease the sleep to find the limit. And of course, please only send emails to those who have opted in. Nobody likes unsolicited junk mail. This should go without saying.

What if you want to send attachments? Although I haven’t tested it myself, I believe it is relatively simple. Look at this stackexchange question for some ideas.

Conclusion

This script provides a simple but working way to send emails in bulk without being flagged as spam, for free. You won’t be able to send millions of emails by simply reducing the sleep time, but you can reach out to subscribers or coworkers with notifications or event reminders. If you were hoping to create a mass mailer, you’ll need to overcome the previously mentioned restrictions that mail providers and ISP’s enforce. Feel free to comment with any questions, additions, suggestions, and so on. Cheers!

Facebooktwittergoogle_plusredditpinterestlinkedintumblr

5 thoughts on “How to create a bulk emailing script with Python

  1. Anonymous

    recipients.append(re.split(‘:’, line)[1])
    IndexError: list index out of range

    I am getting this error

    Reply
    1. transposedmessenger Post author

      Sounds like your mail list consists of only email addresses for each line, this example code uses a list with “emailaddress:full name” format, you’ll have to modify the code to get it working. Good luck!

      Reply
  2. Anonymous

    Mine sends the email with all the recipients at the same time, it does not do individual emails. I have pretty similar code. Do you know why this might be?

    Reply

Leave a Reply

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