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

#目次
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の内容
```python: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の内容
```python: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ファイルがある場合は添付し、ファイルがない場合はメッセージのみ送付する。

```python: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