python: comment envoyer des mails avec TO, CC et BCC?

102

J'ai besoin à des fins de test de remplir quelques centaines de boîtes e-mail avec divers messages, et j'allais utiliser smtplib pour cela. Mais entre autres, je dois être capable d'envoyer des messages non seulement à des boîtes aux lettres spécifiques, mais également en CC et en BCC. Il ne semble pas que smtplib prenne en charge CC-ing et BCC lors de l'envoi d'e-mails.

Vous recherchez des suggestions pour envoyer des messages CC ou BCC à partir du script python.

(Et - non, je ne crée pas de script pour spammer quiconque en dehors de mon environnement de test.)

user63503
la source

Réponses:

150

Les en-têtes des e-mails n'ont pas d'importance pour le serveur smtp. Ajoutez simplement les destinataires CC et BCC aux toaddrs lorsque vous envoyez votre e-mail. Pour CC, ajoutez-les à l'en-tête CC.

toaddr = '[email protected]'
cc = ['[email protected]','[email protected]']
bcc = ['[email protected]']
fromaddr = '[email protected]'
message_subject = "disturbance in sector 7"
message_text = "Three are dead in an attack in the sewers below sector 7."
message = "From: %s\r\n" % fromaddr
        + "To: %s\r\n" % toaddr
        + "CC: %s\r\n" % ",".join(cc)
        + "Subject: %s\r\n" % message_subject
        + "\r\n" 
        + message_text
toaddrs = [toaddr] + cc + bcc
server = smtplib.SMTP('smtp.sunnydale.k12.ca.us')
server.set_debuglevel(1)
server.sendmail(fromaddr, toaddrs, message)
server.quit()
ABentSpoon
la source
smtplib.SMTP n'envoie pas de listes d'adresses. Au moins pas sur python 2.7.2
LostMohican
Dans ce cas, l'en-tête BCC mentionné dans la RFC 2822 n'a aucun sens.
Chenxiong Qi
1
@ABentSpoon il manque un deux-points après "Subject".
user891260
3
N'ajoutez pas l'en-tête Cci. Voir ceci: mail.python.org/pipermail/email-sig/2004-September/000151.html Et ceci: "" "Notez que le deuxième argument de sendmail (), les destinataires, est passé sous forme de liste. Vous pouvez inclure n'importe quel nombre d'adresses dans la liste pour que le message soit remis à chacune d'elles à tour de rôle. Puisque les informations de l'enveloppe sont séparées des en-têtes de message, vous pouvez même Cci quelqu'un en l'incluant dans l'argument de la méthode mais pas dans l'en-tête du message. " "" de pymotw.com/2/smtplib
Leonardo Andrade
2
Ce ne sera jamais BCC ou CC - ce sera toujours To
ProsperousHeart
37

L'essentiel est d'ajouter les destinataires sous forme de liste d'identifiants de messagerie dans votre appel sendmail.

import smtplib
from email.mime.multipart import MIMEMultipart

me = "[email protected]"
to = "[email protected]"
cc = "[email protected],[email protected]"
bcc = "[email protected],[email protected]"

rcpt = cc.split(",") + bcc.split(",") + [to]
msg = MIMEMultipart('alternative')
msg['Subject'] = "my subject"
msg['To'] = to
msg['Cc'] = cc
msg.attach(my_msg_body)
server = smtplib.SMTP("localhost") # or your smtp server
server.sendmail(me, rcpt, msg.as_string())
server.quit()
Hélios
la source
4
Laissez msg['BCC']désactivé - il révèle votre expéditeur masqué et n'a aucun impact sur le fait que le message lui soit envoyé ou non (les arguments pour le sendmailfaire).
Erica Kane
2
Je suis d'accord avec Erica et Julio. L'intention de Bcc est de cacher le récepteur à d'autres récepteurs. Si c'est dans le message, cela va à l'encontre du but.
Timothy C. Quinn
19

N'ajoutez pas l'en-tête Cci.

Voir ceci: http://mail.python.org/pipermail/email-sig/2004-September/000151.html

Et ceci: "" "Notez que le deuxième argument de sendmail (), les destinataires, est passé sous forme de liste. Vous pouvez inclure n'importe quel nombre d'adresses dans la liste pour que le message soit remis à chacun d'eux à tour de rôle. Depuis l'enveloppe les informations sont distinctes des en-têtes de message, vous pouvez même envoyer quelqu'un en BCC en l'incluant dans l'argument de la méthode mais pas dans l'en-tête du message. "" "de http://pymotw.com/2/smtplib

toaddr = '[email protected]'
cc = ['[email protected]','[email protected]']
bcc = ['[email protected]']
fromaddr = '[email protected]'
message_subject = "disturbance in sector 7"
message_text = "Three are dead in an attack in the sewers below sector 7."
message = "From: %s\r\n" % fromaddr
    + "To: %s\r\n" % toaddr
    + "CC: %s\r\n" % ",".join(cc)
    # don't add this, otherwise "to and cc" receivers will know who are the bcc receivers
    # + "BCC: %s\r\n" % ",".join(bcc)
    + "Subject: %s\r\n" % message_subject
    + "\r\n" 
    + message_text
toaddrs = [toaddr] + cc + bcc
server = smtplib.SMTP('smtp.sunnydale.k12.ca.us')
server.set_debuglevel(1)
server.sendmail(fromaddr, toaddrs, message)
server.quit()
Leonardo Andrade
la source
Bravo pour le flair: D
Chris
19

Depuis Python 3.2, publié en novembre 2011, le smtplib a une nouvelle fonction send_messageau lieu de juste sendmail, ce qui facilite le traitement de To / CC / BCC. En tirant des exemples d'e-mails officiels de Python , avec quelques légères modifications, nous obtenons:

# Import smtplib for the actual sending function
import smtplib

# Import the email modules we'll need
from email.message import EmailMessage

# Open the plain text file whose name is in textfile for reading.
with open(textfile) as fp:
    # Create a text/plain message
    msg = EmailMessage()
    msg.set_content(fp.read())

# me == the sender's email address
# you == the recipient's email address
# them == the cc's email address
# they == the bcc's email address
msg['Subject'] = 'The contents of %s' % textfile
msg['From'] = me
msg['To'] = you
msg['Cc'] = them
msg['Bcc'] = they


# Send the message via our own SMTP server.
s = smtplib.SMTP('localhost')
s.send_message(msg)
s.quit()

L'utilisation des en-têtes fonctionne correctement , car send_message respecte BCC comme indiqué dans la documentation :

send_message ne transmet aucun en-tête Bcc ou Resent-Bcc pouvant apparaître dans msg


Avec sendmailil était courant d'ajouter les en-têtes CC au message, en faisant quelque chose comme:

msg['Bcc'] = blind.email@adrress.com

Ou

msg = "From: [email protected]" +
      "To: [email protected]" +
      "BCC: [email protected]" +
      "Subject: You've got mail!" +
      "This is the message body"

Le problème est que la fonction sendmail traite tous ces en-têtes de la même manière, ce qui signifie qu'ils seront envoyés (visiblement) à tous les utilisateurs To: et BCC:, ce qui va à l'encontre des objectifs de BCC. La solution, comme indiqué dans de nombreuses autres réponses ici, était de ne pas inclure BCC dans les en-têtes, mais uniquement dans la liste des e-mails passés à sendmail.

La mise en garde est que cela send_messagenécessite un objet Message, ce qui signifie que vous devrez importer une classe depuis email.messageau lieu de simplement passer des chaînes dans sendmail.


la source
2
Je viens de vérifier que send_message (msg) gère les cc ajoutés à EmailMessage - msg ['Cc'] Si vous utilisez Python 3, c'est la voie à suivre.
bmiller
@bmiller Yup, assez pratique. J'ai écrit cette réponse parce que je la recherchais et que je trouvais le moyen le plus simple dans la documentation et d'autres références, et cela a bien fonctionné pour moi, et j'ai pensé que cela méritait une place ici car beaucoup de gens regarderont ici en premier.
non seulement je trouve cette solution plus élégante mais elle fonctionne parfaitement. Cela résout également un problème que j'ai eu avec la réponse de @ABentSpoon, qui est que pour les adresses gmail en CC, les e-mails n'allaient pas dans la boîte de réception mais dans "All Mail" à la place.
Guillaume Garrigos le
18

La distinction entre TO, CC et BCC ne se produit que dans les en-têtes de texte. Au niveau SMTP, tout le monde est un destinataire.

TO - Il y a un en-tête TO: avec l'adresse de ce destinataire

CC - Il y a un en-tête CC: avec l'adresse de ce destinataire

BCC - Ce destinataire n'est pas du tout mentionné dans les en-têtes, mais reste un destinataire.

Si tu as

TO: abc@company.com
CC: xyz@company.com
BCC: boss@company.com

Vous avez trois destinataires. Les en-têtes dans le corps de l'e-mail comprendront uniquement le TO: et le CC:

Jim Garrison
la source
16

Vous pouvez essayer MIMEText

msg = MIMEText('text')
msg['to'] = 
msg['cc'] = 

puis envoyez msg.as_string ()

https://docs.python.org/3.6/library/email.examples.html

éclosion
la source
4
cet exemple n'utilise pas CC
hoju
1
Je reconnais que les exemples sur le lien ci-dessus ne traitent pas Cci. C'est probablement ce que @hoju voulait dire.
Shailen
5

Cela n'a pas fonctionné pour moi jusqu'à ce que je crée:

#created cc string
cc = ""someone@domain.com;
#added cc to header
msg['Cc'] = cc

et que le cc ajouté dans le destinataire [liste] comme:

s.sendmail(me, [you,cc], msg.as_string())
marko_b123
la source
2

Aucune des choses ci-dessus n'a fonctionné pour moi car j'avais plusieurs destinataires à la fois en «to» et en «cc». J'ai donc essayé comme ci-dessous:

recipients = ['[email protected]', '[email protected]']
cc_recipients = ['[email protected]', '[email protected]']
MESSAGE['To'] = ", ".join(recipients)
MESSAGE['Cc'] = ", ".join(cc_recipients)

et étendez les 'destinataires' avec 'cc_recipients' et envoyez du courrier de manière triviale

recipients.extend(cc_recipients)
server.sendmail(FROM,recipients,MESSAGE.as_string())
Chan Gaikwad
la source