263 votes

Comment envoyer un email à plusieurs destinataires en utilisant python smtplib ?

Après de nombreuses recherches, je n'ai pas trouvé comment utiliser smtplib.sendmail pour envoyer à plusieurs destinataires. Le problème était qu'à chaque fois que le courrier était envoyé, les en-têtes du courrier semblaient contenir plusieurs adresses, mais en fait, seul le premier destinataire recevait l'e-mail.

Le problème semble être que le email.Message attend quelque chose de différent du module smtplib.sendmail() fonction.

En bref, pour envoyer à plusieurs destinataires, vous devez définir l'en-tête comme une chaîne d'adresses électroniques délimitées par des virgules. Le site sendmail() paramètre to_addrs devrait toutefois être une liste d'adresses électroniques.

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

1 votes

Il semble que le PO ait répondu à sa propre question : sendmail a besoin d'une liste.

0 votes

1 votes

En utilisant Python3, j'ai dû passer en boucle les destinataires ; for addr in recipients: msg['To'] = addr et puis ça a marché. Les affectations multiples ajoutent en fait un nouvel en-tête "À" pour chacune d'entre elles. C'est une interface très bizarre, je ne peux même pas expliquer comment j'ai pensé à l'essayer. J'ai même envisagé d'utiliser subprocess pour appeler le système unix sendmail paquet pour sauver ma santé mentale avant de comprendre ça.

7voto

James McPherson Points 41

J'ai compris cela il y a quelques mois et j'en ai parlé sur mon blog. Le résumé est le suivant :

Si vous souhaitez utiliser smtplib pour envoyer un message à plusieurs destinataires, utilisez email.Message.add_header('To', eachRecipientAsString) pour les ajouter, puis lorsque vous invoquez la méthode sendmail, utilisez email.Message.get_all('To') pour envoyer le message à chacun d'entre eux. Idem pour les destinataires Cc et Bcc.

http://www.jmcpdotcom.com/blog/2012/01/06/multiple-recipients-with-pythons-smtplib-sendmail-method a les détails sanglants.

0 votes

Python 3.7 lève une exception avec un message : Une exception s'est produite : ValueError Il peut y avoir au maximum 1 en-tête To dans un message

6voto

Antoine Points 369

Eh bien, la méthode dans cette asnwer La méthode n'a pas fonctionné pour moi. Je ne sais pas, peut-être est-ce un problème lié à Python3 (j'utilise la version 3.4) ou à gmail, mais après quelques essais, la solution qui a fonctionné pour moi, était la ligne

s.send_message(msg)

au lieu de

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

1voto

Gwi7d31 Points 16

Il y a beaucoup de réponses ici qui sont techniquement ou partiellement correctes. Après avoir lu les réponses de tout le monde, j'ai trouvé ceci comme une fonction de courriel plus solide/universelle. J'ai confirmé qu'elle fonctionne et que vous pouvez passer du HTML ou du texte brut pour le corps. Notez que ce code n'inclut pas le code de la pièce jointe :

import smtplib
import socket

# Import the email modules we'll need
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart

#
# @param [String] email_list
# @param [String] subject_line
# @param [String] error_message
def sendEmailAlert(email_list="default@email.com", subject_line="Default Subject", error_message="Default Error Message"):
    hostname = socket.gethostname()
    # Create message
    msg = MIMEMultipart()
    msg['Subject'] = subject_line
    msg['From'] = f'no-reply@{hostname}'
    msg['To'] = email_list
    msg.attach(MIMEText(error_message, 'html'))
    # Send the message via SMTP server
    s = smtplib.SMTP('localhost') # Change for remote mail server!
    # Verbose debugging
    s.set_debuglevel(2)
    try:
        s.sendmail(msg['From'], msg['To'].split(","), msg.as_string())
    except Exception as e:
        print(f'EMAIL ISSUE: {e}')
    s.quit()

Ceci peut évidemment être modifié pour utiliser la journalisation native de Python. Je ne fais que fournir une fonction de base solide. Je ne saurais trop insister sur ce point, sendmail() veut un List et PAS un String ! La fonction est pour Python3.6+.

0voto

Skiller Dz Points 510

Vous pouvez essayer ceci lorsque vous écrivez les emails récpients sur un fichier texte

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')

0voto

Kevin G Points 93

Essayez de déclarer une variable de liste avec tous les destinataires et cc_recipients sous forme de chaînes de caractères et de boucler sur eux, comme ceci :

from email.MIMEMultipart import MIMEMultipart
from email.MIMEText import MIMEText
import smtplib

recipients = ["malcom@example.com","reynolds@example.com", "firefly@example.com"]
cc_recipients=["serenity@example.com", "inara@example.com"]
msg = MIMEMultipart()
msg["Subject"] = "Example"
msg["From"] = "me@example.com"
msg["To"] = ', '.join(recipients)
msg["Cc"] = ', '.join(cc_recipients)
body = MIMEText("example email body")
msg.attach(body)
smtp = smtplib.SMTP("mailhost.example.com", 25)
for recipient in recipients:
    smtp.sendmail(msg["From"], recipient, msg.as_string())
for cc_recipient in cc_recipients:
    smtp.sendmail(msg["From"], cc_recipient, msg.as_string())
smtp.quit()

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X