Gmail APIを使ってPythonでメール送信する
Pythonを用いてメール送信したかったのだが, 適当なメールアドレスがなかったため, 使い慣れているGmailを使用することにした.
検索すると, Googleアカウントのセキュリティを下げれば使用可能な方法はよく出てくるのだが, 2段階認証等を設定しているとセキュリティを下げることができないらしい.
また, セキュリティを下げること自体もいかがなものかと思ったため, Gmail APIを利用する方法を調べた.
基本的には, メイン参照元 (Gmail APIとPythonを使ってメール送信を自動化する方法 – Valmore) のほぼそのままである.
ただし, 本方法だと, Googleによるアプリ検証まではできていないため, 送信できたメールに注意喚起のメッセージがでてしまうことが難点. 要改善, もしくはアプリ検証を実施する必要がある.
目次
Gmail APIを使ってPythonでメール送信する目次GitRequirementInstall Gmail LibrariesTested EnvironmentUsageCodesディレクトリ構成実行前実行後main.pysettings.jsoncredential.json手順Google Cloud PlatformにアクセスGmail APIを有効にするGmail APIの認証Gmail APIアプリを公開Gmail APIトークンの作成とメール送信トークンを利用してメール送信動画参照メインその他
Requirement
- OS: Mac, Windows 
- python3 - import pickle
- import os.path
- from googleapiclient.discovery import build
- from google_auth_oauthlib.flow import InstalledAppFlow
- from google.auth.transport.requests import Request
- import base64
- from email.mime.text import MIMEText
- from apiclient import errors
- import json
 
Install Gmail Libraries
xxxxxxxxxxpip install --upgrade google-api-python-client google-auth-httplib2 google-auth-oauthlib
Tested Environment
- Mac - macOS Big Sur 11.5.2 on M1 MacBook Air 2020
 
Usage
python3 main.pyorpython main.py
Codes
ディレクトリ構成
実行前
.├── credentials.json├── main.py└── settings.json
実行後
.├── credentials.json (下記のtoken.pickleがあれば今後は不要)├── main.py├── settings.json└── token.pickle
main.py
import pickleimport os.pathfrom googleapiclient.discovery import buildfrom google_auth_oauthlib.flow import InstalledAppFlowfrom google.auth.transport.requests import Requestimport base64from email.mime.text import MIMETextfrom apiclient import errorsimport json
def getSettings(_jsonPath):    _json = json.loads(open(_jsonPath, 'r').read())    return _json
def createMessage(sender, to, subject, message_text):    message = MIMEText(message_text)    message['to'] = to    message['from'] = sender    message['subject'] = subject    encode_message = base64.urlsafe_b64encode(message.as_bytes())    return {'raw': encode_message.decode()}
def sendMessage(service, user_id, message):    try:        message = (service.users().messages().send(userId=user_id, body=message).execute())        print('Message Id: %s' % message['id'])        return message    except errors.HttpError as error:        print('An error occurred: %s' % error)
def getAccessToken(_scopes, _token, _credentialJson):    creds = None    if os.path.exists(_token):        with open(_token, 'rb') as token:            creds = pickle.load(token)    if not creds or not creds.valid:        if creds and creds.expired and creds.refresh_token:            creds.refresh(Request())        else:            flow = InstalledAppFlow.from_client_secrets_file(_credentialJson, _scopes)            creds = flow.run_local_server()        with open(_token, 'wb') as token:            pickle.dump(creds, token)    _service = build('gmail', 'v1', credentials=creds)    return _service
def mainProcess():    json = getSettings("settings.json")    service = getAccessToken(json["scopes"], json["gglToken"], json["gglJson"])    message = createMessage(json["sender"], json["to"], json["subject"], json["message"])    sendMessage(service, 'me', message)
# ===================================================if __name__ == '__main__':    mainProcess()
settings.json
メールの設定, 行き先, 本文など
{    "scopes": ["https://www.googleapis.com/auth/gmail.send"],    "gglToken": "token.pickle",    "gglJson": "credentials.json",    "sender": "1234567890@gmail.com",    "to": "1234567890@gmail.com",    "subject": "message ttile",    "message": "mail text test.\nHello mail test!!"}
credential.json
トークン作成前の認証情報
{    "installed": {        "client_id": "12345678902345678901234567890234567890",        "project_id": "12345678901234567890",        "auth_uri": "12345678902345678901234567890234567890",        "token_uri": "12345678902345678901234567890234567890",        "auth_provider_x509_cert_url": "12345678902345678901234567890234567890",        "client_secret": "123456789012345678901234",        "redirect_uris": [            "1234567890123456",            "1234567890123456"        ]    }}
手順
Gmail APIを有効にする
- Gmail APIをタイプして選択

- 有効にするを押す

Gmail APIの認証
- 認証情報を作成を押す

- Gmail APIを選択して, 次へ

- アプリ名をタイプし,
- ユーザーサポートメールに自分のメールアドレスをタイプ

- デベロッパーの連絡先情報のメールアドレスに自分のメールアドレスをタイプ

- 保存して次へ

- デスクトップアプリを選択して作成を押す

- 認証情報の入ったjsonをダウンロード

Gmail APIアプリを公開
- DLした認証情報jsonをコピー

- main.pyと同じディレクトリにいれて, credential.jsonにファイル名を変更

- OAuth同意画面を押す

- アプリを公開を押す

- 確認を押す

- これでGmail APIの今回のアプリが公開され利用可能になった

Gmail APIトークンの作成とメール送信
- python3 main.pyでpythonを実行

- 自分のアカウントを選択

- 詳細を押す

- GmailSendTest (安全ではないページ) に移動をクリック

- チェックを入れる

- Continueを押す

- トークンが作成され, メールも送信された

- メール確認

- セキュリティ通知

- メールが届いている

- トークンファイル (token.pickle) ができている. 今後はこのトークンを使う

トークンを利用してメール送信
- 試しにもう一回main.pyを実行

- 認証を求められることなく, メールを送ることができた

以上.
動画
参照
その他
- メール送信 | Python-izm
- Pythonでメール送信 | Python学習講座
- 面倒なメール配信の作業をPythonで自動化しよう|PythonでGmailを自動送信【Pythonで業務自動化シリーズ#07】 | キノコード
- Gmail APIとPythonを使ってメール送信を自動化する方法 – Valmore
- OAuth API verification FAQs - Google Cloud Platform Console ヘルプ
- Google API - Google認証エラー 403: access_deniedを解決したい|teratail
- Unverified apps - Google Cloud Platform Console ヘルプ
- 【Python】JSONフォーマットの使い方(jsonモジュール) | Hbk project









