Quiero escribir un programa que envía correo electrónico utilizando Python smtplib. Busqué a través del documento y las RFC, pero no pude encontrar nada relacionado con los archivos adjuntos. Por lo tanto, estoy seguro de que hay algún concepto de nivel superior que me estoy perdiendo. ¿Puede alguien darme una pista sobre cómo funcionan los archivos adjuntos en SMTP?¿Cómo envío archivos adjuntos usando SMTP?
Respuesta
Lo que se quiere revisar es el módulo email
. Le permite crear MIME -compliant mensajes que luego envía con smtplib.
Gracias para la edición, que eran un poco más rápido que yo ;-) –
Bueno, accesorios no son tratados de cualquier manera especial, son "sólo" hojas del árbol mensaje a objetos. Puede encontrar las respuestas a cualquier pregunta con respecto mesasges compatible con MIME en this sección de la documentación en el paquete email pitón.
En general, cualquier tipo de archivo adjunto (léase: datos binarios en bruto) puede representarse utilizando base64 (o similar) Content-Transfer-Encoding
.
He aquí un ejemplo que corté de una aplicación de trabajo que hicimos. Crea un correo electrónico HTML con un archivo adjunto de Excel.
import smtplib,email,email.encoders,email.mime.text,email.mime.base
smtpserver = 'localhost'
to = ['[email protected]']
fromAddr = '[email protected]'
subject = "my subject"
# create html email
html = '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" '
html +='"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml">'
html +='<body style="font-size:12px;font-family:Verdana"><p>...</p>'
html += "</body></html>"
emailMsg = email.MIMEMultipart.MIMEMultipart('alternative')
emailMsg['Subject'] = subject
emailMsg['From'] = fromAddr
emailMsg['To'] = ', '.join(to)
emailMsg['Cc'] = ", ".join(cc)
emailMsg.attach(email.mime.text.MIMEText(html,'html'))
# now attach the file
fileMsg = email.mime.base.MIMEBase('application','vnd.ms-excel')
fileMsg.set_payload(file('exelFile.xls').read())
email.encoders.encode_base64(fileMsg)
fileMsg.add_header('Content-Disposition','attachment;filename=anExcelFile.xls')
emailMsg.attach(fileMsg)
# send email
server = smtplib.SMTP(smtpserver)
server.sendmail(fromAddr,to,emailMsg.as_string())
server.quit()
el subtipo de varias partes debe ser 'mixta' en lugar de 'alternativo' de lo contrario no podrá ver el archivo adjunto en algunos clientes de correo electrónico. – rhyek
Así es como enviar correos electrónicos con archivos adjuntos zip y UTF-8 sujetos codificada + cuerpo.
No fue sencillo para la forma de saberlo, debido a la falta de documentación y muestras para este caso particular.
caracteres no ASCII en replyto necesita ser codificada con, por ejemplo, ISO-8859-1. Probablemente exista una función que puede hacer esto.
Consejo:
enviamos un correo electrónico, guardarlo y examinar el contenido de averiguar cómo hacer lo mismo en Python.
Aquí está el código, para Python 3:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# vim:set ts=4 sw=4 et:
from os.path import basename
from smtplib import SMTP
from email.mime.text import MIMEText
from email.mime.base import MIMEBase
from email.mime.multipart import MIMEMultipart
from email.header import Header
from email.utils import parseaddr, formataddr
from base64 import encodebytes
def send_email(recipients=["[email protected]"],
subject="Test subject æøå",
body="Test body æøå",
zipfiles=[],
server="smtp.somewhere.xyz",
username="bob",
password="password123",
sender="Bob <[email protected]>",
replyto="=?ISO-8859-1?Q?M=F8=F8=F8?= <[email protected]>"): #: bool
"""Sends an e-mail"""
to = ",".join(recipients)
charset = "utf-8"
# Testing if body can be encoded with the charset
try:
body.encode(charset)
except UnicodeEncodeError:
print("Could not encode " + body + " as " + charset + ".")
return False
# Split real name (which is optional) and email address parts
sender_name, sender_addr = parseaddr(sender)
replyto_name, replyto_addr = parseaddr(replyto)
sender_name = str(Header(sender_name, charset))
replyto_name = str(Header(replyto_name, charset))
# Create the message ('plain' stands for Content-Type: text/plain)
try:
msgtext = MIMEText(body.encode(charset), 'plain', charset)
except TypeError:
print("MIMEText fail")
return False
msg = MIMEMultipart()
msg['From'] = formataddr((sender_name, sender_addr))
msg['To'] = to #formataddr((recipient_name, recipient_addr))
msg['Reply-to'] = formataddr((replyto_name, replyto_addr))
msg['Subject'] = Header(subject, charset)
msg.attach(msgtext)
for zipfile in zipfiles:
part = MIMEBase('application', "zip")
b = open(zipfile, "rb").read()
# Convert from bytes to a base64-encoded ascii string
bs = encodebytes(b).decode()
# Add the ascii-string to the payload
part.set_payload(bs)
# Tell the e-mail client that we're using base 64
part.add_header('Content-Transfer-Encoding', 'base64')
part.add_header('Content-Disposition', 'attachment; filename="%s"' %
os.path.basename(zipfile))
msg.attach(part)
s = SMTP()
try:
s.connect(server)
except:
print("Could not connect to smtp server: " + server)
return False
if username:
s.login(username, password)
print("Sending the e-mail")
s.sendmail(sender, recipients, msg.as_string())
s.quit()
return True
def main():
send_email()
if __name__ == "__main__":
main()
Aquí es un ejemplo de un mensaje con un archivo PDF adjunto, un texto "cuerpo" y el envío a través de Gmail.
# Import smtplib for the actual sending function
import smtplib
# For guessing MIME type
import mimetypes
# Import the email modules we'll need
import email
import email.mime.application
# Create a text/plain message
msg = email.mime.Multipart.MIMEMultipart()
msg['Subject'] = 'Greetings'
msg['From'] = '[email protected]'
msg['To'] = '[email protected]'
# The main body is just another attachment
body = email.mime.Text.MIMEText("""Hello, how are you? I am fine.
This is a rather nice letter, don't you think?""")
msg.attach(body)
# PDF attachment
filename='simple-table.pdf'
fp=open(filename,'rb')
att = email.mime.application.MIMEApplication(fp.read(),_subtype="pdf")
fp.close()
att.add_header('Content-Disposition','attachment',filename=filename)
msg.attach(att)
# send via Gmail server
# NOTE: my ISP, Centurylink, seems to be automatically rewriting
# port 25 packets to be port 587 and it is trashing port 587 packets.
# So, I use the default port 25, but I authenticate.
s = smtplib.SMTP('smtp.gmail.com')
s.starttls()
s.login('[email protected]','xyzpassword')
s.sendmail('[email protected]',['[email protected]'], msg.as_string())
s.quit()
Esto resolvió mi problema para correo electrónico archivos de Excel, así que era increíble porque me mantuvo fuera de os.system llamando Rubí! Gracias Kevin! – Benjooster
Esta solución también trabajó para mí, después de crear un archivo de .xls utilizando el módulo xlwt Python. En lugar de enviar por Gmail, utilicé el servidor de correo de mi compañía. Gracias, y +1 –
este método realmente funcionó y es mucho más limpio. –
# -*- coding: utf-8 -*-
"""
Mail sender
"""
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
import smtplib
import pystache
import codecs
import time
import sys
reload(sys)
sys.setdefaultencoding('utf-8')
HOST = 'smtp.exmail.qq.com'
PORT = 587
USER = '[email protected]'
PASS = 'yourpass'
FROM = '[email protected]'
SUBJECT = 'subject'
HTML_NAME = 'tpl.html'
CSV_NAME = 'list.txt'
FAILED_LIST = []
def send(mail_receiver, mail_to):
# text = mail_text
html = render(mail_receiver)
# msg = MIMEMultipart('alternative')
msg = MIMEMultipart('mixed')
msg['From'] = FROM
msg['To'] = mail_to.encode()
msg['Subject'] = SUBJECT.encode()
# msg.attach(MIMEText(text, 'plain', 'utf-8'))
msg.attach(MIMEText(html, 'html', 'utf-8'))
try:
_sender = smtplib.SMTP(
HOST,
PORT
)
_sender.starttls()
_sender.login(USER, PASS)
_sender.sendmail(FROM, mail_to, msg.as_string())
_sender.quit()
print "Success"
except smtplib.SMTPException, e:
print e
FAILED_LIST.append(mail_receiver + ',' + mail_to)
def render(name):
_tpl = codecs.open(
'./html/' + HTML_NAME,
'r',
'utf-8'
)
_html_string = _tpl.read()
return pystache.render(_html_string, {
'receiver': name
})
def main():
ls = open('./csv/' + CSV_NAME, 'r')
mail_list = ls.read().split('\r')
for _receiver in mail_list:
_tmp = _receiver.split(',')
print 'Mail: ' + _tmp[0] + ',' + _tmp[1]
time.sleep(20)
send(_tmp[0], _tmp[1])
print FAILED_LIST
main()
- 1. sendmailR (Part2): Envío de archivos como archivos adjuntos de correo
- 2. Java Mail, el envío de varios archivos adjuntos no funciona
- 3. Envío de correos electrónicos con archivos adjuntos programáticamente en ASP.NET
- 4. ¿Cómo enviar un correo electrónico con archivos adjuntos utilizando SmtpClient.SendAsync?
- 5. ¿Cómo envío un mensaje SMTP desde Java?
- 6. vsto + diferenciar archivos adjuntos
- 7. Múltiples archivos adjuntos con Swiftmailer
- 8. Archivos adjuntos de correo electrónico
- 9. ¿Cómo enviar archivos adjuntos de correo electrónico?
- 10. cómo agregar archivos adjuntos en PHPMailer?
- 11. iTextSharp para PDF: ¿cómo agregar archivos adjuntos?
- 12. ¿Cómo enviar correo con archivos adjuntos de gran tamaño usando System.Net.Mail a Google Apps?
- 13. Zend Mail 2.0 Archivos adjuntos
- 14. Ver archivos adjuntos en hilos
- 15. Enviando correos electrónicos con archivos adjuntos desde C#, los archivos adjuntos llegan como parte 1.2 en Thunderbird
- 16. ¿Cómo abrir la lista de archivos adjuntos?
- 17. ¿Cómo envío un correo electrónico usando SMTP e Indy 10 de Gmail?
- 18. ¿Cómo envío un correo electrónico a mi cuenta de Gmail usando SMTP y Perl?
- 19. Decodificación MIME (HTML + archivos adjuntos)
- 20. Varios archivos adjuntos en C#
- 21. Correo de Java: envío de correo electrónico sin SMTP
- 22. cómo enviar correo usando smtp en asp.net
- 23. Envío de correo sin instalar un servidor SMTP
- 24. ¿Cómo extraigo los archivos adjuntos de un archivo pdf?
- 25. Envío de correos electrónicos a través de SMTP con PHPMailer
- 26. enviando un correo electrónico con varios archivos adjuntos
- 27. SOAP con archivos adjuntos en VB.NET
- 28. Enviar correo usando SMTP localhost
- 29. Correo electrónico de envío de ASP clásico con autenticación SMTP
- 30. Envío de correo electrónico SMTP a alta velocidad en .NET
Para que quede claro, no hay nada en absoluto en SMTP para manejar esto, es completamente manejado por la estructuración del documento que se envía como un documento MIME. El artículo sobre MIME en wikipedia parece cubrir bastante bien el básico. – jcoder
La inclusión de un enlace directo a los "ejemplos de correo electrónico" de la documentación de Python haría que cualquier respuesta completa: http://docs.python.org/library/email-examples.html –