Senden und empfangen Sie Google Mail über die Google Mail-API mit Python

Einführung

Wie Sie wissen, verfügt Google Mail über eine Google Mail-API, mit der Sie die einzigartigen Funktionen von Google Mail wie die Suchfunktion nutzen können, ohne SMTP oder POP3 zu verwenden. Dieser Artikel enthält schrittweise Anweisungen zur Verwendung von Python, um die Google Mail-API zu aktivieren, Skripts zu erstellen und auszuführen.

Vor der Verwendung der Google Mail-API ist die Vorbereitung ziemlich schwierig, z. B. das Erstellen eines Projekts, das Aktivieren der API, das Festlegen des Bereichs und das Erstellen von Authentifizierungsinformationen. Daher habe ich es als Memorandum geschrieben.

Vorbereitung vor Gebrauch

Erstellen Sie ein Projekt, das die Google-API verwendet

Öffnen Sie die Google Cloud Platform-Konsole (https://console.cloud.google.com/) im Browser, der Google Mail für Ihr Google Mail-Konto öffnet.

Der folgende Bildschirm wird angezeigt. Stimmen Sie den Allgemeinen Geschäftsbedingungen zu und klicken Sie auf "Zustimmen und ausführen".

A00.jpg

Wählen Sie "Neues Projekt" unter "Projekt auswählen". A01.jpg

Legen Sie den Projektnamen fest und klicken Sie auf "Erstellen". A02.jpg

Wenn Sie es erstellen können, wird der folgende Bildschirm angezeigt A03.jpg

Aktivieren Sie die Google Mail-API

Klicken Sie auf "Bibliothek" A04.jpg

Suchen Sie unter "APIs und Dienste suchen" nach "Google Mail-API". A05.jpg

Klicken Sie auf die angezeigte "Google Mail-API". A06.jpg

Klicken Sie auf "Aktivieren" A07.jpg

Erstellen Sie einen OAuth-Zustimmungsbildschirm

Klicken Sie unter "API und Dienste" auf "OAuth-Zustimmungsbildschirm". A08.jpg

Wählen Sie "Extern" und klicken Sie auf "Erstellen". A09.jpg

Legen Sie einen geeigneten Namen für "Anwendungsname" fest und klicken Sie auf "Bereich hinzufügen". A10.jpg

Wählen Sie einen Bereich wie unten gezeigt aus und klicken Sie auf "Hinzufügen". A11.jpg

Klicken Sie auf "Speichern" A12.jpg

Erstellen Sie Anmeldeinformationen

Wählen Sie "Anmeldeinformationen", klicken Sie auf "Anmeldeinformationen erstellen" und klicken Sie im angezeigten Menü auf "Mit Assistent auswählen". A13.jpg

Stellen Sie im Bildschirm "Anmeldeinformationen zum Projekt hinzufügen" wie unten gezeigt ein und klicken Sie auf "Erforderliche Anmeldeinformationen". A14.jpg

Klicken Sie auf "OAuth-Client-ID erstellen". A15.jpg

Laden Sie die Anmeldeinformationen (client_id.json) herunter und klicken Sie auf "Fertig stellen". A16.jpg

Wenn Sie auf die Schaltfläche Fertig stellen klicken, wechselt der Bildschirm zu dem unten gezeigten. A17.jpg

Die heruntergeladene Anmeldeinformationsdatei client_id.json wird später im Python-Skript verwendet.

Ergänzung: Informationen zur Authentifizierung

Sie können in Ihren Anmeldeinformationen einen API-Schlüssel, eine OAuth2.0-Client-ID oder einen Dienstkontoschlüssel erstellen. Beim Umgang mit Benutzerdaten scheint es üblich zu sein, eine OAuth2.0-Client-ID zu verwenden. Auf der Seite Übersicht über die Authentifizierung von Google Cloud-Dokumenten (https://cloud.google.com/docs/authentication?hl=ja) werden die Verwendungszwecke der einzelnen Authentifizierungsmethoden beschrieben.

Das Ablaufdatum des Aktualisierungstokens für Anmeldeinformationen wird unten beschrieben. Sobald die Authentifizierung erfolgt und das Aktualisierungstoken ausgestellt wurde, scheint es nicht abzulaufen, es sei denn, es bleibt 6 Monate oder es werden 50 oder mehr Token ausgegeben. Es scheint, dass Automatisierungsmechanismen wie RPA ebenfalls akzeptabel sind. https://developers.google.com/identity/protocols/OAuth2#expiration

You must write your code to anticipate the possibility that a granted refresh token might no longer work. A refresh token might stop working for one of these reasons:

* The user has revoked your app's access.
* The refresh token has not been used for six months.
* The user changed passwords and the refresh token contains Gmail scopes.
* The user account has exceeded a maximum number of granted (live) refresh tokens.
* There is currently a limit of 50 refresh tokens per user account per client. If the limit is reached, creating a new refresh token automatically invalidates the oldest refresh token without warning. This limit does not apply to service accounts.

Python-Skriptvorbereitung

Jetzt, da wir fertig sind, können wir ein Python-Skript ausführen.

Vorbereiten der Python-Umgebung

(Ich denke, viele Menschen haben bereits in diesem Teil gelebt)

Python-Installation

Installieren Sie gemäß hier. Bitte installieren Sie 3.7.x.

Installation von pipenv

Befolgen Sie die Schritte hier (http://pipenv-ja.readthedocs.io/ja/translate-ja/install.html#installing-pipenv), um die Installation durchzuführen.

Erstellen eines Python-Skripts

Bereiten Sie ein geeignetes Verzeichnis vor und bereiten Sie ein Python-Skript vor. Speichern Sie die im vorherigen Schritt gespeicherte Datei client_id.json im selben Verzeichnis. Zusammengefügt Gmail API-Beispiele: Sweat_drops:

Beispielcode finden Sie in der Google Mail-API-Referenz. Es ist einfach zu bedienen, wenn Sie hierher kommen!

gmail_credential.py



import os
import pickle
from google.auth.transport.requests import Request
from google_auth_oauthlib.flow import InstalledAppFlow


#Legen Sie den Bereich für die Google Mail-API fest
SCOPES = [
    "https://www.googleapis.com/auth/gmail.compose",
    "https://www.googleapis.com/auth/gmail.readonly",
    "https://www.googleapis.com/auth/gmail.labels",
    "https://www.googleapis.com/auth/gmail.modify",
]


def get_credential():
    """
Zugriffstoken erhalten

Speichern Sie das Token im Pickle-Format im aktuellen Verzeichnis, damit es wiederverwendet werden kann. (Entschuldigung für das Verschiedenes ...)
    """
    creds = None
    if os.path.exists("token.pickle"):
        with open("token.pickle", "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("client_id.json", SCOPES)
            # creds = flow.run_local_server()
            creds = flow.run_console()
        with open("token.pickle", "wb") as token:
            pickle.dump(creds, token)
    return creds

listmail.py



"""
list GMail Inbox.

Usage:
  listmail.py <query> <tag> <count>
  listmail.py -h | --help
  listmail.py --version

Options:
  -h --help     Show this screen.
  --version     Show version.
"""
import pickle
import base64
import json
import io
import csv
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 logging
from docopt import docopt
from gmail_credential import get_credential

logger = logging.getLogger(__name__)


def list_labels(service, user_id):
    """
Holen Sie sich eine Liste der Etiketten
    """
    labels = []
    response = service.users().labels().list(userId=user_id).execute()
    return response["labels"]


def decode_base64url_data(data):
    """
Decodieren von base64url
    """
    decoded_bytes = base64.urlsafe_b64decode(data)
    decoded_message = decoded_bytes.decode("UTF-8")
    return decoded_message


def list_message(service, user_id, query, label_ids=[], count=3):
    """
Holen Sie sich eine Liste von E-Mails

    Parameters
    ----------
    service : googleapiclient.discovery.Resource
Ressourcen für die Kommunikation mit Google Mail
    user_id : str
Benutzeridentifikation
    query : str
E-Mail-Abfragezeichenfolge. ist:ungelesen etc.
    label_ids : list
Liste der IDs, die das zu durchsuchende Etikett angeben
    count : str
Maximale Anzahl der zurückzugebenden E-Mail-Informationen

    Returns
    ----------
    messages : list
        id, body, subject,Liste der Wörterbuchdaten mit Schlüsseln wie von
    """
    messages = []
    try:
        message_ids = (
            service.users()
            .messages()
            .list(userId=user_id, maxResults=count, q=query, labelIds=label_ids)
            .execute()
        )

        if message_ids["resultSizeEstimate"] == 0:
            logger.warning("no result data!")
            return []

        #Überprüfen Sie den Inhalt der Nachricht anhand der Nachrichten-ID
        for message_id in message_ids["messages"]:
            message_detail = (
                service.users()
                .messages()
                .get(userId="me", id=message_id["id"])
                .execute()
            )
            message = {}
            message["id"] = message_id["id"]
            message["body"] = decode_base64url_data(
                message_detail["payload"]["body"]["data"]
            )
            # payload.headers[name: "Subject"]
            message["subject"] = [
                header["value"]
                for header in message_detail["payload"]["headers"]
                if header["name"] == "Subject"
            ][0]
            # payload.headers[name: "From"]
            message["from"] = [
                header["value"]
                for header in message_detail["payload"]["headers"]
                if header["name"] == "From"
            ][0]
            logger.info(message_detail["snippet"])
            messages.append(message)
        return messages

    except errors.HttpError as error:
        print("An error occurred: %s" % error)


def remove_labels(service, user_id, messages, remove_labels):
    """
Löschen Sie das Etikett. Wird verwendet, um als gelesen zu markieren(is:Wenn Sie das ungelesene Etikett entfernen, wird es gelesen.
    """
    message_ids = [message["id"] for message in messages]
    labels_mod = {
        "ids": message_ids,
        "removeLabelIds": remove_labels,
        "addLabelIds": [],
    }
    # import pdb;pdb.set_trace()
    try:
        message_ids = (
            service.users()
            .messages()
            .batchModify(userId=user_id, body=labels_mod)
            .execute()
        )
    except errors.HttpError as error:
        print("An error occurred: %s" % error)


#Hauptverarbeitung
def main(query="is:unread", tag="daily_report", count=3):
    creds = get_credential()
    service = build("gmail", "v1", credentials=creds, cache_discovery=False)
    #Etikettenliste
    labels = list_labels(service, "me")
    target_label_ids = [label["id"] for label in labels if label["name"] == tag]
    #Mail-Liste[{'body': 'xxx', 'subject': 'xxx', 'from': 'xxx'},]
    messages = list_message(service, "me", query, target_label_ids, count=count)
    # unread label
    unread_label_ids = [label["id"] for label in labels if label["name"] == "UNREAD"]
    # remove labels form messages
    remove_labels(service, "me", messages, remove_labels=unread_label_ids)
    logger.info(json.dumps(messages, ensure_ascii=False))
    if messages:
        return json.dumps(messages, ensure_ascii=False)
    else:
        return None


#Programmausführungsteil
if __name__ == "__main__":
    arguments = docopt(__doc__, version="0.1")
    query = arguments["<query>"]
    tag = arguments["<tag>"]
    count = arguments["<count>"]
    logging.basicConfig(level=logging.DEBUG)

    messages_ = main(query=query, tag=tag, count=count)
    print(messages_)

Das Sendeskript sieht folgendermaßen aus.

sendmail.py


"""
Send E-Mail with GMail.

Usage:
  sendmail.py <sender> <to> <subject> <message_text_file_path>  [--attach_file_path=<file_path>] [--cc=<cc>]
  sendmail.py -h | --help
  sendmail.py --version

Options:
  -h --help     Show this screen.
  --version     Show version. 
  --attach_file_path=<file_path>     Path of file attached to message.
  --cc=<cc>     cc email address list(separated by ','). Default None.
"""
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.base import MIMEBase
from email.mime.text import MIMEText
from email.mime.image import MIMEImage
from email.mime.audio import MIMEAudio
from pathlib import Path

from email.mime.multipart import MIMEMultipart
import mimetypes
from apiclient import errors
from gmail_credential import get_credential
from docopt import docopt
import logging

logger = logging.getLogger(__name__)


def create_message(sender, to, subject, message_text, cc=None):
    """
Base64 codiert MIMEText
    """
    enc = "utf-8"
    message = MIMEText(message_text.encode(enc), _charset=enc)
    message["to"] = to
    message["from"] = sender
    message["subject"] = subject
    if cc:
        message["Cc"] = cc
    encode_message = base64.urlsafe_b64encode(message.as_bytes())
    return {"raw": encode_message.decode()}


def create_message_with_attachment(
    sender, to, subject, message_text, file_path, cc=None
):
    """
Base64 codiert MIMEText mit Anhängen
    """
    message = MIMEMultipart()
    message["to"] = to
    message["from"] = sender
    message["subject"] = subject
    if cc:
        message["Cc"] = cc
    # attach message text
    enc = "utf-8"
    msg = MIMEText(message_text.encode(enc), _charset=enc)
    message.attach(msg)

    content_type, encoding = mimetypes.guess_type(file_path)

    if content_type is None or encoding is not None:
        content_type = "application/octet-stream"
    main_type, sub_type = content_type.split("/", 1)
    if main_type == "text":
        with open(file_path, "rb") as fp:
            msg = MIMEText(fp.read(), _subtype=sub_type)
    elif main_type == "image":
        with open(file_path, "rb") as fp:
            msg = MIMEImage(fp.read(), _subtype=sub_type)
    elif main_type == "audio":
        with open(file_path, "rb") as fp:
            msg = MIMEAudio(fp.read(), _subtype=sub_type)
    else:
        with open(file_path, "rb") as fp:
            msg = MIMEBase(main_type, sub_type)
            msg.set_payload(fp.read())
    p = Path(file_path)
    msg.add_header("Content-Disposition", "attachment", filename=p.name)
    message.attach(msg)

    encode_message = base64.urlsafe_b64encode(message.as_bytes())
    return {"raw": encode_message.decode()}


def send_message(service, user_id, message):
    """
eine E-Mail senden

    Parameters
    ----------
    service : googleapiclient.discovery.Resource
Ressourcen für die Kommunikation mit Google Mail
    user_id : str
Benutzeridentifikation
    message : dict
        "raw"Schlüssel,Ein Diktat mit einem base64-codierten MIME-Objekt als Wert

    Returns
    ----------
Keiner
    """
    try:
        sent_message = (
            service.users().messages().send(userId=user_id, body=message).execute()
        )
        logger.info("Message Id: %s" % sent_message["id"])
        return None
    except errors.HttpError as error:
        logger.info("An error occurred: %s" % error)
        raise error


#Hauptverarbeitung
def main(sender, to, subject, message_text, attach_file_path, cc=None):
    #Erhalten von Zugangstoken und Gebäudetechnik
    creds = get_credential()
    service = build("gmail", "v1", credentials=creds, cache_discovery=False)
    if attach_file_path:
        #E-Mail-Text erstellen
        message = create_message_with_attachment(
            sender, to, subject, message_text, attach_file_path, cc=cc
        )
    else:
        message = create_message(
            sender, to, subject, message_text, cc=cc
        )
    #E-Mail senden
    send_message(service, "me", message)


#Programmausführungsteil
if __name__ == "__main__":
    arguments = docopt(__doc__, version="0.1")
    sender = arguments["<sender>"]
    to = arguments["<to>"]
    cc = arguments["--cc"]
    subject = arguments["<subject>"]
    message_text_file_path = arguments["<message_text_file_path>"]
    attach_file_path = arguments["--attach_file_path"]

    logging.basicConfig(level=logging.DEBUG)

    with open(message_text_file_path, "r", encoding="utf-8") as fp:
        message_text = fp.read()

    main(
        sender=sender,
        to=to,
        subject=subject,
        message_text=message_text,
        attach_file_path=attach_file_path,
        cc=cc,
    )

Vorbereiten der Ausführung eines Python-Skripts

Wechseln Sie in das Verzeichnis, in dem Sie das Python-Skript erstellt haben, und installieren Sie die erforderlichen Module.

% pipenv install google-api-python-client oauth2client google-auth-httplib2 google-auth-oauthlib docopt

Führen Sie das Python-Skript aus

% pipenv run python listmail.py is:ungelesen Fordern Sie ein Angebot an 10

Wenn Sie beispielsweise ausführen, wird die URL des OAuth-Authentifizierungsbildschirms bei der ersten Ausführung auf dem Bildschirm von cmd.exe angezeigt. Öffnen Sie sie daher im Browser und genehmigen Sie sie. Die URL des OAuth-Authentifizierungsbildschirms wird ab dem zweiten Mal nicht mehr angezeigt.

% pipenv run python listmail.py is:ungelesen Fordern Sie ein Angebot an 10
Please visit this URL to authorize this application: https://accounts.google.com/o/oauth2/auth?response_type=code&client_id=AAAAAAAAAAAAAA
Enter the authorization code:

Wenn Sie die auf der obigen Konsole angezeigte URL öffnen, wird der folgende Bildschirm angezeigt. A18.jpg

Klicken Sie auf "Details" und dann auf den angezeigten Link "Gehe zu XX (unsichere Seite)". A19.jpg

Der Autorisierungsdialog wird mehrmals angezeigt, lassen Sie also jeden zu. A20.jpg

Am Ende wird ein Bestätigungsbildschirm angezeigt. Lassen Sie es also zu. A21.jpg

Kopieren Sie den Code vom folgenden Bildschirm und fügen Sie ihn nach `ein. Geben Sie den Autorisierungscode ein:`, um das Skript auszuführen. A22.jpg

schließlich

Die Google Mail-API ist interessant, da Sie die leistungsstarken Filter, Beschriftungsfunktionen und Abfragen von Google Mail unverändert verwenden können.

Recommended Posts

Senden und empfangen Sie Google Mail über die Google Mail-API mit Python
Senden Sie mit Python mit Google Mail
So senden Sie automatisch E-Mails mit Anhängen mithilfe der Google Mail-API in Python
[Python] API zum Senden von Google Mail erstellen
Senden Sie E-Mails über Google Mail mit Python 3.4.3.
Versuchen Sie es mit der Wunderlist-API in Python
So erhalten Sie mithilfe der Mastodon-API Follower und Follower von Python
Tweet mit der Twitter-API in Python
Senden und Empfangen von Bilddaten als JSON in Python über das Netzwerk
Senden und Empfangen von Binärdaten über serielle Kommunikation mit Python3 (auf Mac)
Versuchen Sie es mit der BitFlyer Ligntning API in Python
Senden Sie Google Mail am Ende des Vorgangs [Python]
Holen Sie sich den Betreff und den Text von Google Mail mit der Python- und Google Mail-API
Versuchen Sie, die ChatWork-API und die Qiita-API in Python zu verwenden
Versuchen Sie, die DropBox Core-API mit Python zu verwenden
Senden Sie Google Mail in Python
Erhalten Sie das Formular in Python und führen Sie verschiedene Aktionen aus
Grundeinstellungen bei Verwendung der foursquare-API mit Python
PHP- und Python-Beispiele, die die ChatWork-API treffen
Sprachtranskriptionsverfahren mit Python und Google Cloud Speech API
Verwenden Sie die Such-API der National Parliament Library in Python
Versuchen Sie es mit der Twitter-API
Versuchen Sie es mit der Twitter-API
Versuchen Sie es mit der PeeringDB 2.0-API
Senden und Empfangen von Kolbenbildern
Rufen Sie die API mit python3 auf.
Versuchen Sie, mit Python schnell und einfach auf die Twitter-API zuzugreifen
Prognostizieren Sie das Geschlecht anhand des Namens mithilfe der Gender-API und von Pykakasi in Python
[Python] Ich habe versucht, Daten mit der API von Wikipedia zu sammeln
Holen Sie sich das Wetter mit API und lassen Sie Raspberry Pi sprechen!
Ich habe Chatbot mit LINE Messaging API und Python erstellt
Aggregieren und analysieren Sie Produktpreise mit der Rakuten Product Search API [Python]
Senden und Empfangen von Daten mit MQTT über die Watson IoT Platform
[aws] Senden und Empfangen von SQL-Nachrichten
Die Geschichte von Python und die Geschichte von NaN
Abrufen der arXiv-API in Python
Datenerfassung mit Python Googlemap API
Klicken Sie in Python auf die Sesami-API
[Python] Klicken Sie auf die Google Übersetzungs-API
[Version September 2020] Erläutert das Verfahren zur Verwendung der Google Mail-API mit Python
[Python3] Google übersetzt Google Übersetzung ohne Verwendung von API
Senden Sie Nachrichten und Bilder mit LineNotify
Versuchen Sie es mit der Pleasant-API (Python / FastAPI).
Zusammenarbeit zwischen Python-Modul und API
Klicken Sie mit Python auf die Etherpad-Lite-API
Sammeln Sie Produktinformationen und Prozessdaten mit der Rakuten-Produktsuch-API [Python].
Erstellen Sie Google Mail in Python ohne Verwendung der API
Klicken Sie auf die Web-API in Python
Clustering und Visualisierung mit Python und CytoScape
Verwenden Sie die Flickr-API von Python
Rufen Sie den Wert des Dropdown-Menüs mit Python und Selen ab und legen Sie ihn fest
[Python] Sprechen mit OpenJTalk und Talk API (bis zur Sprachausgabe)
Extrahieren Sie die Targz-Datei mit Python
Versuchen Sie es mit der Aktions-API von Python argparse
Versuchen Sie es mit dem Python Cmd-Modul
Führen Sie Ansible über Python mithilfe der API aus
Greifen Sie mit Python auf die Twitter-API zu
[Python] Ich habe eine REST-API mit AWS API Gateway und Lambda geschrieben.