Close Encounter with Vendor Lock-in, Python Triumphs

By | July 25, 2017

mailchimp logoVendor lock-in is a term that refers to the practice of a company making a customer dependent (but not entirely) on their goods or services. In IT circles, I hear Cisco’s name thrown around a lot with references to “building a moat“. Some other examples of this are: the patented K-Cup brewing system of Kuerig, printer ink cartridges in general, and Nvidia’s proprietary G-sync. My experience wasn’t nearly as dramatic, but I quickly felt the power that was being held over me when I went to follow up with readers who entered a giveaway that I coordinated through the use of a third party, MailChimp. I had a list of people who entered and wanted to follow up with them to let them know how the contest ended. When I went to send that email, a message popped up saying my account was temporarily disabled until further notice. There was a button I could click to send a message, but that was all. No response.

mailchimp

Sure, I probably could’ve imported the contacts list into gmail and sent it to everyone in BCC instead, but what fun would that be? Bonus tidbit: though adding HTML to emails in Gmail isn’t supported, you can still achieve it through Gmail’s browser interface (2nd answer).

I wanted to send that email over the weekend when people would have time to kill and might actually open it. But I couldn’t do that, and I’m not exactly a big spender with them so I did not expect this to be resolved quickly. Thankfully, they let you download your lists and email templates, so you aren’t entirely dependent. And I had a Python emailing script from a year ago, so I put 2 and 2 together and modified the script to send the email I designed with MailChimp to all the people on the mailing list I gathered with MailChimp. Here’s the code if you’re interested:


import smtplib
from email.mime.text import MIMEText
from time import sleep
import re
import io
import getpass
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
import csv
import sys

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
# created by transposed messenger on 7.24.2017 							       						   #
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
# You must turn ON less secure apps for Gmail (https://www.google.com/settings/security/lesssecureapps)#
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
# usage: subscriber_mailinglist.py /path/to/list.csv /path/to/htmltemplate.html 					   #
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
# http://adamantine.me/index.php/2016/06/11/how-to-create-a-bulk-emailing-script-with-python/          #
# http://adamantine.me/index.php/2017/07/25/close-encounter-with-vendor-lock-in-python-triumphs/       #
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

def main():

	while 1:
	
		sender = raw_input('Enter your sending email address: ')
		subjectline = raw_input('Enter your email subject line: ')
		passwd = getpass.getpass('Your password: ')
		answer = raw_input('"' + str(subjectline) + '"' + ' is your subject for this email.\n' + sender + ' is the sender email address.\n O.K.? Enter 1 to confirm. ')
		if answer == "1":
			break
			
	subscriberlist = sys.argv[1]
	html_template = sys.argv[2]

	try:
		s = smtplib.SMTP_SSL('smtp.gmail.com', 465)
		# identify ourselves to gmail client
		# use port 587 for TLS with the basic smtplib.SMTP('domain.com', 587) method.
		# re-identify ourselves as an encrypted connection
		s.ehlo()
		# If using TLS, uncomment the line below.
		# s.starttls()
		# login with user input if you are not comfortable storing your password in plaintext
		s.login(sender, passwd)
		s.set_debuglevel(1)
		
	except IOError:

		print IOError

	# initialize your sending address and create empty lists
	recipients = []

	# As it stands, the script takes a .csv file with emails in each cell of the first column
	with open(subscriberlist,'r') as csvfile:
	
		next(csvfile, None) # skip headers
		reader = csv.reader(csvfile)
		
		for row in reader:
		
			recipients.append(row[0])
	
	with open(html_template) as file:
			html = file.read()

	# write the message to a log file for later analysis/debugging
	# send an email every 75 seconds to avoid getting flagged as spam
	# print out "sending..." and the message for debugging purposes

	for k in range(len(recipients)):

		msg = MIMEMultipart('alternative')
		msg['Subject'] = subjectline
		msg['From'] = sender
		msg['To'] = recipients[k]
		html_body = MIMEText(html, 'html')
		msg.attach(html_body)
		
		print "Sending..."
		#print msg
		
		try:
			s.sendmail(sender, recipients[k], msg.as_string())
		
		# Basic error handling: sometimes the SSL/TLS connection is interrupted which will stop the script. When this happens, it will try to reconnect, send the message, and continue the loop.
		except Exception, e:
			
			print str(e) + "error: logging in and continuing loop with next address..."
			s = smtplib.SMTP_SSL('smtp.domain.com',465)
			s.ehlo()
			s.login(sender, passwd)
			s.set_debuglevel(1)
			continue	
		
		with io.open('log.txt', 'a', encoding='utf-8') as f:
		  
		  try:
			f.write(unicode(msg))
		  
		  # As the code stands, it has trouble with accented characters. You might want to figure out a way to remove them or change the encoding of the script.
		  except:
			f.write("Error handling ASCII encoded names: "+ unicode(recipients[k]))
			
		print "Sleeping for 75 seconds..."
		sleep(75)

	print "Messages have been sent."
	s.quit()

if __name__ == "__main__":
	main()

And that got my email across when the service I was depending on failed me (I even cleaned it up a little bit and made it more command line tool-ish). I am not denouncing MailChimp – they offer free and paid services that typically work extremely well. It’s not viable to hire a large enough support staff to handle every single account, paid and free alike. The hybrid free/paid model is the current best solution to the “things should be free-money motivation” conundrum. However, it is good to have something to fall back on if your current solution – paid or free – falls through. It is rarely good to be completely dependent on a thing, since it reduces competition and stifles creativity. Here’s to a healthy dose of self-reliance and Python.

Facebooktwittergoogle_plusredditpinterestlinkedintumblr

Leave a Reply

Your email address will not be published.