python: como enviar e-mail com TO, CC e BCC?

102

Eu preciso, para fins de teste, preencher algumas centenas de caixas de e-mail com várias mensagens e usaria smtplib para isso. Mas, entre outras coisas, preciso ser capaz de enviar mensagens não apenas para caixas de correio específicas, mas também em CC e em BCC. Não parece que o smtplib suporta CC-ing e BCC-ing ao enviar e-mails.

Procurando por sugestões de como enviar mensagens CC ou BCC a partir do script python.

(E - não, não estou criando um script para enviar spam para ninguém fora do meu ambiente de teste.)

user63503
fonte

Respostas:

150

Os cabeçalhos de e-mail não importam para o servidor SMTP. Basta adicionar os destinatários CC e BCC aos toaddrs ao enviar seu e-mail. Para CC, adicione-os ao cabeçalho 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
fonte
smtplib.SMTP não envia listas de endereços. Pelo menos não no python 2.7.2
LostMohican
Nesse caso, o cabeçalho BCC mencionado no RFC 2822 não faz sentido.
Chenxiong Qi
1
@ABentSpoon faltam dois pontos depois de 'Assunto'.
user891260
3
Não adicione o cabeçalho Cco. Veja isto: mail.python.org/pipermail/email-sig/2004-September/000151.html E isto: "" "Observe que o segundo argumento para sendmail (), os destinatários, é passado como uma lista. Você pode incluir qualquer número de endereços na lista para que a mensagem seja entregue a cada um deles por vez. Como as informações do envelope são separadas dos cabeçalhos da mensagem, você pode até mesmo enviar uma pessoa para BCC incluindo-a no argumento do método, mas não no cabeçalho da mensagem. " "" de pymotw.com/2/smtplib
Leonardo Andrade
2
Isso nunca será BCC ou CC - sempre será To
ProsperousHeart
37

O principal é adicionar os destinatários como uma lista de ids de e-mail em sua chamada 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()
Helios
fonte
4
Deixe o msg['BCC']desligado - ele revela seu remetente oculto e não tem impacto sobre se a mensagem é enviada a eles ou não (os argumentos para sendmailisso).
Erica Kane,
2
Eu concordo com a Erica e o Julio. A intenção do Bcc é ocultar o receptor para outros receptores. Se estiver na mensagem, isso vai contra o propósito.
Timothy C. Quinn
19

Não adicione o cabeçalho Cco.

Veja isto: http://mail.python.org/pipermail/email-sig/2004-September/000151.html

E isto: "" "Observe que o segundo argumento para sendmail (), os destinatários, é passado como uma lista. Você pode incluir qualquer número de endereços na lista para que a mensagem seja entregue a cada um deles por vez. Desde o envelope as informações são separadas dos cabeçalhos das mensagens, você pode até mesmo enviar uma pessoa para BCC incluindo-os no argumento do método, mas não no cabeçalho da mensagem. "" "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
fonte
Perfeito para tal: D
Chris
19

A partir do Python 3.2, lançado em novembro de 2011, o smtplib tem uma nova função em send_messagevez de apenas sendmail, o que torna mais fácil lidar com To / CC / BCC. Pegando os exemplos de e-mail oficial do Python , com algumas pequenas modificações, obtemos:

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

Usar os cabeçalhos funciona bem, porque send_message respeita BCC conforme descrito na documentação :

send_message não transmite quaisquer cabeçalhos Bcc ou Resent-Bcc que possam aparecer na msg


Com sendmailisso era comum adicionar cabeçalhos CC à mensagem, fazendo algo como:

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"

O problema é que a função sendmail trata todos os cabeçalhos da mesma forma, o que significa que eles serão enviados (visivelmente) para todos os usuários Para: e BCC: frustrando os propósitos do BCC. A solução, conforme mostrado em muitas das outras respostas aqui, foi não incluir BCC nos cabeçalhos e, em vez disso, apenas na lista de e-mails passados ​​parasendmail .

A ressalva é que send_messagerequer um objeto Message, o que significa que você precisará importar uma classe de em email.messagevez de apenas passar strings para sendmail.


fonte
2
Acabei de verificar se send_message (msg) lida com os cc adicionados a EmailMessage - msg ['Cc'] Se você estiver usando Python 3, este é o caminho a seguir.
bmiller
@bmiller Sim, bastante útil. Escrevi esta resposta porque estava pesquisando e encontrei a maneira mais simples nos documentos e outros refs, e funcionou bem para mim, e achei que merecia um lugar aqui, já que muitas pessoas olharão aqui primeiro.
além de achar esta solução mais elegante, ela funciona perfeitamente. Também resolve um problema que tive com a resposta de @ABentSpoon, que para os endereços do gmail em CC, os e-mails não iam para a caixa de entrada, mas para "Todos os e-mails".
Guillaume Garrigos
18

A distinção entre TO, CC e BCC ocorre apenas nos cabeçalhos do texto. No nível SMTP, todos são destinatários.

TO - Há um cabeçalho TO: com o endereço deste destinatário

CC - há um cabeçalho CC: com o endereço deste destinatário

BCC - Este destinatário não é mencionado nos cabeçalhos, mas ainda é um destinatário.

Se você tem

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

Você tem três destinatários. Os cabeçalhos no corpo do e-mail incluirão apenas o PARA: e o CC:

Jim Garrison
fonte
16

Você pode tentar o MIMEText

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

então envie msg.as_string ()

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

Foosion
fonte
4
esse exemplo não usa CC
hoju
1
Concordo que os exemplos no link acima não tratam Bcc. Isso é o que provavelmente @hoju significava.
Shailen
5

Não funcionou para mim até que criei:

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

e então adicionou cc no destinatário [lista] como:

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

Nenhuma das coisas acima funcionou para mim, pois eu tinha vários destinatários em 'para' e 'cc'. Então, tentei como abaixo:

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

e estender os 'destinatários' com 'cc_recipients' e enviar e-mail de forma trivial

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