Vendor 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.
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 html_template = sys.argv 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) 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.