2010-07-29 44 views
187

Tengo problemas para entender cómo enviar un archivo adjunto usando Python. He enviado correos electrónicos con éxito con el smtplib. ¿Podría alguien explicar cómo enviar un archivo adjunto en un correo electrónico? Sé que hay otras publicaciones en línea pero, como principiante de Python, las encuentro difíciles de entender.¿Cómo enviar archivos adjuntos de correo electrónico?

+3

he aquí una sencilla implementación que puede adjuntar múltiples archivos, e incluso referirse a ellos en el caso de imágenes para incrustar. http://datamakessense.com/easy-scheduled-emailing-with-python-for-typical-bi-needs/ – AdrianBR

Respuesta

269

Aquí hay otro:

import smtplib 
from os.path import basename 
from email.mime.application import MIMEApplication 
from email.mime.multipart import MIMEMultipart 
from email.mime.text import MIMEText 
from email.utils import COMMASPACE, formatdate 


def send_mail(send_from, send_to, subject, text, files=None, 
       server="127.0.0.1"): 
    assert isinstance(send_to, list) 

    msg = MIMEMultipart() 
    msg['From'] = send_from 
    msg['To'] = COMMASPACE.join(send_to) 
    msg['Date'] = formatdate(localtime=True) 
    msg['Subject'] = subject 

    msg.attach(MIMEText(text)) 

    for f in files or []: 
     with open(f, "rb") as fil: 
      part = MIMEApplication(
       fil.read(), 
       Name=basename(f) 
      ) 
     # After the file is closed 
     part['Content-Disposition'] = 'attachment; filename="%s"' % basename(f) 
     msg.attach(part) 


    smtp = smtplib.SMTP(server) 
    smtp.sendmail(send_from, send_to, msg.as_string()) 
    smtp.close() 

Es lo mismo que el primer ejemplo ... pero debería ser más fácil para caer en

+4

Tenga cuidado con los valores predeterminados mutables: http://stackoverflow.com/questions/101268/hidden-features-of-python/113198#113198 –

+0

-1 El bucle for no funcionará. Debe leer 'para archivo en archivos'. – garnertb

+10

@ user589983 ¿Por qué no sugerir una edición como lo haría cualquier otro usuario aquí? Cambié la referencia restante a 'archivo' en' f'. – Oli

19
from email.MIMEMultipart import MIMEMultipart 
from email.MIMEText import MIMEText 
from email.MIMEImage import MIMEImage 
import smtplib 

msg = MIMEMultipart() 
msg.attach(MIMEText(file("text.txt").read())) 
msg.attach(MIMEImage(file("image.png").read())) 

# to send 
mailer = smtplib.SMTP() 
mailer.connect() 
mailer.sendmail(from_, to, msg.as_string()) 
mailer.close() 

Adaptado de here.

+0

No es exactamente lo que estoy buscando. El archivo fue enviado como el cuerpo de un correo electrónico. También faltan corchetes en la línea 6 y 7. Siento que nos estamos acercando aunque – Richard

+0

Los correos electrónicos son texto sin formato, y eso es lo que 'smtplib' admite. Para enviar archivos adjuntos, los codifica como un mensaje MIME y los envía en un mensaje de texto sin formato. Sin embargo, hay un nuevo módulo de correo electrónico de python: http://docs.python.org/library/email.mime.html – katrielalex

+0

@katrienlalex, un ejemplo de trabajo que ayudaría mucho a comprender – Richard

55

este es el código que terminé usando:.

import smtplib 
from email.MIMEMultipart import MIMEMultipart 
from email.MIMEBase import MIMEBase 
from email import Encoders 


SUBJECT = "Email Data" 

msg = MIMEMultipart() 
msg['Subject'] = SUBJECT 
msg['From'] = self.EMAIL_FROM 
msg['To'] = ', '.join(self.EMAIL_TO) 

part = MIMEBase('application', "octet-stream") 
part.set_payload(open("text.txt", "rb").read()) 
Encoders.encode_base64(part) 

part.add_header('Content-Disposition', 'attachment; filename="text.txt"') 

msg.attach(part) 

server = smtplib.SMTP(self.EMAIL_SERVER) 
server.sendmail(self.EMAIL_FROM, self.EMAIL_TO, msg.as_string()) 

El código es muy parecido al de Oli. Gracias a todos

Código basado en la publicación Binary file email attachment problem.

+1

Buena respuesta. Sería bueno si también contenía código que agrega un cuerpo de texto de muestra. –

46

Aquí es la versión modificada de Oli para Python 3

import smtplib 
import os.path as op 
from email.mime.multipart import MIMEMultipart 
from email.mime.base import MIMEBase 
from email.mime.text import MIMEText 
from email.utils import COMMASPACE, formatdate 
from email import encoders 


def send_mail(send_from, send_to, subject, message, files=[], 
       server="localhost", port=587, username='', password='', 
       use_tls=True): 
    """Compose and send email with provided info and attachments. 

    Args: 
     send_from (str): from name 
     send_to (str): to name 
     subject (str): message title 
     message (str): message body 
     files (list[str]): list of file paths to be attached to email 
     server (str): mail server host name 
     port (int): port number 
     username (str): server auth username 
     password (str): server auth password 
     use_tls (bool): use TLS mode 
    """ 
    msg = MIMEMultipart() 
    msg['From'] = send_from 
    msg['To'] = COMMASPACE.join(send_to) 
    msg['Date'] = formatdate(localtime=True) 
    msg['Subject'] = subject 

    msg.attach(MIMEText(message)) 

    for path in files: 
     part = MIMEBase('application', "octet-stream") 
     with open(path, 'rb') as file: 
      part.set_payload(file.read()) 
     encoders.encode_base64(part) 
     part.add_header('Content-Disposition', 
         'attachment; filename="{}"'.format(op.basename(path))) 
     msg.attach(part) 

    smtp = smtplib.SMTP(server, port) 
    if use_tls: 
     smtp.starttls() 
    smtp.login(username, password) 
    smtp.sendmail(send_from, send_to, msg.as_string()) 
    smtp.quit() 
+0

gracias pero sería bueno tener también lo básico: la sintaxis para un solo archivo adjunto (usando su ruta) – JinSnow

+0

parece que no cierra sus archivos, será basura recolectada o cerrada en la salida pero es un mal hábito. con open() como f: es la forma correcta. – comte

+0

El código no funciona. Nombre de variable incorrecta f en formato (os.path.basename (f)) debe ser formato (os.path.basename (ruta)) – Chris

3

El código más simple que pudiera llegar a es:

#for attachment email 
from django.core.mail import EmailMessage 

    def attachment_email(request): 
      email = EmailMessage(
      'Hello', #subject 
      'Body goes here', #body 
      '[email protected]', #from 
      ['[email protected]'], #to 
      ['[email protected]'], #bcc 
      reply_to=['[email protected]'], 
      headers={'Message-ID': 'foo'}, 
      ) 

      email.attach_file('/my/path/file') 
      email.send() 

Se basaba en el funcionario Django documentation

+1

en su caso tiene que instalar django para enviar un correo electrónico ...no responde correctamente la pregunta – comte

+0

@comte 'coz python solo se usa para Django, ¿verdad? – Auspex

+2

@Auspex ese es mi punto ;-) es como instalar LibreOffice para editar un archivo de configuración ... – comte

Cuestiones relacionadas