8 months

Engaging with E-mails




 

E-mail is one of the most popular ways of digital communication. Python has a rich number of built-in libraries for dealing with e-mails.


The mail that you send from your client interface does not reach the receiver's computer directly. Your mail travels through a number of specialized e-mail servers. These servers run a piece of software called the Mail Transfer Agent (MTA), and its primary job is to route the e-mail to the appropriate destinations by analyzing the mail header, among other things. Lots of other things also happen en-route, and then the mail reaches the recipient's 
local e-mail gateway. Then, the recipient can retrieve the e-mail by using his or her e-mail client.

Simple Mail Transfer Protocol (SMTP): The SMTP protocol is used by the MTA for delivering your e-mail to the recipient's e-mail server. The SMTP protocol can only be used for sending e-mails from one host to another.

Post Office Protocol 3 (POP3): The POP3 protocol provides a simple and standardized way for the users to gain access to the mailboxes and then download the messages to their computers. When using the POP3 protocol, your e-mail messages will be downloaded from the Internet service provider's (ISP) mail server to the local computer. You can also leave the copies of your e-mails on the ISP server.

Internet Message Access Protocol (IMAP): The IMAP protocol also provides a simple and standardized way for accessing your e-mail from the ISP's local server. IMAP is a client/server protocol in which the e-mails are received and held for you by your ISP. As this requires only a small data transfer, this scheme works well even over a slow connection, such as the mobile phone network. Only if you send a request to read a specific e-mail, that email message will be downloaded from the ISP. You can also do some other interesting things, such as creating and manipulating folders or mailboxes on the server, deleting messages, and so on.

Python has three modules, smtplib, poplib, and imaplib, which support SMTP, POP3, and the IMAP protocols respectively. Each module has options for transmitting the information securely by using the Transport Layer Security (TLS) protocol. Each protocol also uses some form of authentication for ensuring the confidentiality of the data.

 

Sending e-mails with SMTP

The smtplib module provides an SMTP objects which is used for sending mail by using either an SMTP or an Extended SMTP (ESMTP) protocol. The e-mail module helps us in constructing the e-mail messages with the help of the various header information and attachments. This module conforms to the Internet Message Format(IMF).

The email.mime module provides classes for creating the e-mail and MIME objects from scratch. MIME is an acronym for Multi-purpose Internet Mail Extensions. This is an extension of the original Internet e-mail protocol. This is widely used for exchanging different kinds of data files, such as audio, video, images, applications, and so on.

from email.mime.multipart import MIMEMultipart()
 msg = MIMEMultipart()
 msg['To'] = recipient
 msg['From'] = sender
 msg['Subject'] = 'Email subject..'
 part = MIMEText('text', 'plain')
 message = 'Email message ….'
 part.set_payload(message)
 msg.attach(part)

 

Sending an e-mail message

The smtplib module supplies us with an SMTP class, which can be initialized by an SMTP server socket. Upon successful initialization, this will give us an SMTP session object. The SMTP client will establish a proper SMTP session with the server. This can be done by using the ehlo() method for an SMTP session object. The actual message sending will be done by applying the sendmail() method to the SMTP session.

session = smtplib.SMTP(SMTP_SERVER, SMTP_PORT)
 session.ehlo()
 session.sendmail(sender, recipient, msg.as_string())
 session.quit()

import smtplib
from email.mime.image import MIMEImage
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
SMTP_SERVER = 'aspmx.l.google.com'
SMTP_PORT = 25
def send_email(sender, recipient):
 """ Send email message """
 msg = MIMEMultipart()
msg['To'] = recipient
 msg['From'] = sender
 subject = input('Enter your email subject: ')
 msg['Subject'] = subject
 message = input('Enter your email message. Press Enter when  finished. ')
 part = MIMEText('text', "plain")
 part.set_payload(message)
msg.attach(part)
 # create smtp session
 session = smtplib.SMTP(SMTP_SERVER, SMTP_PORT)
 session.ehlo()
 #session.set_debuglevel(1)
 # send mail
 session.sendmail(sender, recipient, msg.as_string())
 print("You email is sent to {0}.".format(recipient))
 session.quit()
if __name__ == '__main__':
 sender = input("Enter sender email address: ")
 recipient = input("Enter recipient email address: ")
 send_email(sender, recipient)

 

Sending e-mails securely with TLS

TLS protocol is a successor of SSL or Secure Socket Layer. This ensures that the communication between the client and the server is secure. This is done by sending the message in an encrypted format so that unauthorized people cannot see the message. It is not difficult to use TLS with smtplib. After you create an SMTP session object, you need to call the starttls() method. Before sending an e-mail, you need to login to the server by using the SMTP server redentials.

import getpass
import smtplib
from email.mime.image import MIMEImage
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
SMTP_SERVER = 'smtp.gmail.com'
SMTP_PORT = 587 # ssl port 465, tls port 587
def send_email(sender, recipient):
 """ Send email message """
 msg = MIMEMultipart()
 msg['To'] = recipient
 msg['From'] = sender
msg['Subject'] = input('Enter your email subject: ')
 message = input('Enter your email message. Press Enter when  finished. ')
 part = MIMEText('text', "plain")
 part.set_payload(message)
 msg.attach(part)
 # create smtp session
 session = smtplib.SMTP(SMTP_SERVER, SMTP_PORT)
 session.set_debuglevel(1)
 session.ehlo()
 session.starttls()
 session.ehlo
 password = getpass.getpass(prompt="Enter you email password:  ") 
 # login to server
 session.login(sender, password)
 # send mail
 session.sendmail(sender, recipient, msg.as_string())
 print("You email is sent to {0}.".format(recipient))
 session.quit()
if __name__ == '__main__':
   sender = input("Enter sender email address: ")
   recipient = input("Enter recipeint email address: ")
   send_email(sender, recipient)


Retrieving e-mails by using POP3 with poplib

The stored e-mail messages can be downloaded and read by the local computer. The POP3 protocol can be used to download the messages from the e-mail server. 
Python has a module called poplib, and it can be used for this purpose. This module provides two high-level classes, POP() and POP3_SSL(),which implement the POP3 and POP3S protocols respectively for communicating with a POP3/POP3S server. It accepts three arguments, host, port, and timeout. If port is omitted, then the default port (110) can be used. The optional timeout parameter determines the length (in seconds) of the connection timeout at the server.


The secure version of POP3() is its subclass POP3_SSL(). It takes additional parameters, such as keyfile and certfile, which are used for supplying the SSL 
certificate files, namely the private key and certificate chain file.

mailbox = poplib.POP3_SSL(<POP3_SERVER>, <SERVER_PORT>) 
mailbox.user('username')
mailbox.pass_('password')

By default, the POP3 server listens on port 995 securely. 

import getpass
import poplib
GOOGLE_POP3_SERVER = 'pop.googlemail.com'
POP3_SERVER_PORT = '995'
def fetch_email(username, password): 
 mailbox = poplib.POP3_SSL(GOOGLE_POP3_SERVER,  POP3_SERVER_PORT) 
 mailbox.user(username)
 mailbox.pass_(password) 
 num_messages = len(mailbox.list()[1])
 print("Total emails: {0}".format(num_messages))
 print("Getting last message") 
 for msg in mailbox.retr(num_messages)[1]:
 print(msg)
 mailbox.quit()
if __name__ == '__main__':
 username = input("Enter your email user ID: ")
 password = getpass.getpass(prompt="Enter your email password: ") 
 fetch_email(username, password)

Retrieving e-mails by using IMAP with imaplib

Python provides a client-side library called imaplib, which can be used for accessing e-mails over the IMAP protocol. This provides the IMAP4() class, which implements the IMAP protocol. It takes two arguments, that is, host and port for implementing this protocol. By default, 143 has been used as the port number. 
The derived class, that is, IMAP4_SSL(), provides a secure version of the IMAP4 protocol. It connects over an SSL encrypted socket. So, you will need an SSL friendly socket module. The default port is 993. Similar to POP3_SSL(), you can supply the path to a private key and a certificate file path.

mailbox = imaplib.IMAP4_SSL(<IMAP_SERVER>, <SERVER_PORT>) 
 mailbox.login('username', 'password')
 mailbox.select('Inbox')

import getpass
import imaplib
import pprint
GOOGLE_IMAP_SERVER = 'imap.googlemail.com'
IMAP_SERVER_PORT = '993'
def check_email(username, password): 
 mailbox = imaplib.IMAP4_SSL(GOOGLE_IMAP_SERVER,  IMAP_SERVER_PORT) 
 mailbox.login(username, password)
 mailbox.select('Inbox')

tmp, data = mailbox.search(None, 'ALL')
 for num in data[0].split():
 tmp, data = mailbox.fetch(num, '(RFC822)')
 print('Message: {0}\n'.format(num))
 pprint.pprint(data[0][1])
 break
 mailbox.close()
 mailbox.logout()
 
if __name__ == '__main__':
 username = input("Enter your email username: ")
 password = getpass.getpass(prompt="Enter you account password:  ")
 check_email(username, password)

Sending e-mail attachments

import os
import getpass
import re
import sys
import smtplib
from email.mime.image import MIMEImage
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
SMTP_SERVER = 'aspmx.l.google.com'
SMTP_PORT = 25
def send_email(sender, recipient):
 """ Sends email message """
 msg = MIMEMultipart()
 msg['To'] = recipient
 msg['From'] = sender
 subject = input('Enter your email subject: ')
 msg['Subject'] = subject
 message = input('Enter your email message. Press Enter when  finished. ')

part = MIMEText('text', "plain")
 part.set_payload(message)
 msg.attach(part)
 # attach an image in the current directory
 filename = input('Enter the file name of a GIF image: ')
 path = os.path.join(os.getcwd(), filename)
 if os.path.exists(path):
 img = MIMEImage(open(path, 'rb').read(), _subtype="gif")
 img.add_header('Content-Disposition', 'attachment', 
 filename=filename)
 msg.attach(img)
 # create smtp session
 session = smtplib.SMTP(SMTP_SERVER, SMTP_PORT)
 session.ehlo()
 session.starttls()
 session.ehlo
 # send mail
 session.sendmail(sender, recipient, msg.as_string())
 print("You email is sent to {0}.".format(recipient))
 session.quit()
if __name__ == '__main__':
 sender = input("Enter sender email address: ")
 recipient = input("Enter recipeint email address: ")
 send_email(sender, recipient)


Sending e-mails via the logging module

import logging.handlers
import getpass
MAILHOST = 'localhost'
FROM = '[email protected]'
TO = ['%[email protected]' %getpass.getuser()] 
SUBJECT = 'Test Logging email from Python logging module  (buffering)'
class BufferingSMTPHandler(logging.handlers.BufferingHandler):
 def __init__(self, mailhost, fromaddr, toaddrs, subject,  capacity):
 logging.handlers.BufferingHandler.__init__(self, capacity)
 self.mailhost = mailhost
 self.mailport = None
 self.fromaddr = fromaddr
 self.toaddrs = toaddrs
 self.subject = subject

self.setFormatter(logging.Formatter("%(asctime)s 
 %(levelname)-5s %(message)s"))
 def flush(self):
 if len(self.buffer) > 0:
 try:
 import smtplib
 port = self.mailport
 if not port:
 port = smtplib.SMTP_PORT
 smtp = smtplib.SMTP(self.mailhost, port)
 msg = "From: %s\r\nTo: %s\r\nSubject: 
 %s\r\n\r\n" % (self.fromaddr, 
 ",".join(self.toaddrs), self.subject)
 for record in self.buffer:
 s = self.format(record)
 print(s)
 msg = msg + s + "\r\n"
 smtp.sendmail(self.fromaddr, self.toaddrs, msg)
 smtp.quit()
 except:
 self.handleError(None) # no particular record
 self.buffer = []
def test():
 logger = logging.getLogger("")
 logger.setLevel(logging.DEBUG)
 logger.addHandler(BufferingSMTPHandler(MAILHOST, FROM, TO,  SUBJECT, 10))
 for data in ['First', 'Second', 'Third', 'Fourth']:
 logger.info("%s line of log", data)
 logging.shutdown()
if __name__ == "__main__":
 test()


Responses(0)