Yi Tang Data Scientist with Emacs

Build Notification Features

Data processing time will becomes longer and longer as the increasing rate of data volumes. Users may check-in frequently to see the whether it is finished. Most of the time they will found it hasn't, doing this the users make contact switch which break the flow of whatever the using was doing.

Sometimes the user can't stop doing so, either because they are impatient, or because they really have a deadline to catch. Also, with less likelihood, they might find errors in the processing, either because of the QC check fails, or running out of computational resources.

Giving this fact, it really makes sens to have your program actively inform the user on the process so that they doesn't need to check-in at all. Because users will be notified immediately whenever the whole progressing is completed, or there's error that the user needs to take action onup.

This blog posts walk though the basics of sending Emails in Python, composing and sending out Emails. Each component is broken down into small piceses. It helps you debug/tests Email program, and personalise your Emails. In the end, you should be able to build a email robot.

Prerequisite

Before going into the technical details, you have to check that you are able to send out emails. You need the

  • [ ] SMTP server,
  • [ ] user name,
  • [ ] password,
  • [ ] port number, and
  • [ ] communication protocol.

You could easily found out these information from your Email service provider. An example of Gmail is at Here.

To check if you have all the information correct, run the following snippet. It will try to send out an empty Email to yourself. Make sure you fill in the username and password before hit go.

  import smtplib
  username = <Fill In>
  password = <Fill In>
  conn = smtplib.SMTP("smtp.gmail.com")
  conn.starttls()  # set connection to TLS mode
  conn.login(username, password,)  # Log in to the remote server
  conn.sendmail(username, [username], 'For testing')  # Send emails
  conn.quit()  # close connection.
  

If you don't see error messages, that's great, you are all set. There should be an Email in your Inbox. It has no subject and for testing in the main body.

If you do, you need to double check the information, and try again. If you are sure that the information are correct, btu still can't send out, check your network configuration, maybe the firewall block the connection.

Once you are able to send out an empty email the next is to compose an full Email.

Compose An Email in Python

An Email is consisted of multiple parts, the Subject, Body, attachments, Signature, and also some meta-data including from, to, and date.

Firstly, create an object of MIMEMutiple() class. It will be the building block of your Email. The approached described here is to add each components into it.

Email meta data

Start with meta data.

   msg = MIMEMultipart()
   msg['From'] = 'your_email_address@somewhere.com'
   msg['To'] = 'email_friend_#28473@somewhere.com, email_friend_#122xs2212@somewhere.com'
   msg['Date'] = formatdate(localtime=True)  # standard.
   

Email body

For plain text, simply add

   body_txt = '''
   Hello,

   Just to tell you Python is awesome.
   '''
   plain_body = MIMEText(body_txt, "plain")
   

You could also try to compose an complex HTML email in Python, or use diffenret tool to generate the HTML and import in Python.

   html_txt = r'''\
   <html>
   <head></head>
   <body>
   <p>Hi!<br>
   How are you?<br>
   Here is the <a href="http://www.python.org">link</a> you wanted.
   </p>
   </body>
   </html>
   '''
   html_body = email.mime.text.MIMEText(html_txt, 'html')

   

Attachment

You can attach files of any type in an Email, specially, for image, you could use MIMEImage, and for audio, you could use MIMEAudio.

But you don't have to be specific. MIMEApplication would be sufficeincy for all cases. It will configure the file type of the attached file. Use it as follows:

 with open(fpath, 'rb') as fp:
     part = MIMEApplication(fp.read(), Name=basename(fpath))  # file content as string
     part['Content-Disposition'] = 'attachment; filename="%s"' % basename(f)  # attachment description.
     msg.attach(part)  # attach to the msg.
 

Put Everything Together

   from os.path import basename
   import smtplib
   from email.mime.application import MIMEApplication
   from email.mime.multipart import MIMEMultipart
   from email.mime.text import MIMEText
   from email.utils import formatdate

   # Configure your email
   username = <Fill in>
   password = <Fill in>
   recipents = <Fill in>
   subject = 'Hey'
   attachments = []  # add attachment here.
   body_txt = '''
      Hello,

      Just to tell you Python is awesome.
      '''

   # Email - meta data
   msg = MIMEMultipart()
   msg['From'] = username
   msg['To'] = ', '.join(recipents)
   msg['Subject'] = subject
   msg['Date'] = formatdate(localtime=True)  # standard.

   # Email - main body
   plain_body = MIMEText(body_txt, "plain")
   msg.attach(plain_body)

   # attachments
   for fpath in attachments or []:
       with open(fpath, 'rb') as fp:
	   part = MIMEApplication(fp.read(), Name=basename(fpath))  # file content as string
	   part['Content-Disposition'] = 'attachment; filename="%s"' % basename(fpath)  # attachment description.
	   msg.attach(part)  # attach to the msg.


   # send out email
   conn = smtplib.SMTP("smtp.gmail.com")
   conn.starttls()  # set connection to TLS mode
   conn.login(username, password)  # Log in to the remote server
   conn.sendmail(username, [username], msg.as_string())  # Send emails
   conn.quit()  # close connection.

   

Wrap everything in a Class

At JBARML, we are planing to send users emails for a progress update. Many of the data generating process are lured together and automated by a workflow manager. The whole programcan takes upto weeks to complete. Actively sending update progeress to user is much more senssible then user loggin in to a remote machien and check it now and then.

In this case,

email to notify user the progress of the data generating workflow.

If you have any questions or comments, please post them below. If you liked this post, you can share it with your followers or follow me on Twitter!
comments powered by Disqus