Today we will look at a method of using the SMTP protocol via Python. Our goal is to create a class through which we can send emails with attachments.
First, a word about the SMTP protocol.
- SMTP (Simple Mail Transfer Protocol) is the standard protocol for sending email via internet. By default, SMTP uses port number 25 and the transmission protocol is TCP. One of the first SMTP servers is sendmail, still widely in use, others exist, such as Postfix, Exim.
Ok, on to the code. The main way of sending emails via python is the smtplib.
Create a file called “smtp.py” in your working directory and paste the following code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 | import smtplib, os, time, atexit from email.MIMEMultipart import MIMEMultipart from email.MIMEBase import MIMEBase from email.MIMEText import MIMEText from email.Utils import formatdate from email import Encoders class ConnectionError(smtplib.SMTPException): pass class LoginError(smtplib.SMTPException): pass class DisconnectionError(smtplib.SMTPException): pass class EmailSendError(smtplib.SMTPException): pass class Smtp: def __init__(self, host, user, password, port=25): self._host = host self._port = port self._user = user self._password = password self._message = None self._subject = None self._from_addr = None self._rcpt_to = None self._server = None self._attachments = [] atexit.register(close) #our close() method will be automatically executed upon normal interpreter termination self.connect() def connect(self): if all([self._host, self._port, self._user, self._password]): try: self._server = smtplib.SMTP(self._host, self._port) except smtplib.SMTPException, e: raise ConnectionError("Connection failed!") try: self._server.login(self._user, self._password) except smtplib.SMTPException, e: raise LoginError("Login Failed!") def close(self): if self._server: try: self._server.quit() except smtplib.SMTPException, e: raise DisconnectionError("Disconnection failed!") def message(self, message): self._message = message def subject(self, subject): self._subject = subject def from_addr(self, email): self._from_addr = email def rcpt_to(self, email): self._rcpt_to = email def attach(self, file): if os.path.exists(file): self._attachments.append(file) def load_attachments(self, m_message): for file in self._attachments: part = MIMEBase('application', "octet-stream") part.set_payload(open(file,"rb").read()) Encoders.encode_base64(part) part.add_header('Content-Disposition', 'attachment; filename="%s"' % os.path.basename(file)) m_message.attach(part) return m_message def send(self, content_type='plain', charset='UTF-8'): if all([self._message, self._subject, self._from_addr, self._rcpt_to]): m_message = MIMEMultipart() m_message['From'] = self._from_addr m_message['To'] = self._rcpt_to m_message['Date'] = formatdate(localtime=True) m_message['Subject'] = self._subject m_message['X-Mailer'] = "Python X-Mailer" m_message.attach(MIMEText(self._message, content_type, charset)) m_message = self.load_attachments(m_message) try: self._server.sendmail(self._from_addr, self._rcpt_to, m_message.as_string()) except smtplib.SMTPException, e: raise EmailSendError("Email has not been sent") |
Here we have a simple class ready for sending email over an authenticated connection via python.
Now for the explanation (This should be easy to understand for those of us who already use python a bit).
Skipping over the various module import commands required to run our class, we come to the declaration of 4 classes (from line 8 to 11) needed for error management.
- ConnectionError – the exception generated if there is a problem in connecting to the SMTP server.
- Loginerror – the exception generated when there is a problem with the login (user/password).
- DisconnectionError – the exception generated when there is a problem when disconnecting from SMTP server.
- EmailSendError – the exception generated when there is a problem in sending the email.
As you can see every exception inherits smtplib.SMTPException. In this way you can also catch our exceptions, by using the baseclass smtplib module.
Now we move on to the explanation of SMTP class…
The class has an initialiser for the declaration of all attributes for the class and automatically calls the connect() method to connect to the SMTP server.
Moving on… at line number 33, we meet our connect() method, in which we will create an instance of the SMTP class (smtplib) and will then try to authenticate to the smtp server with self._server.login(). If there are errors in the connection or the login to the server, the two exceptions (ConnectionError, Loginerror) will be generated.
To successfully send an email certain data are needed: the sender, recipient, subject and message. For this reason, using our methods: from_addr(), rcpt_to(), subject(), and message() we will be able to upload all data needed to send our email. In addition to these basic methods, our class has a very useful method for attaching a file or files to our email, attach(file_path).
Now lets give it a try! Create a file named “test.py” in your working directory and paste the following code:
from smtp import Smtp smtp = Smtp("mail.server.com", "user", "password") smtp.subject('This is a test') smtp.message('Email message') smtp.from_addr('from@server.com') smtp.rcpt_to('to@server.com') smtp.attach("file1.jpg") smtp.attach("file2.gif") smtp.attach("file3.pdf") smtp.send()
Need more explanation?
Have fun using this!
superdrupermegapuper54321…
Very usefull info. Thanks!…