If you are developing some Python module or application that needs to send some message to your users, one of the communication channel that you will use Email. Like any other language or framework, you will have a question about how can you send email from your application using Python. In this post, I will show you my EmailSender class. This class encapsulates all the low level details and expose one method sendEmail to allow your application to send email to recipients.
Before I provide some details how this is accomplished in Python, I will show you the code I use.
# email_sender.py from smtplib import SMTP, SMTPAuthenticationError, SMTPException, SMTPRecipientsRefused from email.message import EmailMessage, Message from config import Config from email_account import EmailAccount import mimetypes import os class EmailSender: """ Use EmailSender class to send emails to recipients. """ def __init__(self, emailAccount): self.emailAccount = emailAccount def sendEmail(self, subject, message, fromEmail, to, cc="", bcc="", attachments=None): try: smtp_sever = SMTP(self.emailAccount.host, self.emailAccount.port) if (len(self.emailAccount.username) != 0): smtp_sever.login(self.emailAccount.username, self.emailAccount.password) email_message = EmailMessage() email_message["Subject"] = subject email_message["From"] = fromEmail email_message["To"] = to email_message["CC"] = cc email_message["BCC"] = bcc email_message.set_content(message) if (attachments != None): for attachment_file in attachments: # Before reading attachment file, check if file exists or not if not os.path.exists(attachment_file): continue with open(attachment_file, "rb") as attachment: # Guess file's mimetype ctype, encoding = mimetypes.guess_type(attachment_file) # If we are not able to guess mimetype, then set it to generic octet-stream type if ctype is None or encoding is not None: ctype = "application/octet-stream" # Split the mimetype into main and subtype. We will need these individual types # when attaching the file's content to email. main_type, sub_type = ctype.split("/",1) attachment_data = attachment.read() email_message.add_attachment(attachment_data, maintype=main_type, subtype=sub_type, filename=os.path.basename(attachment_file)) smtp_sever.send_message(msg=email_message) except SMTPException: print("SMTP error!") except SMTPAuthenticationError: print("SMTP authetnication failed!") except SMTPRecipientsRefused: print("SMTP recepients refused") finally: pass if __name__ == "__main__": app_config = Config() app_config.load() email_sender = EmailSender(app_config.configuration.emailAccount) email_sender.sendEmail(subject="Hello Python", message="Geetings from Python Email Sender", fromEmail="firstname.lastname@example.org", to="email@example.com", cc="firstname.lastname@example.org", bcc="email@example.com", attachments=["config.json"]) # email_account.py class EmailAccount: def __init__(self, email, displayName, host, username, password, enableSsl=False,useDefaultCredentials=False,port=25): self.email=email self.displayName = displayName self.host = host self.username = username self.password = password self.port = port self.enableSsl = enableSsl self.useDefaultCredentials = useDefaultCredentials
In Python, SMTP protocol functionality is provided by smtplib module. In your code, you are going to need to import objects from this module. Next is construction of message that needs to be sent in your email. Python has email package that provides functionality to create message details that is RFC compliant.
EmailSender class allows the caller to provide path of attachments that need to be send to recipients. The implementation ensures that attachment files exist and can be read. The implementation uses a support class, EmailAccount, to encapsulates host and other information about sending server. These settings include credentials settings as well. You can extend this class to include other authentication methods as well.