LoginSignup
7
7

More than 5 years have passed since last update.

Python Gmail APIでCSV付きメール送信

Posted at

目次

1,内容
2,開発環境
3,事前準備
4,コード
5,終わりに

内容

自分で作っているツールでGmailAPIが必要になり、
検索しても微妙に再現出来ずハマったので、ここに記する。

開発環境

OS : Mac10.13.6
Python : 3.6.5

事前準備

1,credentials.jsonをダウンロードする。
参照URL : https://developers.google.com/gmail/api/quickstart/python
ページ内の ENABLE THE GMAIL APIをクリックし、credentials.jsonをダウンロードする。
2,コードを実行するディレクトリに上記credentials.jsonを置く。
3,pip install --upgrade google-api-python-client google-auth-httplib2 google-auth-oauthlibする

コード

ディレクトリ構造

$ tree .

.
├── Amazon.csv
├── gmail_auth.py
└── main_gmail.py

【内容】
Amazon.csv = ちとスクレイピングの練習で使ったCSV # 何のCSVでもOK
gmail_auth.py = 認証キー作成コード
main_gmail.py = メール送信コード

1,terminalでgmail_auth.pyを実行する

$ python gmail_auth.py

そうすると、token.jsonなるファイルが出来上がる。
今後はソイツを使うらしい。 細かいこたー知らん。

gmail_auth.pyの内容

gmail_auth.py
from googleapiclient.discovery import build
from httplib2 import Http
from oauth2client import file, client, tools

def create_Gmail_credential():
    # define app name whatever you want
    APPLICATION_NAME = "myGmailApi"
    """
    scope for sending
    refer to https://developers.google.com/gmail/api/auth/scopes
    """
    SCOPES = 'https://www.googleapis.com/auth/gmail.send'
    store = file.Storage('token.json')
    creds = store.get()
    if not creds or creds.invalid:
        flow = client.flow_from_clientsecrets('credentials.json', SCOPES)
        flow.user_agent = APPLICATION_NAME
        creds = tools.run_flow(flow, store)
    service = build('gmail', 'v1', http=creds.authorize(Http()))
    return service

if __name__ == "__main__":
    # create credentials
    create_Gmail_credential()

2,main_gmail.pyを実行する

$ python gmail_auth.py

そのままだとエラーになるぜよ。
ちと解説。

main_gmail.pyの内容

main_gmail.py
import base64
import apiclient
import traceback
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.mime.base import MIMEBase
from email import encoders
import os
from gmail_auth import create_Gmail_credential

def send_msg_with_file(sender, to, subject, message_text, file_name):
    """Create a message for an email.
    Args:
    sender: Email address of the sender.
    to: Email address of the receiver.
    subject: The subject of the email message.
    message_text: The text of the email message.
    file: The path to the file to be attached.
    Returns:
    An object containing a base64url encoded email object.
    """
    # initialize message object
    message = MIMEMultipart()
    # set each elementes needed
    message['to'] = to
    message['from'] = sender
    message['subject'] = subject
    msg = MIMEText(message_text)
    message.attach(msg)
    try:
        # defie file type
        msg = MIMEBase('text', 'comma-separated-values')
        # define file location and open it
        file_location = os.path.abspath(file_name)
        # make attachment
        attachment = open(file_location, "rb")
        # set attachment
        msg.set_payload((attachment).read())
        encoders.encode_base64(msg)
        msg.add_header(f'Content-Disposition', "attachment; filename={file_location}")
        # attach the file
        message.attach(msg)
    except:
        print("There is no file here")
    # encode bytes string
    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}

def send_message(to, subject, message_text, file_name):
    # "me" means that your email address authorized
    sender = "me"
    # create credentials
    service = create_Gmail_credential()
    try:
        result = service.users().messages().send(
            userId=sender,
            body=send_msg_with_file(sender, to, subject, message_text, file_name)
        ).execute()
        print("Message Id: {}".format(result["id"]))
    except apiclient.errors.HttpError:
        print("------start trace------")
        traceback.print_exc()
        print("------end trace------")

if __name__ == "__main__":
    # set email address you want to send
    to = "xxxxxx@gmail.com"
    # set subject
    subject = "Test sending csv using Gmail api"
    # set message
    message_text = "This is a Gmail API test"
    send_message(to, subject, message_text, file_name)

下記に送付先のメアドを入れるべし。
送付元は"me"で定義済み。変える必要はなさそう。

下の参考例はgmail.comになっているが、なんでもOK。

# set email address you want to send
to = "xxxxxx@gmail.com"

下記コードでは、CSVファイルがある場合は添付し、ファイルがない場合はメッセージのみ送付する。

main_gmail.pyの中身
try:
    # defie file type
    msg = MIMEBase('text', 'comma-separated-values')
    # define file location and open it
    file_location = os.path.abspath(file_name)
    # make attachment
    attachment = open(file_location, "rb")
    # set attachment
    msg.set_payload((attachment).read())
    encoders.encode_base64(msg)
    msg.add_header(f'Content-Disposition', "attachment; filename={file_location}")
    # attach the file
    message.attach(msg)
except:
    print("There is no file here")
# encode bytes string
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}

終わりに

ワテのGit : https://github.com/LightSign/gmail_api
参考にしたURL
Gmail API sample code : https://developers.google.com/gmail/api/quickstart/python
Send Email : https://developers.google.com/gmail/api/guides/sending
Python3 + google-api-python-clientで、Gmail APIを使ってメールを送信する :
http://thinkami.hatenablog.com/entry/2016/06/09/062528

7
7
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
7
7