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ó:
- 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
-
- 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
- Este enlace SO trata con mensajes multiparte / firmados
- No me interesan los mensajes de varias partes porque es una solución poco elegante. Quiero que el mensaje ENTERO sea
HTML
. - Además, este enlace no tiene una respuesta aceptada, y la única respuesta presente es una no respuesta ya que simplemente indica que están enviando una declaración de problema a Google.
- No me interesan los mensajes de varias partes porque es una solución poco elegante. Quiero que el mensaje ENTERO sea
- Este trata sobre c #, que no me interesa ya que estoy escribiendo en python
- Este es para rieles
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''