python smtplib을 사용하여 여러 수신자에게 이메일을 보내는 방법은 무엇입니까?


198

많은 검색을 한 후 smtplib.sendmail을 사용하여 여러 수신자에게 보내는 방법을 찾을 수 없었습니다. 문제는 메일을 보낼 때마다 메일 헤더에 여러 주소가 포함 된 것처럼 보이지만 실제로는 첫 번째 수신자 만 전자 메일을받습니다.

문제는 email.Message모듈이 다른 것과 다른 것을 기대 하는 것 같습니다smtplib.sendmail() 기능 .

즉, 여러 수신자에게 보내려면 헤더를 쉼표로 구분 된 전자 메일 주소 문자열로 설정해야합니다. sendmail()매개 변수는 to_addrs그러나 이메일 주소의 목록이어야합니다.

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
OP가 자신의 질문에 답변 한 것으로 보입니다 sendmail. 목록이 필요합니다.
— Cees Timmerman


Python3을 사용하여 수신자를 반복해야했습니다. for addr in recipients: msg['To'] = addr그런 다음 효과가있었습니다. 여러 할당은 실제로 각각에 새로운 'To'헤더를 추가합니다. 이것은 매우 기이 한 인터페이스이며, 어떻게 시도했는지 설명조차 할 수 없습니다. 나는 이것을 이해하기 전에 subprocess유닉스 sendmail를 절약하기 위해 유닉스 패키지 를 호출하는 것을 고려 하고있었습니다.
— mehtunguh

답변:


312

이것은 실제로 작동합니다 . 여러 변형을 시도하는 데 많은 시간을 보냈습니다.

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

3
문서에 예가 있습니다.tolist =["one@one.org","two@two.org","three@three.org","four@four.org"]
— chug2k

2
이 스크립트에 대해 @sorin에게 감사합니다. 파이썬 스크립트에서 이메일을 보내는 데 문제가 있었고이 코드로 이메일을 보낼 수 있습니다.
— fear_matrix

5
아래의 Antoine의 의견과 파이썬 문서 docs.python.org/3/library/email-examples.htmlsend_messagesendmail
— cardamom

sendmail의 수신자가 각 트래버스에 사용해야합니다. 그렇지 않으면 첫 번째 요소 만 메일을받습니다.
— Johnny

2
위에서 언급 한 URL 수정 : docs.python.org/3/library/email.examples.html
— David

151

은 msg['To']문자열이어야합니다 :

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

recipientsin sendmail(sender, recipients, message)은 목록이어야 하지만 :

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

1
이것은 하나의 이상한 디자인 결정입니다smtplib.
— Adam Matan

2
recipients목록이 될 필요는 없습니다. 문자열이 제공되면 하나의 요소가있는 목록으로 취급됩니다. msg['To']문자열은 간단히 생략 할 수 있습니다.
— Suzana

나는 'a@a.com, b@b.com'이 어떻게 파싱되는지 이해하지 못하므로 첫 번째 주소 만 이메일을 가져옵니다. 그러나 감사합니다! 이것은 대답입니다. 거기에 목록을 넣어야했습니다.
— antonavy


44

이메일 의 보이는 주소와 배달 의 차이점을 이해해야합니다 .

msg["To"]본질적으로 편지에 인쇄되어 있습니다. 실제로 아무런 영향을 미치지 않습니다. 전자 우편 클라이언트는 정규 우체국과 마찬가지로 전자 우편을 보낼 사람이라고 가정합니다.

그러나 실제 배송은 상당히 다를 수 있습니다. 그래서 당신 은 할 수 있습니다 이메일 (또는 사본)을 완전히 다른 사람의 포스트 박스에 .

여기에는 여러 가지 이유가 있습니다. 예를 들어 전달 . 그만큼To:헤더 필드가 전달에 변경되지 않습니다, 그러나 이메일은 다른 사서함으로 삭제됩니다.

이 smtp.sendmail명령은 이제 실제 배달을 처리합니다.email.Message배달 내용이 아닌 문자의 내용입니다.

하위 수준 SMTP에서는 수신자에게 하나씩 하나씩 제공해야하므로 주소 목록 (이름 제외)이 합리적인 API입니다.

헤더의 경우 예를 들어 이름을 포함 할 수도 있습니다 To: First Last <email@addr.tld>, Other User <other@mail.tld>. 따라서 코드 예제는 메일을 분할 ,하지 않아도 유효한 주소가 없기 때문에이 메일을 전달 하지 못하므로 권장 하지 않습니다!


2
RFC 2822는 지정된 헤더에 최대 너비 988 자, 권장 너비 78 자입니다. 주소가 너무 많으면 헤더를 "접습니다".
— Steve Hunt

실제로 그 이유와 방법을 설명하므로 허용되는 답변이어야합니다.
— Serrano

좋은 대답입니다. CC 및 BCC 이메일 필드는 어떻습니까? smtp.send에 CC 및 BCC 이메일도 포함시켜야한다고 가정합니다. 그리고 msg 필드에 CC 목록 만 (BCC 목록은 아님)?
— Tagar

예, 그것이 작동하는 방식입니다. 메일 서버는 BCC 필드를 제거 할 가능성이 있지만 (이것은 보이지 않으며 모두 그렇게 생각하지는 않습니다) 파싱하지는 않습니다.
— Anony - 무스 - 종료 될

19

그것은 나를 위해 작동합니다.

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

어떤 버전의 파이썬을 사용하고 있습니까? 나는 원래 포스터와 같은 문제를 겪고 있고 나는 파이썬 2.7.9
— panofish를

1
단순히 recipients = ['john.doe@example.com','john.smith@example.co.uk']문자열을 만드는 대신 목록을 만들기 위해 분할하는 것이 어떻습니까?
— WoJ

msg [ 'To']는 문자열이어야하고 s.sendmail은 (sender, >>> LIST HERE <<<, msg.as_string ())리스트를 가져야하기 때문에 Woj에게 전달됩니다. 보이는 짜증나는만큼 그것은 당신이 두 필드에 대해 하나 개의 동일한 유형 [문자열이나 목록]을 사용할 수 없습니다, 수단이다
— 파스칼 루이 마리

나를 위해 매력처럼 작동합니다. 파이썬 3.7.3.
— Anadyn

11

나는 아래를 시도했고 그것은 매력처럼 일했다 :)

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

FYR 전체 간단한 코드는 다음과 같습니다. import smtplib from email.mime.multipart import MIMEMultipart from email.mime.text import MIMEText sender = 'myEmailAddress@example.com' rec_list = ['first@example.com', 'second@example.com'] rec = ', '.join(rec_list) msg = MIMEMultipart('alternative') msg['Subject'] = 'The required subject' msg['From'] = sender msg['To'] = rec html = ('whatever html code') htm_part = MIMEText(html, 'html') msg.attach(htm_part) send_out = smtplib.SMTP('localhost') send_out.sendmail(sender, rec_list, msg.as_string()) send_out.quit()
— MasterMind

10

실제로 문제는 SMTP.sendmail과 email.MIMEText가 두 가지 다른 것이 필요하다는 것입니다.

email.MIMEText는 이메일 본문에 대한 "To :"헤더를 설정합니다. 사람에게 결과를 다른 쪽 끝에 표시하는 데만 사용되며 모든 전자 메일 헤더와 마찬가지로 단일 문자열이어야합니다. (실제로 메시지를받는 사람들과 관련이있을 필요는 없습니다.)

반면에 SMTP.sendmail은 SMTP 프로토콜에 대한 메시지의 "봉투"를 설정합니다. 파이썬의 문자열 목록이 필요하며 각 문자열에는 단일 주소가 있습니다.

따라서 귀하가해야 할 일은받은 두 개의 회신을 결합하는 것입니다. msg [ 'To']를 단일 문자열로 설정하지만 원시 목록을 sendmail에 전달하십시오.

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

7

이 수입 가능한 모듈 기능을 생각해 냈습니다. 이 예에서는 Gmail 이메일 서버를 사용합니다. 헤더와 메시지로 나뉘어 진행 상황을 명확하게 볼 수 있습니다.

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

7

나는 이것을 몇 달 전에 알아 냈고 그것에 대해 블로그를 작성했습니다. . 요약은 다음과 같습니다.

smtplib를 사용하여 여러 수신자에게 이메일을 보내려면을 사용 email.Message.add_header('To', eachRecipientAsString)하여 추가 한 다음 sendmail 메소드를 호출 할 때 use email.Message.get_all('To')모든 수신자에게 메시지를 보내십시오. 참조 및 숨은 참조 수신자에게 적합합니다.


파이썬 3.7은 메시지와 함께 예외를 던졌습니다 : 예외가 발생했습니다 : ValueError 메시지 에 최대 1 개의 To 헤더가있을 수 있습니다
— Wojciech Jakubas

6

아래 솔루션이 저에게 효과적이었습니다. "CC"및 "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)

1
이것은 부분적으로 작동하며 숨은 참조를 숨기려면 숨은 참조 줄을 생략해야합니다. bcc = [ 'mailid_5', 'mailid_6'] 그렇지 않으면 헤더에 숨은 참조가 bcc의 목적을 무너 뜨립니다. Gmail 및 기타 메일 서버에서 테스트되었습니다.
— Wil

@이 경우 어떻게 BCC를 구현할 것입니까?
— 3pitt

4

글쎄, 이 asnwer 방법의 방법은 저에게 효과적이지 않았습니다. 모르겠습니다. 아마도 이것이 Python3 (3.4 버전을 사용하고 있습니다) 또는 gmail 관련 문제 일지 모르지만 일부 시도 후에 나에게 도움이되는 해결책은 줄이었습니다.

s.send_message(msg)

대신에

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

4

파이썬 3.6을 사용하고 다음 코드가 저에게 효과적입니다.

email_send = 'xxxxx@xxx.xxx,xxxx@xxx.xxx'
server.sendmail(email_user,email_send.split(','),text)    

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

send_message 함수와 python 3.6 수신자 목록에서 join 함수를 사용하여 나에게만 효과가있었습니다.


0

당신은 텍스트 파일에 recpient 이메일을 쓸 때 이것을 시도 할 수 있습니다

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')
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.