it-swarm.com.de

Wie versende ich HTML-formatierte E-Mails über die Google Mail-API für Python?

Verwenden des Beispielcodes aus der GMail-API Beispiel: Mail senden und nachdem Sie die Regeln für die Authentifizierung befolgt haben, ist es einfach genug, eine programmgesteuert generierte E-Mail über ein Google Mail-Konto zu senden. Aus dem Beispiel ist nicht ersichtlich, wie diese E-Mail im HTML-Format formatiert wird.


Die Frage

Wie erhalte ich HTML-Formatierungen in meinen Google Mail-API-Sende-Nachrichten mit Python?

Ich habe das...

message_body = "Hello!\nYou've just received a test message!\n\nSincerely,\n-Test Message Generator\n"

und ich möchte, dass es so ist ...

Hello!
You've just received a test message!

Sincerely,
-Test Message Generator

Beispiel Quellcode aus GMail-API

Unten finden Sie eine leicht geänderte Version des Beispiels, die jedoch noch funktioniert:

import argparse
import base64
from pprint import pformat
from pprint import pprint
import httplib2
import os
from email.MIMEMultipart import MIMEMultipart
from email.MIMEText import MIMEText

from apiclient import discovery
from oauth2client import client
from oauth2client import tools
from oauth2client.file import Storage


SCOPES = 'https://mail.google.com/'
CLIENT_SECRET_FILE = 'client_secret.json'
APPLICATION_NAME = 'Test EMail App'


def get_credentials():
    """Gets valid user credentials from storage.

    If nothing has been stored, or if the stored credentials are invalid,
    the OAuth2 flow is completed to obtain the new credentials.

    Returns:
        Credentials, the obtained credential.
    """

    home_dir = os.path.expanduser('~')
    credential_dir = os.path.join(home_dir, '.credentials')
    if not os.path.exists(credential_dir):
        os.makedirs(credential_dir)
    credential_path = os.path.join(credential_dir,
                                   'gmail-python-quickstart.json')

    store = Storage(credential_path)
    credentials = store.get()
    if not credentials or credentials.invalid:
        flow = client.flow_from_clientsecrets(CLIENT_SECRET_FILE, SCOPES)
        flow.user_agent = APPLICATION_NAME
        if flags:
            credentials = tools.run_flow(flow, store, flags)
        else: # Needed only for compatibility with Python 2.6
            credentials = tools.run(flow, store)
        print('Storing credentials to ' + credential_path)
    return credentials

def create_message(sender, to, cc, subject, message_text):
    """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.

    Returns:
    An object containing a base64url encoded email object.
    """
    print(sender + ', ' + to + ', ' + subject + ', ' + message_text)
    message = MIMEText(message_text)
    message['to'] = to
    message['from'] = sender
    message['subject'] = subject
    message['cc'] = cc
    pprint(message)
    return {'raw': base64.urlsafe_b64encode(message.as_string())}

def send_message(service, user_id, message_in):
    """Send an email message.

    Args:
    service: Authorized Gmail API service instance.
    user_id: User's email address. The special value "me"
    can be used to indicate the authenticated user.
    message: Message to be sent.

    Returns:
    Sent Message.
    """
    pprint(message_in)
    try:
        message = (service.users().messages().send(userId=user_id, body=message_in).execute())
        pprint(message)
        print ('Message Id: %s' % message['id'])
        return message
    except errors.HttpError, error:
        print ('An error occurred: %s' % error)

def main(cli):
    """Shows basic usage of the Gmail API.

    Creates a Gmail API service object and outputs a list of label names
    of the user's Gmail account.
    """


    credentials = get_credentials()
    http = credentials.authorize(httplib2.Http())
    service = discovery.build('gmail', 'v1', http=http)

    email_msg = create_message(cli.addr_from, cli.addr_to, cli.addr_cc, cli.subject, cli.message)
    msg_out = service.users().messages().send(userId = 'me', body = email_msg).execute()
    pprint(msg_out)


if __== '__main__':
    parser = argparse.ArgumentParser()
    parser.add_argument('-m', '--message',   help = 'The message to send in the email', default='<MESSAGE = unfinished>')
    parser.add_argument('-t', '--addr_to',   help = 'the list of comma separated emails to send', default='[email protected]')
    parser.add_argument('-s', '--subject',   help = 'the email subject', default='<SUBJECT = undefined>')
    parser.add_argument('-c', '--addr_cc',   help = 'email CC\'s', default='')
    parser.add_argument('-f', '--addr_from', help = 'Email address to send from', default='[email protected]')
    cli = parser.parse_args()
    pprint(dir(cli))

    main(cli)

Ich habe versucht, mit diesem Code und Variationen davon, weder HTML-formatierten Code noch einfache Escape-Zeichen zu erhalten, um Wagenrückläufe dort zu erstellen, wo sie sein mussten.


Folgendes hat nicht funktioniert

Das Folgende zu versuchen hat auch nicht funktioniert:

  1. line 69 wird geändert, um zusätzliche Nachrichtenwörterbuchparameter hinzuzufügen ... dh.
    • {'raw': base64.urlsafe_b64encode(message.as_string()), 'payload': {'mimeType': 'text/html'}}
    • Wie hier in den GMail API-Dokumenten dokumentiert
    •  enter image description here
  2. Eine Vielzahl von maskierten Backslashes in den Nachrichtentext einfügen:
    • \n... dh: \\n noch \\\n und nur als diese genauen Zeichen gerendert
    • Beim Hinzufügen von <br> </br> <br/> wurden keine neuen Zeilen hinzugefügt und nur die exakten Zeichen gerendert
    • Durch das Hinzufügen von \r wurden keine neuen Zeilen hinzugefügt und nur als genau dieses Zeichen gerendert

Gründe, warum dies keine doppelte Frage ist

16
Andrew

Nachdem ich viel herumgegraben hatte, begann ich auf der Python-Seite der Nachrichtenbehandlung nachzuschauen und bemerkte, dass ein Python-Objekt tatsächlich die Nachricht erstellt, die für die base64-Kodierung in den gmail-api-Nachrichtenobjektkonstruktor gesendet werden soll.

Siehe Zeile 63 von oben: message = MIMEText(message_text)

Der einzige Trick, der schließlich für mich funktionierte, nach all den Versuchen, die Header-Werte und das Payload-Diktat (das ein Mitglied des message-Objekts ist) zu ändern, war (line 63) zu setzen:

  • message = MIMEText(message_text, 'html') <- fügen Sie den 'html' als zweiten Parameter des MIMEText-Objektkonstruktors hinzu

Der von Google bereitgestellte Standardcode für die Google Mail-API gibt nur an, wie E-Mails im Nur-Text-Format gesendet werden sollen. Sie verbergen jedoch nicht, wie sie dies tun . Ala ...message = MIMEText(message_text)

Ich musste die Python-Klasse email.mime.text.MIMEText object nachschlagen. Dort sehen Sie diese Definition des Konstruktors für das MIMEText-Objekt:

  • klasse email.mime.text.MIMEText (_text [ _subtype [ _charset]])) Wir möchten einen Wert explizit an den _subtype übergeben. In diesem Fall möchten wir 'html' als _subtype übergeben.

Jetzt haben Sie keine unerwarteten Zeilenumbrüche mehr auf Ihre Nachrichten von Google oder das Python mime.text.MIMEText-Objekt angewendet


Der feste Code

 def create_message (Absender, an, cc, Betreff, Nachrichtentext): 
 "" "Erstellen Sie eine Nachricht für eine E-Mail .

 Args: 
 Absender: E-Mail-Adresse des Absenders .
 An: E-Mail-Adresse des Empfängers .
 Betreff: Der Betreff der E-Mail message .
 message_text: Der Text der E-Mail-Nachricht .

 Gibt Folgendes zurück: 
 Ein Objekt, das ein mit Base64url codiertes E-Mail-Objekt enthält .
 "" 
 print (Absender + ',' + an + ',' + Betreff + ',' + Nachrichtentext) 
 message = MIMEText (Nachrichtentext, 'html') 
 message ['to'] = an 
 message ['from'] = Absender 
 message ['subject'] = Betreff 
 message ['cc'] = cc 
 pprint (Nachricht) 
 return {'raw': base64.urlsafe_b64encode (message.as_string ())} 
17
Andrew

Versuche dies:

    def CreateMessage(emailSubject, emailTo, emailFrom, message_body, emailCc, html_content=None):
        try:
            message = MIMEMultipart('alternative')
            message['to'] = emailTo
            message['from'] = emailFrom
            message['subject'] = emailSubject
            message['Cc'] = emailCc
            body_mime = MIMEText(message_body, 'plain')
            message.attach(body_mime)
            if html_content:
                html_mime = MIMEText(html_content, 'html')
                message.attach(html_mime)
            return {
                'raw': base64.urlsafe_b64encode(
                    bytes(
                        message.as_string(),
                        "utf-8")).decode("utf-8")}
        except Exception as e:
            print('Error in CreateMessage()', e)
            return '400'
1