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.

392voto

sorin Points 23747

Ce site fonctionne vraiment J'ai passé beaucoup de temps à essayer plusieurs 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())

4 votes

La documentation contient l'exemple : tolist =["one@one.org","two@two.org","three@three.org","four@four.o‌​rg"]

2 votes

Merci @sorin pour ce script. J'avais un problème pour envoyer un email depuis un script python et avec ce bout de code, je peux maintenant envoyer l'email.

19 votes

Ceci n'enverra pas à plusieurs destinataires si vous utilisez Python 3 vous avez besoin de send_message au lieu de sendmail selon le commentaire d'Antoine ci-dessous et les docs Python docs.python.org/3/library/email.examples.html

180voto

dvdhns Points 1339

El msg['To'] doit être une chaîne de caractères :

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

Alors que le recipients sur sendmail(sender, recipients, message) doit être une liste :

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

3 votes

C'est une étrange décision de conception pour smtplib.

4 votes

recipients ne doit pas nécessairement être une liste - si une chaîne est donnée, elle est traitée comme une liste à un élément. Le site msg['To'] peut simplement être omise.

1 votes

Je ne comprends pas vraiment comment 'a@a.com, b@b.com' est analysé pour que seule la première adresse reçoive l'e-mail. Mais, merci ! C'est la réponse, je devais mettre la liste là-dedans.

56voto

Anony-Mousse Points 24646

Vous devez comprendre la différence entre le visible d'un courriel, et l'adresse livraison .

msg["To"] est essentiellement ce qui est imprimé sur la lettre. Cela n'a en fait aucun effet. Sauf que votre client de messagerie, tout comme l'agent postal ordinaire, supposera que c'est à cette personne que vous voulez envoyer le courrier électronique.

La livraison effective peut toutefois être très différente. Ainsi, vous peut déposer l'e-mail (ou une copie) dans la boîte aux lettres d'une personne complètement différente.

Il y a plusieurs raisons à cela. Par exemple redirection . Le site To: ne change pas lors du transfert, mais l'e-mail est déposé dans une autre boîte aux lettres.

Le site smtp.sendmail s'occupe maintenant de la réel livraison. email.Message ne concerne que le contenu de la lettre, pas la livraison.

En bas niveau SMTP vous devez indiquer les destinataires un par un, c'est pourquoi une liste d'adresses (sans les noms !) est une API judicieuse.

Pour l'en-tête, il peut aussi contenir par exemple le nom, ex. To: First Last <email@addr.tld>, Other User <other@mail.tld> . Votre exemple de code n'est donc pas recommandé car il n'arrivera pas à distribuer ce courrier, puisqu'en le divisant simplement sur , vous n'avez toujours pas les adresses valides !

2 votes

La RFC 2822 impose une largeur maximale de 988 caractères pour un en-tête donné et une largeur recommandée de 78 caractères. Vous devrez veiller à "plier" l'en-tête si vous avez trop d'adresses.

0 votes

Cette réponse devrait être acceptée, car elle explique le pourquoi et le comment.

0 votes

Excellente réponse. Qu'en est-il des champs de courriel CC et BCC ? Je suppose que nous devons également inclure les adresses CC et BCC dans smtp.send. Et seulement la liste CC (et pas la liste BCC) dans les champs msg ?

32voto

coolguy Points 291

Ça marche pour moi.

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

0 votes

Quelle version de python utilisez-vous ? J'ai le même problème que le posteur original et j'utilise python 2.7.9.

1 votes

Pourquoi ne pas simplement recipients = ['john.doe@example.com','john.smith@example.co.uk'] au lieu d'en faire une chaîne, puis de la diviser pour en faire une liste ?

1 votes

À Woj, parce que msg['To'] devrait être une chaîne et s.sendmail devrait avoir une liste : (sender,>>>LIST HERE<<<,msg.as_string()). Cela signifie, aussi ennuyeux que cela puisse paraître, que vous ne pouvez pas utiliser le même type [ string ou list ] pour les deux champs.

22voto

Omkar Points 420

La solution ci-dessous a fonctionné pour moi. Elle permet d'envoyer avec succès un courriel à plusieurs destinataires, y compris "CC" et "BCC".

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)

2 votes

Cela fonctionne partiellement, pour vraiment cacher le BCC vous devez omettre la ligne BCC bcc = ['mailid_5', 'mailid_6'] sinon cela apparaîtra dans l'en-tête, ce qui va à l'encontre du but du BCC. Testé avec gmail et d'autres serveurs de messagerie.

1 votes

@Wil comment implémenteriez-vous BCC dans ce cas ?

0 votes

@3pitt un peu tard, mais il suffit de leur envoyer le même email en utilisant s.sendmail(fromaddr, bcc, message) .

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