Snippets

Daniel Homola Send email through your Gmail account with Python

Created by Daniel Homola last modified
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
Module for sending emails with attachment through a gmail account.

A few stackoverflow threads and Justin Duke's blog post was used to write this.
Please have a look at __credits__.

This method only works if you sign in to the gmail account and then go to:
https://www.google.com/settings/security/lesssecureapps and allow access
for less secure apps.

By default it sends html formatted email. Multiple recipients is supported.
No sanity checking is involved, so use it as a 'consenting adult'.
"""

__author__ = 'Daniel Homola'
__copyright__ = "Copyright 2015"
__credits__ = ['Justin Duke', 'Oli Warner', 'pcboy', 'Daniel Homola']
__license__ = "BSD"
__version__ = "0.1"
__maintainer__ = "Daniel Homola"
__email__ = "dani.homola@gmail.com"
__status__ = "Prototype"

import smtplib
import traceback
import os
from email.mime.multipart import MIMEMultipart
from email.mime.base import MIMEBase
from email.mime.text import MIMEText
from email.utils import COMMASPACE, formatdate
from email import encoders


class Gmail(object):
    """
    Class for sending emails through a gmail account.

    :param gmail_user: gmail address not just username
    :param gmail_pwd: gmail password
    :param mail_to: list of recipient(s)' email address(es)
    :param subject: subject of email
    :param message: text of the message
    :param files: list of strings pointing to the attachments

    """

    def __init__(self, gmail_user, gmail_pwd, mail_to, subject, message,
                 files=None):
        """
        Returns a Gmail object with its default variables set up.
        """
        self.gmail_user = gmail_user
        self.gmail_pwd = gmail_pwd
        self.mail_to = mail_to
        self.subject = subject
        self.message = message
        self.files = files
        self.sent = False

        try:
            self.msg = self._construct_mail()
        except Exception:
            raise Exception('Creating message object failed.\n' +
                            traceback.format_exc())
        try:
            self._send_mail()
            self.sent = True
        except Exception:
            raise Exception('Sending email failed.\n' +
                            traceback.format_exc())

    def _construct_mail(self):
        """
        Creates a MIMEMultipart message with attachment (if needed).

        Internal function no need to call it explicitly.
        """

        msg = MIMEMultipart()
        msg['To'] = COMMASPACE.join(self.mail_to)
        msg['From'] = self.gmail_user
        msg['Date'] = formatdate(localtime=True)
        msg['Subject'] = self.subject
        msg.attach(MIMEText(self.message, 'html'))

        # add attachment
        if self.files is not None:
            msg = self._attach_files(msg)

        return msg

    def _send_mail(self):
        """
        Sends an email from a gmail account.

        Internal function no need to call it explicitly.
        """

        server = smtplib.SMTP("smtp.gmail.com", 587)
        server.ehlo()
        server.starttls()
        server.login(self.gmail_user, self.gmail_pwd)
        server.sendmail(self.gmail_user, self.mail_to, self.msg.as_string())
        server.close()

    def _attach_files(self, msg):
        """
        Attaches the files to the msg.

        Internal function no need to call it explicitly.
        """

        for f in self.files:
            part = MIMEBase('application', "octet-stream")
            part.set_payload(open(f, "rb").read())
            encoders.encode_base64(part)
            part.add_header('Content-Disposition', 'attachment; filename="{0}"'
                            .format(os.path.basename(f)))
            msg.attach(part)
        return msg

Comments (0)