script mail enviar correo con adjunto python html gmail gmail-api mime-message

enviar - send email python 3



¿Cómo envío correos electrónicos con formato HTML, a través de gmail-api para python? (2)

Uso del código de muestra del GMail API Ejemplo: Enviar correo , y luego de seguir las reglas de autenticación, es lo suficientemente simple como para enviar un correo electrónico generado mediante programación, a través de una cuenta de gmail. Lo que no es obvio del ejemplo es cómo configurar ese correo electrónico para que tenga el formato HTML.

La pregunta

¿Cómo obtengo el formato HTML en mis mensajes de envío de gmail-api, usando python?

Tengo esto...

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

y quiero que sea esto ...

Hello! You''ve just received a test message! Sincerely, -Test Message Generator

Código fuente de ejemplo de GMail-API

A continuación se muestra una versión ligeramente modificada del ejemplo, pero aún funciona:

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 __name__ == ''__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)

Intenté todo lo que pude, con este código y las variaciones en él, no pude obtener el código con formato html, ni tampoco podría obtener caracteres de escape simples para crear retornos de carro donde debían estar.

Esto es lo que no funcionó

Intentar lo siguiente tampoco funcionó:

  1. modificando la line 69 para agregar parámetros de diccionario de mensajes adicionales ... es decir.
    • {''raw'': base64.urlsafe_b64encode(message.as_string()), ''payload'': {''mimeType'': ''text/html''}}
    • Como se documenta aquí en GMail API Docs
  2. Agregando una variedad de barras invertidas escapadas en el texto del mensaje:
    • /n ... es decir: //n nor ///n y solo se representan como esos caracteres exactos
    • Al agregar <br> </br> <br/> no se agregaron nuevas líneas y solo se representaron como esos caracteres exactos
    • Agregar /r no agregó nuevas líneas y solo se representó como ese carácter exacto

Razones esto no es una pregunta duplicada


Después de investigar mucho, comencé a mirar hacia el lado de Python en el manejo de mensajes y noté que un objeto de Python está construyendo realmente el mensaje que se enviará para la codificación de base64 en el constructor de objetos de mensajes de gmail-api.

Consulte la línea 63 de arriba: message = MIMEText(message_text)

El único truco que finalmente funcionó para mí , después de todos los intentos de modificar los valores del encabezado y el dictamen de carga útil (que es un miembro del objeto de message ), fue establecer ( line 63 ):

  • message = MIMEText(message_text, ''html'') <- agrega el ''html'' como el segundo parámetro del constructor de objetos MIMEText

El código predeterminado suministrado por Google para su API de gmail solo le indica cómo enviar correos electrónicos de texto sin formato, pero ocultan cómo lo hacen. ala ... message = MIMEText(message_text)

Tuve que buscar el objeto email.mime.text.MIMEText clase python. Ahí es donde verá esta definición del constructor para el objeto MIMEText:

  • class email.mime.text.MIMEText (_text [, _subtype [, _charset]]) Queremos pasarle un valor explícitamente al _subtype . En este caso, queremos pasar: ''html'' como el _subtype .

Ahora, ya no tendrá que aplicar el mime.text.MIMEText palabras inesperado a sus mensajes por parte de Google o del objeto mime.text.MIMEText Python

El Código Fijo

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,''html'') message[''to''] = to message[''from''] = sender message[''subject''] = subject message[''cc''] = cc pprint(message) return {''raw'': base64.urlsafe_b64encode(message.as_string())}


Prueba esto:

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