#!/usr/bin/env python """Sending Email in Python A useful set of functions to facilitate the sending of emails in your Python application. Supports plain text email body and file attachments complete with Cc and Bcc support. """ from smtplib import SMTP from itertools import chain from errno import ECONNREFUSED from mimetypes import guess_type from subprocess import Popen, PIPE from email.mime.base import MIMEBase from email.mime.text import MIMEText from socket import error as SocketError from email.encoders import encode_base64 from email.mime.multipart import MIMEMultipart from os.path import abspath, basename, expanduser def get_mimetype(filename): """Returns the MIME type of the given file. :param filename: A valid path to a file :type filename: str :returns: The file's MIME type :rtype: tuple """ content_type, encoding = guess_type(filename) if content_type is None or encoding is not None: content_type = "application/octet-stream" return content_type.split("/", 1) def mimify_file(filename): """Returns an appropriate MIME object for the given file. :param filename: A valid path to a file :type filename: str :returns: A MIME object for the givne file :rtype: instance of MIMEBase """ filename = abspath(expanduser(filename)) basefilename = basename(filename) msg = MIMEBase(*get_mimetype(filename)) msg.set_payload(open(filename, "rb").read()) msg.add_header("Content-Disposition", "attachment", filename=basefilename) encode_base64(msg) return msg def send_email(to, subject, text, **params): """Send an outgoing email with the given parameters. This function assumes your system has a valid MTA (Mail Transfer Agent) or local SMTP server. This function will first try a local SMTP server and then the system's MTA (/usr/sbin/sendmail) connection refused. :param to: A list of recipient email addresses. :type to: list :param subject: The subject of the email. :type subject: str :param test: The text of the email. :type text: str :param params: An optional set of parameters. (See below) :type params; dict Optional Parameters: :cc: A list of Cc email addresses. :bcc: A list of Cc email addresses. :files: A list of files to attach. :sender: A custom sender (From:). """ # Default Parameters cc = params.get("cc", []) bcc = params.get("bcc", []) files = params.get("files", []) sender = params.get("sender", "root@localhost") recipients = list(chain(to, cc, bcc)) # Prepare Message msg = MIMEMultipart() msg.preamble = subject msg.add_header("From", sender) msg.add_header("Subject", subject) msg.add_header("To", ", ".join(to)) cc and msg.add_header("Cc", ", ".join(cc)) # Attach the main text msg.attach(MIMEText(text)) # Attach any files [msg.attach(mimify_file(filename)) for filename in files] # Contact local SMTP server and send Message try: smtp = SMTP() smtp.connect() smtp.sendmail(sender, recipients, msg.as_string()) smtp.quit() except SocketError as e: if e.args[0] == ECONNREFUSED: p = Popen(["/usr/sbin/sendmail", "-t"], stdin=PIPE) p.communicate(msg.as_string()) else: raise def test(): send_email(["root@localhost"], "Test", "Test Message") if __name__ == "__main__": test()