LoginSignup
2
3

More than 3 years have passed since last update.

Gmail で添付ファイル付きのメールを送る (python3)

Last updated at Posted at 2019-01-03

次のプログラムを改造して、添付ファイル付きのメールを送るようにしました。
Gmail の oauth2 でメールの送信 (python3)

まず、credentials.json を取得します。

Gmail->API->Guides->Python Quickstart

get_credentials.py
#
#   get_credentials.py
#
#                   Jan/03/2019
# ------------------------------------------------------------------
import httplib2
import os
import sys

import oauth2client
import argparse
from oauth2client import file, client, tools
# ------------------------------------------------------------------
SCOPES = "https://www.googleapis.com/auth/gmail.send"
CLIENT_SECRET_FILE = "credentials.json"
APPLICATION_NAME = "MyGmailSender"

# ------------------------------------------------------------------
# [6-4]:
def get_credentials_proc(flags):
    script_dir =os.path.abspath(os.path.dirname(__file__)) 
    credential_dir = os.path.join(script_dir, ".credentials")

    if not os.path.exists(credential_dir):
        os.makedirs(credential_dir)
    credential_path = os.path.join(credential_dir,"my-gmail-sender.json")

    store = oauth2client.file.Storage(credential_path)
    credentials = store.get()
    if not credentials or credentials.invalid:
        flow = oauth2client.client.flow_from_clientsecrets(CLIENT_SECRET_FILE, SCOPES)
        flow.user_agent = APPLICATION_NAME
        credentials = oauth2client.tools.run_flow(flow,store,flags)
        print("Storing credentials to " + credential_path)
#
    return credentials
#
# ------------------------------------------------------------------
gmail_attachement.py
#
#   gmail_attachement.py
#
#                   Jan/03/2019
# ------------------------------------------------------------------
import httplib2
import os
import sys

import apiclient
from get_credentials import get_credentials_proc
# ------------------------------------------------------------------
import base64
from email.mime.multipart import MIMEMultipart
from email.utils import formatdate
from email.mime.base import MIMEBase
import traceback
from email.message import EmailMessage
import imghdr

# ------------------------------------------------------------------
# [6-8-4]:
def attach_image_proc(message,img_data,filename):
    try:
        message.add_attachment(img_data,maintype='image',
            subtype=imghdr.what(None,img_data),filename=filename)
    except Exception as ee:
        sys.stderr.write("*** error *** in message.add_attachment ***\n")
        sys.stderr.write(str(ee) + "\n")
#
    return message
# ------------------------------------------------------------------
# [6-8-6]:
def attach_application_proc(message,data_attach,filename,subtype):
    try:
        message.add_attachment(data_attach,maintype='application',
            subtype=subtype,filename=filename)
    except Exception as ee:
        sys.stderr.write("*** error *** in message.add_attachment ***\n")
        sys.stderr.write(str(ee) + "\n")
#
    return message
# ------------------------------------------------------------------
# [6-8]:
def create_message(mail_from,mail_to,subject,str_message,file_attach):
    message = EmailMessage()
    message.set_content(str_message)
#
    message["From"] = mail_from
    message["To"] = mail_to
    message["Subject"] = subject
    message["Date"] = formatdate(localtime=True)
#
    fp = open(file_attach,'rb')
    img_data = fp.read()
    fp.close()
#
    for suffix in [".pdf",".csv",".json",".xlsx",".zip"]:
        if (file_attach.endswith(suffix)):
            message = attach_application_proc \
                (message,img_data,file_attach,suffix)
#
    for suffix in [".jpg",".png"]:
        if (file_attach.endswith(suffix)):
            message = attach_image_proc \
                (message,img_data,file_attach)
#
    byte_msg = message.as_string().encode(encoding="UTF-8")
    byte_msg_b64encoded = base64.urlsafe_b64encode(byte_msg)
    str_msg_b64encoded = byte_msg_b64encoded.decode(encoding="UTF-8")

    return {"raw": str_msg_b64encoded}
#
# ------------------------------------------------------------------
# [6]:
def gmail_attachement_proc(mail_from,mail_to,subject,str_message,file_attach,flags):
    credentials = get_credentials_proc(flags)
    http = credentials.authorize(httplib2.Http())
    service = apiclient.discovery.build("gmail", "v1", http=http)
#
    try:
        result = service.users().messages().send(
            userId=mail_from,
            body=create_message(mail_from,mail_to,subject,str_message,file_attach)
        ).execute()

        print("Message Id: {}".format(result["id"]))

    except apiclient.errors.HttpError:
        print("------start trace------")
        traceback.print_exc()
        print("------end trace------")
#
# ------------------------------------------------------------------

mail_from は credentials.json を作成したユーザーにして下さい。
mail_to は送信先です。
file_attach は添付ファイルの名前です。

test_gmail.py
#! /usr/bin/python
#
#   test_gmail.py
#
#                   Jan/03/2019
# ------------------------------------------------------------------
import sys

import argparse
import oauth2client

from gmail_attachement import gmail_attachement_proc 

flags = argparse.ArgumentParser(
    parents=[oauth2client.tools.argparser]
).parse_args()

# ------------------------------------------------------------------
sys.stderr.write("*** 開始 ***\n")
#
mail_from = "example01@gmail.com"
mail_to = "user01@example.or.jp"
#
subject = "Gmail Api Test Jan/03/2019 PM 20:45"
str_message = ""
str_message += "こんにちは。\n"
str_message += "Jan/03/2019 PM 20:45\n"
#
file_attach = "federer.png"
file_attach = "in01.csv"
file_attach = "example01.pdf"
file_attach = "federer.jpg"
#
sys.stderr.write("file_attach = " + file_attach + "\n")
#
gmail_attachement_proc(mail_from,mail_to,subject,str_message,file_attach,flags)
#
sys.stderr.write("*** 終了 ***\n")
# ------------------------------------------------------------------

実行方法

./test_gmail.py

リモートのサーバーのコンソールで最初に実行する時は

./test_gmail.py --noauth_local_webserver

次のバージョンで確認しました。

$ python --version
Python 3.8.2
2
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
3