Send files with Gmail using a python script

2
Jan 2019
By: Theo van der Sluijs

reading time: 5 min.

Category: Coding
Sending an email with this Python 3 script is very easy, but you can also send attachments with Python and Gmail.

Now as I do not like doing stuff twice I wanted to have a script that would send files from a folder as separate emails.

And that is exactly what this python script does. It takes a folder and for every file a mail with that file is created and send to a email address.

So I have a subscription on this online Receipt scanner service where I can scan receipts with my mobile camera and it will get processed by this service.

Now as this service is very good I also receive a lot of invoices and receipts by mail or I have to download them manually. As the service has a send to email option, sending hundreds of invoices manually to this email address is not really an option for me….  it doing something very simple more then twice! And if I have to do it twice I AUOTMATE it!

Gmail app Password

Now if you are like me and want to use the Gmail service for this and you have 2-way authentication (which you REALLY shoud have!) you cannot simple start using Gmail to send these emails as Gmail wants to authenticate in a 2-way!

So when you have signed up for 2-Step Verification, Gmaikl normally sends you verification codes. However, these codes do not work with some apps and devices, like Outlook or my Python script. Instead, you’ll need to authorize the app or device the first time you use it to sign in to your Google Account by generating and entering an App password.

Creating a Google App Password is very easy.

  1. Go to your Google Account.
  2. On the left navigation panel, click Security.
  3. On the Signing in to Google panel, click App passwords.  Note: If you can’t get to the page, 2-Step Verification is:
  • Not set up for your account
  • Set up for security keys only
  1. At the bottom, click Select app and choose the app you’re using.
  2. Click Select device and choose the device you’re using.
  3. Click Generate.
  4. Copy the the 16 character code in the yellow bar you will need it for this script.
  5. Click Done.

Once you are finished, you won’t see that App password code again. However, you will see a list of apps and devices you’ve created App passwords for.

Mail file folders

To use this script save it somewhere on your pc or Mac, name it “send_files_by_gmail.py” and create a folder named “mail_files” and within this folder, and within this new “mail_files” folder create a folder named “done” and “new”.

Your folder will look like this

  • send_files_by_gmail.py
  • mail_files
  • done
  • new

You can place all the attachments within the “new” folder.

When the script is ready all attachments send will be in the “done” folder.

If the script crashes, you can rerun the script as it will start where it stopped as it only puts files in the “done” folder when the mail is send out.

How the python script works

Well, very simple! You do not need to install anything. You have to use python 3 (it will not work with python 2)

You only have to fill in 3 items in the python script

your gmail email address your gmail app password and the email address your want to send it to!

if __name__ == '__main__':
    
    from_addr = "some@gmail.com"         # your gmail account email address
    pass_wd = "yourpasswors"              # your pwd (see discription above)
    to_addr = "to@emailaddress.com"     # where the attachment should go to
    
    m = MailFiles(from_addr, pass_wd, to_addr)

That’s it! Have Fun!

"""
author: Pure Python
url: https://www.purepython.org
copyright: CC BY-NC 4.0
creation date: 02-01-2019

Small script to send mails with attachment from folder with Gmail

Uses nothing but python 3 modules.

Create a folder named mail_files and within this folder done and new.
You can place all the attachments within the new folder.
When the script is ready all attachments send will be in the Done folder.
If the script crashes, you can rerun the script as it will start
where it stopped.

You need an gmail app password for this to work
https://support.google.com/accounts/answer/185833?hl=en
"""
import os
import time
import smtplib

from email.mime.base import MIMEBase
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email import encoders


class MailFiles:
    def __init__(self, from_addr=None, pass_wd=None, to_addr=None):
        """
        init function for this to work
        :param from_addr: your gmail account email address
        :param pass_wd: your gmail app pwd (see discription above)
        :param to_addr: here the attachment should go to
        """
        self.from_addr = from_addr
        self.pass_wd = pass_wd
        self.to_addr = to_addr

        dir_path = os.path.dirname(os.path.realpath(__file__))
        self.start_dir = os.path.join(dir_path, "mail_files/new")
        self.done_dir = os.path.join(dir_path, "mail_files/done")

        self.process_files()

    def process_files(self):
        """
        This will loop thru the files in the New folder and calls the
        mail_file function. It has a sleep function so Gmail will not
        be flooded.
        """
        i = 1
        for filename in os.listdir(self.start_dir):
            file = os.path.join(self.start_dir, filename)
            if self.mail_file(file, filename):  # Mailing retuns True or False
                backup_file = os.path.join(self.done_dir, filename)
                os.rename(file, backup_file)    # move done file to done folder
            print("Document {} send!".format(filename))
            i += 1
            time.sleep(5)   # Sleep for 5 seconds to not overrun Gmail

    def mail_file(self, file=None, filename=None):
        """
        This function will mail the file to the email address as an attachment
        :param file: path with filename
        :param filename: filename online
        :return: true or false
        """
        try:
            msg = MIMEMultipart()

            msg['From'] = self.from_addr
            msg['To'] = self.to_addr
            msg['Subject'] = "Sending file {}".format(filename)

            body = "Sending File {} to you".format(filename)
            msg.attach(MIMEText(body, 'plain'))

            attachment = open(file, "rb")

            part = MIMEBase('application', 'octet-stream')
            part.set_payload(attachment.read())
            encoders.encode_base64(part)
            part.add_header('Content-Disposition', "attachment; filename= %s" % filename)

            msg.attach(part)

            server = smtplib.SMTP('smtp.gmail.com', 587)
            server.starttls()
            server.login(self.from_addr, self.pass_wd)
            text = msg.as_string()
            server.sendmail(self.from_addr, self.to_addr, text)
            server.quit()

            return True
        except smtplib.SMTPException as e:
            print(e)
            return False
        except:
            return False


if __name__ == '__main__':
    
    from_addr = "some@gmail.com"         # your gmail account email address
    pass_wd = "yourpasswors"              # your pwd (see discription above)
    to_addr = "to@emailaddress.com"     # where the attachment should go to
    m = MailFiles(from_addr, pass_wd, to_addr)

0 Comments

Submit a Comment

Your email address will not be published. Required fields are marked *