¿Cómo enviar correos electrónicos a múltiples destinatarios usando Python smtplib?

Después de mucho buscar, no pude descubrir cómo usar smtplib.sendmail para enviar a múltiples destinatarios. El problema era que cada vez que se enviaba el correo, los encabezados del correo parecían contener varias direcciones, pero de hecho solo el primer destinatario recibiría el correo electrónico.

El problema parece ser que el módulo email.Message espera algo diferente a la función smtplib.sendmail() .

En resumen, para enviar a múltiples destinatarios, debe configurar el encabezado como una cadena de direcciones de correo electrónico delimitadas por comas. El parámetro sendmail() to_addrs sin embargo, debe ser una lista de direcciones de correo electrónico.

 from email.MIMEMultipart import MIMEMultipart from email.MIMEText import MIMEText import smtplib msg = MIMEMultipart() msg["Subject"] = "Example" msg["From"] = "me@example.com" msg["To"] = "malcom@example.com,reynolds@example.com,firefly@example.com" msg["Cc"] = "serenity@example.com,inara@example.com" body = MIMEText("example email body") msg.attach(body) smtp = smtplib.SMTP("mailhost.example.com", 25) smtp.sendmail(msg["From"], msg["To"].split(",") + msg["Cc"].split(","), msg.as_string()) smtp.quit() 

Esto realmente funciona , pasé mucho tiempo probando múltiples variantes.

 import smtplib from email.mime.text import MIMEText s = smtplib.SMTP('smtp.uk.xensource.com') s.set_debuglevel(1) msg = MIMEText("""body""") sender = 'me@example.com' recipients = ['john.doe@example.com', 'john.smith@example.co.uk'] msg['Subject'] = "subject line" msg['From'] = sender msg['To'] = ", ".join(recipients) s.sendmail(sender, recipients, msg.as_string()) 

El msg['To'] necesita ser una cadena:

 msg['To'] = "a@b.com, b@b.com, c@b.com" 

Mientras que los recipients en sendmail(sender, recipients, message) deben ser una lista:

 sendmail("a@a.com", ["a@b.com", "b@b.com", "c@b.com"], "Howdy") 

Debe comprender la diferencia entre la dirección visible de un correo electrónico y la entrega .

msg["To"] es esencialmente lo que está impreso en la carta. En realidad no tiene ningún efecto. Excepto que su cliente de correo electrónico, al igual que el oficial de correos regular, asumirá que es a quién desea enviar el correo electrónico.

Sin embargo, la entrega real puede funcionar bastante diferente. Por lo tanto, puede colocar el correo electrónico (o una copia) en el buzón de alguien completamente diferente.

Hay varias razones para esto. Por ejemplo reenvío . El campo del encabezado To: no cambia al reenviar, sin embargo, el correo electrónico se coloca en un buzón diferente.

El comando smtp.sendmail ahora se encarga de la entrega real . email.Message es solo el contenido de la carta, no la entrega.

En SMTP bajo nivel, debe proporcionar a los destinatarios uno por uno, por lo que una lista de direcciones (¡sin incluir nombres!) Es la API adecuada.

Para el encabezado, también puede contener, por ejemplo, el nombre, por ejemplo, To: First Last , Other User . Por lo tanto, no se recomienda el ejemplo de su código , ya que fallará la entrega de este correo, ya que simplemente al dividirlo , ¡todavía no tiene las direcciones válidas!

Esto funciona para mi.

 import smtplib from email.mime.text import MIMEText s = smtplib.SMTP('smtp.uk.xensource.com') s.set_debuglevel(1) msg = MIMEText("""body""") sender = 'me@example.com' recipients = 'john.doe@example.com,john.smith@example.co.uk' msg['Subject'] = "subject line" msg['From'] = sender msg['To'] = recipients s.sendmail(sender, recipients.split(','), msg.as_string()) 

Probé a continuación y funcionó a la perfección 🙂

 rec_list = ['first@example.com', 'second@example.com'] rec = ', '.join(rec_list) msg['To'] = rec send_out = smtplib.SMTP('localhost') send_out.sendmail(me, rec_list, msg.as_string()) 

Se me ocurrió esta función de módulo importable. Utiliza el servidor de correo de gmail en este ejemplo. Se divide en encabezado y mensaje para que pueda ver claramente qué está pasando:

 import smtplib def send_alert(subject=""): to = ['email@one.com', 'email2@another_email.com', 'a3rd@email.com'] gmail_user = 'me@gmail.com' gmail_pwd = 'my_pass' smtpserver = smtplib.SMTP("smtp.gmail.com", 587) smtpserver.ehlo() smtpserver.starttls() smtpserver.ehlo smtpserver.login(gmail_user, gmail_pwd) header = 'To:' + ", ".join(to) + '\n' + 'From: ' + gmail_user + '\n' + 'Subject: ' + subject + '\n' msg = header + '\n' + subject + '\n\n' smtpserver.sendmail(gmail_user, to, msg) smtpserver.close() 

Descubrí esto hace unos meses y escribí un blog al respecto . El resumen es:

Si desea usar smtplib para enviar correos electrónicos a múltiples destinatarios, use email.Message.add_header('To', eachRecipientAsString) para agregarlos, y luego, cuando invoque el método sendmail, use email.Message.get_all('To') Envía el mensaje a todos ellos. Lo mismo ocurre con los destinatarios de Cc y Bcc.

Entonces, en realidad, el problema es que SMTP.sendmail y email.MIMEText necesitan dos cosas diferentes.

email.MIMEText configura el encabezado “Para:” para el cuerpo del correo electrónico. SOLO se usa para mostrar un resultado al ser humano en el otro extremo, y como todos los encabezados de correo electrónico, debe ser una sola cadena. (Tenga en cuenta que en realidad no tiene que tener nada que ver con las personas que realmente reciben el mensaje).

SMTP.sendmail, por otro lado, configura el “sobre” del mensaje para el protocolo SMTP. Necesita una lista de cadenas de Python, cada una de las cuales tiene una sola dirección.

Entonces, lo que debe hacer es COMBINAR las dos respuestas que recibió. Establezca msg [‘To’] en una sola cadena, pero pase la lista en bruto a sendmail:

 emails = ['a.com','b.com', 'c.com'] msg['To'] = ', '.join( emails ) .... s.sendmail( msg['From'], emails, msg.as_string()) 

Bueno, el método en este método de respuesta no funcionó para mí. No sé, tal vez este es un problema relacionado con Python3 (estoy usando la versión 3.4) o gmail, pero después de algunos bashs, la solución que funcionó para mí fue la línea

 s.send_message(msg) 

en lugar de

 s.sendmail(sender, recipients, msg.as_string()) 

Yo uso Python 3.6 y el siguiente código funciona para mí

 email_send = 'xxxxx@xxx.xxx,xxxx@xxx.xxx' server.sendmail(email_user,email_send.split(','),text) 
 Below worked for me. It sends email to multiple with attachment - "To", "Cc" & "Bcc" successfully. toaddr = ['mailid_1','mailid_2'] cc = ['mailid_3','mailid_4'] bcc = ['mailid_5','mailid_6'] subject = 'Email from Python Code' fromaddr = 'sender_mailid' message = "\n !! Hello... !!" msg['From'] = fromaddr msg['To'] = ', '.join(toaddr) msg['Cc'] = ', '.join(cc) msg['Bcc'] = ', '.join(bcc) msg['Subject'] = subject s.sendmail(fromaddr, (toaddr+cc+bcc) , message) 

puede intentar esto cuando escribe los correos electrónicos de recpient en un archivo de texto

 from email.mime.text import MIMEText from email.header import Header import smtplib f = open('emails.txt', 'r').readlines() for n in f: emails = n.rstrip() server = smtplib.SMTP('smtp.uk.xensource.com') server.ehlo() server.starttls() body = "Test Email" subject = "Test" from = "me@example.com" to = emails msg = MIMEText(body,'plain','utf-8') msg['Subject'] = Header(subject, 'utf-8') msg['From'] = Header(from, 'utf-8') msg['To'] = Header(to, 'utf-8') text = msg.as_string() try: server.send(from, emails, text) print('Message Sent Succesfully') except: print('There Was An Error While Sending The Message') 
 import smtplib from email.mime.multipart import MIMEMultipart from email.mime.text import MIMEText def sender(recipients): body = 'Your email content here' msg = MIMEMultipart() msg['Subject'] = 'Email Subject' msg['From'] = 'your.email@gmail.com' msg['To'] = (', ').join(recipients.split(',')) msg.attach(MIMEText(body,'plain')) server = smtplib.SMTP('smtp.gmail.com', 587) server.starttls() server.login('your.email@gmail.com', 'yourpassword') server.send_message(msg) server.quit() if __name__ == '__main__': sender('email_1@domain.com,email_2@domain.com') 

Solo me funcionó con la función send_message y usando la función join en la lista con los destinatarios, python 3.6.