script por enviar con adjunto python email smtp attachment smtplib

python - por - ¿Cómo envío archivos adjuntos usando SMTP?



python send email gmail (6)

A continuación, le indicamos cómo enviar correos electrónicos con archivos adjuntos en un archivo zip y un cuerpo + cuerpo codificado en utf-8.

No fue sencillo descifrar esto, debido a la falta de documentación y muestras para este caso en particular.

Los caracteres que no son ASCII en la respuesta a deben codificarse, por ejemplo, con ISO-8859-1. Probablemente existe una función que puede hacer esto.

Propina:
Envíese un correo electrónico, guárdelo y examine el contenido para descubrir 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()

Quiero escribir un programa que envíe correo electrónico usando el smtplib de Python. Busqué en el documento y en los 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. ¿Alguien me puede dar una idea de cómo funcionan los archivos adjuntos en SMTP?


Aquí hay un ejemplo de un mensaje con un archivo PDF adjunto, un "cuerpo" de texto y 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()


Aquí hay un ejemplo que saqué 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()


Bueno, los archivos adjuntos no se tratan de ninguna manera especial, son "solo" hojas del árbol de objetos de mensaje. Puede encontrar las respuestas a cualquier pregunta sobre mesasges compatibles con MIME en this sección de la documentación del paquete de email python.

En general, cualquier tipo de adjunto (leído: datos binarios sin procesar) se puede representar mediante el uso de la codificación Content-Transfer-Encoding base64 (o similar).


Lo que quieres revisar es el módulo de email . Le permite crear mensajes compatibles con MIME que luego envía con smtplib.


# -*- 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()