จะส่งอีเมลด้วย Python ได้อย่างไร


169

รหัสนี้ใช้งานได้และส่งอีเมลถึงฉัน:

import smtplib
#SERVER = "localhost"

FROM = 'monty@python.com'

TO = ["jon@mycompany.com"] # must be a list

SUBJECT = "Hello!"

TEXT = "This message was sent with Python's smtplib."

# Prepare actual message

message = """\
From: %s
To: %s
Subject: %s

%s
""" % (FROM, ", ".join(TO), SUBJECT, TEXT)

# Send the mail

server = smtplib.SMTP('myserver')
server.sendmail(FROM, TO, message)
server.quit()

อย่างไรก็ตามถ้าฉันพยายามปิดมันในฟังก์ชั่นแบบนี้:

def sendMail(FROM,TO,SUBJECT,TEXT,SERVER):
    import smtplib
    """this is some test documentation in the function"""
    message = """\
        From: %s
        To: %s
        Subject: %s
        %s
        """ % (FROM, ", ".join(TO), SUBJECT, TEXT)
    # Send the mail
    server = smtplib.SMTP(SERVER)
    server.sendmail(FROM, TO, message)
    server.quit()

และเรียกว่าฉันได้รับข้อผิดพลาดต่อไปนี้:

 Traceback (most recent call last):
  File "C:/Python31/mailtest1.py", line 8, in <module>
    sendmail.sendMail(sender,recipients,subject,body,server)
  File "C:/Python31\sendmail.py", line 13, in sendMail
    server.sendmail(FROM, TO, message)
  File "C:\Python31\lib\smtplib.py", line 720, in sendmail
    self.rset()
  File "C:\Python31\lib\smtplib.py", line 444, in rset
    return self.docmd("rset")
  File "C:\Python31\lib\smtplib.py", line 368, in docmd
    return self.getreply()
  File "C:\Python31\lib\smtplib.py", line 345, in getreply
    raise SMTPServerDisconnected("Connection unexpectedly closed")
smtplib.SMTPServerDisconnected: Connection unexpectedly closed

ใครช่วยฉันเข้าใจว่าทำไม


2
คุณเรียกฟังก์ชั่นนี้ได้อย่างไร?
Jochen Ritzel

การเยื้องที่คุณโพสต์เหมือนกับที่คุณมีในไฟล์ของคุณหรือไม่
gddc

@ gddc ไม่ฉันทำให้แน่ใจว่าได้เยื้องอย่างถูกต้องนั่นเป็นเพียงวิธีที่ฉันวางไว้ในนั้น
cloud311

ฉันเรียกใช้ฟังก์ชั่นโดยนำเข้าสู่โมดูลหลักของฉันและส่งผ่านพารามิเตอร์ที่ฉันกำหนดไว้
cloud311

4
แม้ว่าคำแนะนำของ @ Arrieta ในการใช้แพคเกจอีเมลเป็นวิธีที่ดีที่สุดในการแก้ปัญหานี้แนวทางของคุณก็สามารถใช้งานได้ ความแตกต่างระหว่างสองเวอร์ชันของคุณอยู่ในสตริง: (1) เนื่องจาก @NickODell ชี้ให้เห็นว่าคุณมีช่องว่างนำหน้าในเวอร์ชันฟังก์ชั่น ส่วนหัวไม่ควรมีช่องว่างนำหน้า (เว้นเสีย แต่จะถูกห่อหุ้ม) (2) เว้นเสียแต่ว่า TEXT จะมีบรรทัดว่างนำหน้าคุณสูญเสียตัวคั่นระหว่างส่วนหัวและเนื้อความ
Tony Meyer

คำตอบ:


191

ฉันแนะนำให้คุณใช้แพ็คเกจมาตรฐานemailและsmtplibรวมกันเพื่อส่งอีเมล โปรดดูตัวอย่างต่อไปนี้ (ทำซ้ำจากเอกสาร Python ) ขอให้สังเกตว่าถ้าคุณทำตามวิธีนี้งาน "ง่าย" นั้นง่ายมากและงานที่ซับซ้อนมากขึ้น (เช่นการแนบวัตถุไบนารีหรือการส่งข้อความธรรมดา / HTML หลายส่วน) ทำได้สำเร็จอย่างรวดเร็ว

# Import smtplib for the actual sending function
import smtplib

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

# Open a plain text file for reading.  For this example, assume that
# the text file contains only ASCII characters.
with open(textfile, 'rb') as fp:
    # Create a text/plain message
    msg = MIMEText(fp.read())

# me == the sender's email address
# you == the recipient's email address
msg['Subject'] = 'The contents of %s' % textfile
msg['From'] = me
msg['To'] = you

# Send the message via our own SMTP server, but don't include the
# envelope header.
s = smtplib.SMTP('localhost')
s.sendmail(me, [you], msg.as_string())
s.quit()

สำหรับการส่งอีเมลไปยังปลายทางหลายแห่งคุณสามารถทำตามตัวอย่างในเอกสาร Python :

# Import smtplib for the actual sending function
import smtplib

# Here are the email package modules we'll need
from email.mime.image import MIMEImage
from email.mime.multipart import MIMEMultipart

# Create the container (outer) email message.
msg = MIMEMultipart()
msg['Subject'] = 'Our family reunion'
# me == the sender's email address
# family = the list of all recipients' email addresses
msg['From'] = me
msg['To'] = ', '.join(family)
msg.preamble = 'Our family reunion'

# Assume we know that the image files are all in PNG format
for file in pngfiles:
    # Open the files in binary mode.  Let the MIMEImage class automatically
    # guess the specific image type.
    with open(file, 'rb') as fp:
        img = MIMEImage(fp.read())
    msg.attach(img)

# Send the email via our own SMTP server.
s = smtplib.SMTP('localhost')
s.sendmail(me, family, msg.as_string())
s.quit()

อย่างที่คุณเห็นส่วนหัวToในMIMETextวัตถุจะต้องเป็นสตริงที่ประกอบด้วยที่อยู่อีเมลคั่นด้วยเครื่องหมายจุลภาค ในทางกลับกันอาร์กิวเมนต์ที่สองของsendmailฟังก์ชันจะต้องเป็นรายการสตริง (แต่ละสตริงคือที่อยู่อีเมล)

ดังนั้นถ้าคุณมีสามที่อยู่อีเมล: person1@example.com, person2@example.comและperson3@example.comคุณสามารถทำดังต่อไปนี้ (ส่วนที่เห็นได้ชัดละเว้น):

to = ["person1@example.com", "person2@example.com", "person3@example.com"]
msg['To'] = ",".join(to)
s.sendmail(me, to, msg.as_string())

",".join(to)ส่วนหนึ่งที่ทำให้สายเดียวจากรายการคั่นด้วยเครื่องหมายจุลภาค

จากคำถามของคุณฉันรวบรวมว่าคุณยังไม่ได้ผ่านการสอน Python - มันเป็นสิ่งที่จำเป็นถ้าคุณต้องการที่จะไปไหนมาไหนใน Python - เอกสารส่วนใหญ่นั้นยอดเยี่ยมสำหรับไลบรารี่มาตรฐาน


1
ขอบคุณสิ่งนี้ทำงานได้ดีมากจากภายในฟังก์ชั่น แต่ฉันจะส่งไปยังผู้รับหลายคนได้อย่างไร เนื่องจาก msg [ถึง] ดูเหมือนว่าเป็นคีย์พจนานุกรมฉันจึงพยายามแยก msg [เป็น] ด้วยเครื่องหมายอัฒภาค แต่ดูเหมือนจะไม่ทำงาน
cloud311

1
@ cloud311 เหมือนกับที่คุณมีในรหัส มันต้องการสตริงที่คั่นด้วยเครื่องหมายจุลภาค: ", ".join(["a@example.com", "b@example.net"])
Tim McNamara

3
โปรดทราบว่าส่วนหัวถึง: มีความหมายที่แตกต่างจากผู้รับซองจดหมาย ตัวอย่างเช่นคุณสามารถใช้ "" Tony Meyer "<tony.meyer@gmail.com> 'เป็นที่อยู่ในส่วนหัวถึง: แต่ผู้รับซองจดหมายต้องเป็น" tony.meyer@gmail.com "เท่านั้น ในการสร้างที่อยู่ 'ดี' ถึง: ใช้ email.utils.formataddr เช่น email.utils.formataddr ("Tony Meyer", "tony.meyer@gmail.com")
Tony Meyer

1
การปรับปรุงเล็กน้อยwith: ควรเปิดไฟล์โดยใช้: with open(textfile, 'rb') as fp:. การปิดที่ชัดเจนสามารถถูกทิ้งเนื่องจากwithบล็อกจะปิดไฟล์แม้ว่าจะมีข้อผิดพลาดเกิดขึ้นภายในก็ตาม
jpmc26

1
ไม่เฉพาะคำตอบนี้ แต่เมื่อเชื่อมต่อกับเซิร์ฟเวอร์ SMTP ใด ๆ ที่คุณไม่ได้ควบคุมคุณควรพิจารณาความเป็นไปได้ว่ามันไม่สามารถเข้าถึงได้ช้าปฏิเสธการเชื่อมต่อหรือสิ่งอื่นใด คุณควรได้รับข้อยกเว้น แต่คุณต้องหาวิธีที่จะลองส่งอีกครั้งในภายหลัง หากคุณพูดคุยกับ sendmail / postfix ของคุณเองมันจะดูแลการส่งให้คุณอีกครั้ง
Ralph Bolton

66

คุณต้องการคำตอบที่ทันสมัยและทันสมัย

นี่คือคำตอบของฉัน:

เมื่อฉันต้องการส่งเมลด้วย python ฉันใช้mailgun API ซึ่งมีจำนวนมากที่ปวดหัวกับการส่งเมลที่แยกออก พวกเขามีแอพพลิเคชั่น / api ที่ยอดเยี่ยมที่ช่วยให้คุณส่งอีเมล 10,000 ฉบับต่อเดือนฟรี

การส่งอีเมลจะเป็นเช่นนี้:

def send_simple_message():
    return requests.post(
        "https://api.mailgun.net/v3/YOUR_DOMAIN_NAME/messages",
        auth=("api", "YOUR_API_KEY"),
        data={"from": "Excited User <mailgun@YOUR_DOMAIN_NAME>",
              "to": ["bar@example.com", "YOU@YOUR_DOMAIN_NAME"],
              "subject": "Hello",
              "text": "Testing some Mailgun awesomness!"})

นอกจากนี้คุณยังสามารถติดตามกิจกรรมและอื่น ๆ อีกมากมายดูคู่มือการเริ่มด่วน

ฉันหวังว่าคุณจะพบว่ามีประโยชน์นี้!


3
นี่คือ "วันนี้" ที่มากขึ้นอย่างแน่นอน แม้ว่ามันจะใช้ API ภายนอก โดยส่วนตัวฉันจะใช้บางอย่างเช่นyagmailเพื่อให้อยู่ภายใน
PascalVKooten

6
@PascalvKooten สนุกแน่นอนที่จะติดตาม yagmail ของคุณอย่างต่อเนื่อง (ใช่ครับฉันจะพิจารณาอีกครั้งนะครับ;) แต่ฉันพบว่ามันสับสนมากที่เกือบจะไม่มีใครสนใจปัญหา OP แต่แนะนำวิธีแก้ไขที่แตกต่างกัน มันเหมือนกับว่าฉันกำลังถามวิธีการเปลี่ยนหลอดไฟในสมาร์ท 2009 ของฉันและคำตอบคือ: ซื้อ Mercedes จริง ...
flaschbier

เยี่ยมมากที่ภารกิจของฉันมีค่าความสนุกสำหรับบางคน
PascalVKooten

4
@flaschbier เหตุผลที่ไม่มีใครสนใจเกี่ยวกับปัญหา OPs เพราะชื่อผิด "วิธีส่งอีเมลด้วย Python ได้อย่างไร" เป็นเหตุผลที่แท้จริงที่ผู้คนมาดูเมื่อพวกเขาคลิกคำถามนั้นและพวกเขาคาดหวังคำตอบที่yagmailสามารถให้ได้: ดีและสั้น ไปแล้ว โฆษณา yagmail เพิ่มเติม
PascalVKooten

1
เพียงเพื่อบอกว่าสำหรับลูกค้า Mailgun การส่งจดหมายทางเว็บเซอร์วิซนั้นง่ายกว่าแบนด์วิดท์มากกว่าทาง SMTP (โดยเฉพาะถ้าใช้สิ่งที่แนบมา)
Ralph Bolton

44

ฉันต้องการช่วยคุณส่งอีเมลโดยแนะนำแพ็คเกจ yagmail (ฉันเป็นผู้ดูแลขออภัยในการโฆษณา แต่ฉันรู้สึกว่ามันช่วยได้จริงๆ!)

รหัสทั้งหมดสำหรับคุณจะเป็น:

import yagmail
yag = yagmail.SMTP(FROM, 'pass')
yag.send(TO, SUBJECT, TEXT)

โปรดทราบว่าฉันให้ค่าเริ่มต้นสำหรับการขัดแย้งทั้งหมดเช่นถ้าคุณต้องการส่งถึงตัวคุณเองคุณสามารถละเว้นTOหากคุณไม่ต้องการหัวเรื่องคุณสามารถละเว้นได้

นอกจากนี้เป้าหมายคือเพื่อให้ง่ายต่อการแนบรหัส html หรือภาพ (และไฟล์อื่น ๆ )

คุณใส่เนื้อหาที่คุณสามารถทำสิ่งที่ชอบ:

contents = ['Body text, and here is an embedded image:', 'http://somedomain/image.png',
            'You can also find an audio file attached.', '/local/path/song.mp3']

ว้าวมันง่ายแค่ไหนในการส่งไฟล์แนบ! การดำเนินการนี้จะมี 20 บรรทัดที่ไม่มี yagmail;)

นอกจากนี้หากคุณตั้งค่าครั้งเดียวคุณจะไม่ต้องป้อนรหัสผ่านอีกครั้ง (และเก็บไว้อย่างปลอดภัย) ในกรณีของคุณคุณสามารถทำสิ่งที่ชอบ:

import yagmail
yagmail.SMTP().send(contents = contents)

ซึ่งกระชับกว่านี้มาก!

ผมอยากเชิญชวนให้คุณได้ดูที่GitHubpip install yagmailหรือติดตั้งโดยตรงกับ


4
นี่ควรเป็นทางออกอันดับต้น ๆ
Richard de Ree

1
OMG นั่นเป็นโมดูลอีเมลที่เรียบง่ายและแสนหวาน ขอบคุณ!
pepoluan

1
ฉันสามารถใช้yagmailอื่นที่ไม่ใช่ gmail ได้ไหม? ฉันพยายามใช้สำหรับเซิร์ฟเวอร์ SMTP ของฉันเอง
Anirban Nag 'tintinmj'

@dtgq ขอบคุณสำหรับความกังวลของคุณ โดยส่วนตัวฉันไม่เห็นเวกเตอร์การโจมตี หากใครบางคนกำลังจะเปลี่ยนไฟล์ภายใต้เส้นทางที่คุณต้องการส่งมันไม่สำคัญว่าคุณจะมีAttachmentคลาสหรือไม่ มันยังคงเป็นสิ่งเดียวกัน หากพวกเขาสามารถเปลี่ยนรหัสของคุณพวกเขาก็สามารถทำสิ่งที่พวกเขาต้องการได้ (โดยมี / ไม่มีรูทนั่นคือการส่งอีเมล wrt เดียวกัน) ดูเหมือนว่าฉันจะชอบแบบทั่วไป "สะดวกสบาย / น่าอัศจรรย์ดังนั้นจึงต้องปลอดภัยน้อยกว่า" ฉันอยากรู้ว่าภัยคุกคามที่แท้จริงที่คุณเห็นคืออะไร?
PascalVKooten

14

มีปัญหาการเยื้อง รหัสด้านล่างจะใช้งานได้:

import textwrap

def sendMail(FROM,TO,SUBJECT,TEXT,SERVER):
    import smtplib
    """this is some test documentation in the function"""
    message = textwrap.dedent("""\
        From: %s
        To: %s
        Subject: %s
        %s
        """ % (FROM, ", ".join(TO), SUBJECT, TEXT))
    # Send the mail
    server = smtplib.SMTP(SERVER)
    server.sendmail(FROM, TO, message)
    server.quit()


3
@geotheory SERVERตัวแปรที่ส่งผ่านไปยังฟังก์ชันคือหนังสือรับรองผู้ใช้
ผู้ใช้

ไม่แนะนำให้ใช้การรวมข้อความ SMTP ที่ถูกต้องพร้อมการแก้ไขสตริงอย่างง่ายด้วยตนเองและคำตอบของคุณมีข้อบกพร่องซึ่งแสดงให้เห็นอย่างสมบูรณ์แบบนี้ (เนื้อความต้องเริ่มต้นด้วยบรรทัดว่างเพื่อให้เป็นข้อความที่ถูกต้อง) สำหรับสิ่งที่เกี่ยวข้องกับชุดอักขระอื่นนอกเหนือจากข้อความธรรมดาในปี 1980 7 บิต US-ASCII ภาษาอังกฤษเท่านั้นสหรัฐอเมริกา ASCII (สิ่งที่แนบมาเป็นสากลและการสนับสนุน MIME อื่น ๆ ) จริงๆต้องการที่จะใช้ห้องสมุดซึ่งมีหน้าที่จัดการสิ่งนี้ emailไลบรารีPython ทำได้ดีพอสมควร (โดยเฉพาะอย่างยิ่งตั้งแต่ 3.6) แต่ก็ยังต้องการความเข้าใจในสิ่งที่คุณทำอยู่
tripleee

7

นี่คือตัวอย่างของ Python 3.xซึ่งง่ายกว่า2.x:

import smtplib
from email.message import EmailMessage
def send_mail(to_email, subject, message, server='smtp.example.cn',
              from_email='xx@example.com'):
    # import smtplib
    msg = EmailMessage()
    msg['Subject'] = subject
    msg['From'] = from_email
    msg['To'] = ', '.join(to_email)
    msg.set_content(message)
    print(msg)
    server = smtplib.SMTP(server)
    server.set_debuglevel(1)
    server.login(from_email, 'password')  # user & password
    server.send_message(msg)
    server.quit()
    print('successfully sent the mail.')

เรียกใช้ฟังก์ชันนี้:

send_mail(to_email=['12345@qq.com', '12345@126.com'],
          subject='hello', message='Your analysis has done!')

ด้านล่างสำหรับผู้ใช้ภาษาจีนเท่านั้น:

หากคุณใช้ 126/163, 网易邮箱คุณต้องตั้งค่า "客户端授权密码" เช่นด้านล่าง:

ป้อนคำอธิบายรูปภาพที่นี่

ref: https://stackoverflow.com/a/41470149/2803344 https://docs.python.org/3/library/email.examples.html#email-examples


4

ขณะที่เยื้องรหัสของคุณในฟังก์ชั่น (ซึ่งก็โอเค) คุณก็เยื้องบรรทัดของสตริงข้อความดิบ แต่พื้นที่สีขาวนำหมายถึงการพับ (การต่อข้อมูล) ของบรรทัดส่วนหัวดังอธิบายในส่วน 2.2.3 และ 3.2.3 ของRFC 2822 - รูปแบบข้อความอินเทอร์เน็ต :

แต่ละฟิลด์ส่วนหัวเป็นอักขระบรรทัดเดียวที่มีเหตุผลซึ่งประกอบด้วยชื่อฟิลด์โคลอนและเนื้อความฟิลด์ อย่างไรก็ตามเพื่อความสะดวกและเพื่อจัดการกับข้อ จำกัด ของอักขระ 998/78 ต่อบรรทัดส่วนเนื้อหาของฟิลด์ของฟิลด์ส่วนหัวสามารถแบ่งออกเป็นการแสดงหลายบรรทัด สิ่งนี้เรียกว่า "การพับ"

ในรูปแบบฟังก์ชั่นการsendmailโทรของคุณทุกบรรทัดจะเริ่มต้นด้วย white space และดังนั้นจึงเป็น "unfolded" (เรียงต่อกัน) และคุณพยายามที่จะส่ง

From: monty@python.com    To: jon@mycompany.com    Subject: Hello!    This message was sent with Python's smtplib.

นอกเหนือจากความคิดของเราแนะนำsmtplibจะไม่เข้าใจTo:และSubject:ส่วนหัวอีกต่อไปเพราะชื่อเหล่านี้จะได้รับการยอมรับเพียงจุดเริ่มต้นของบรรทัด แต่smtplibจะถือว่าที่อยู่อีเมลของผู้ส่งยาวมาก:

monty@python.com    To: jon@mycompany.com    Subject: Hello!    This message was sent with Python's smtplib.

สิ่งนี้จะไม่ทำงานและข้อยกเว้นของคุณจะมาถึง

วิธีแก้ปัญหานั้นง่าย: เพียงรักษาmessageสตริงเหมือนเดิม สิ่งนี้สามารถทำได้โดยฟังก์ชั่น (ตามที่แนะนำ Zeeshan) หรือในซอร์สโค้ดทันที:

import smtplib

def sendMail(FROM,TO,SUBJECT,TEXT,SERVER):
    """this is some test documentation in the function"""
    message = """\
From: %s
To: %s
Subject: %s

%s
""" % (FROM, ", ".join(TO), SUBJECT, TEXT)
    # Send the mail
    server = smtplib.SMTP(SERVER)
    server.sendmail(FROM, TO, message)
    server.quit()

ตอนนี้การแฉจะไม่เกิดขึ้นและคุณส่ง

From: monty@python.com
To: jon@mycompany.com
Subject: Hello!

This message was sent with Python's smtplib.

สิ่งที่ทำงานและสิ่งที่ทำโดยรหัสเก่าของคุณ

โปรดทราบว่าฉันยังคงรักษาบรรทัดว่างไว้ระหว่างส่วนหัวและร่างกายเพื่อรองรับส่วน 3.5 ของRFC (ซึ่งจำเป็น) และวางการรวมภายนอกฟังก์ชันตามคู่มือสไตล์ Python PEP-0008 (ซึ่งเป็นทางเลือก)


3

มันอาจจะใส่แท็บในข้อความของคุณ พิมพ์ข้อความก่อนส่งผ่านไปยัง sendMail


1

ตรวจสอบให้แน่ใจว่าคุณได้รับอนุญาตให้ทั้งผู้ส่งและผู้รับส่งอีเมลและรับอีเมลจากแหล่งที่ไม่รู้จัก (แหล่งภายนอก) ในบัญชีอีเมล

import smtplib

#Ports 465 and 587 are intended for email client to email server communication - sending email
server = smtplib.SMTP('smtp.gmail.com', 587)

#starttls() is a way to take an existing insecure connection and upgrade it to a secure connection using SSL/TLS.
server.starttls()

#Next, log in to the server
server.login("#email", "#password")

msg = "Hello! This Message was sent by the help of Python"

#Send the mail
server.sendmail("#Sender", "#Reciever", msg)

ป้อนคำอธิบายรูปภาพที่นี่


msgไม่ใช่ข้อความ SMTP ที่ถูกต้องและดูเหมือนจะหายไปในอีเธอร์หากเซิร์ฟเวอร์อีเมลของคุณยอมรับ
tripleee

0

คิดว่าฉันจะใส่สองบิตของฉันที่นี่เพราะฉันเพิ่งคิดออกว่าการทำงานนี้

ดูเหมือนว่าคุณไม่มีพอร์ตที่ระบุไว้ในการตั้งค่าการเชื่อมต่อเซิร์ฟเวอร์ของคุณสิ่งนี้มีผลกับฉันเล็กน้อยเมื่อฉันพยายามเชื่อมต่อกับเซิร์ฟเวอร์ SMTP ที่ไม่ได้ใช้พอร์ตเริ่มต้น: 25

ตาม smtplib.SMTP doc ehlo หรือ helo คำขอ / ตอบกลับของคุณควรได้รับการดูแลโดยอัตโนมัติดังนั้นคุณไม่ควรกังวลเกี่ยวกับเรื่องนี้ (แต่อาจเป็นสิ่งที่ยืนยันได้หากทุกอย่างล้มเหลว)

อีกสิ่งที่จะถามตัวเองคือคุณได้อนุญาตการเชื่อมต่อ SMTP บนเซิร์ฟเวอร์ SMTP ของคุณหรือไม่ สำหรับบางไซต์เช่น GMAIL และ ZOHO คุณต้องเข้าใช้งานจริงและเปิดใช้งานการเชื่อมต่อ IMAP ภายในบัญชีอีเมล เซิร์ฟเวอร์อีเมลของคุณอาจไม่อนุญาตการเชื่อมต่อ SMTP ที่ไม่ได้มาจาก 'localhost' ใช่ไหม บางสิ่งบางอย่างที่จะมองเข้าไป

สิ่งสุดท้ายคือคุณอาจต้องการลองและเริ่มการเชื่อมต่อกับ TLS เซิร์ฟเวอร์ส่วนใหญ่ต้องการการรับรองความถูกต้องประเภทนี้

คุณจะเห็นว่าฉันติดสองช่องถึงลงในอีเมลของฉัน รายการพจนานุกรม msg ['ถึง'] และ msg ['FROM'] msg ช่วยให้ข้อมูลที่ถูกต้องแสดงในส่วนหัวของอีเมลเองซึ่งจะเห็นที่ปลายรับอีเมลในฟิลด์ถึง / จาก (คุณ อาจจะสามารถเพิ่มฟิลด์ตอบกลับในที่นี่ฟิลด์ถึงและจากตัวเองเป็นสิ่งที่เซิร์ฟเวอร์ต้องการฉันรู้ว่าฉันได้ยินมาว่ามีบางเซิร์ฟเวอร์อีเมลที่ปฏิเสธอีเมลหากพวกเขาไม่มีส่วนหัวอีเมลที่เหมาะสม

นี่คือรหัสที่ฉันใช้ในฟังก์ชั่นที่ทำงานให้ฉันส่งอีเมลเนื้อหาของไฟล์ * .txt โดยใช้คอมพิวเตอร์ในพื้นที่ของฉันและเซิร์ฟเวอร์ SMTP ระยะไกล (ZOHO ดังที่แสดง):

def emailResults(folder, filename):

    # body of the message
    doc = folder + filename + '.txt'
    with open(doc, 'r') as readText:
        msg = MIMEText(readText.read())

    # headers
    TO = 'to_user@domain.com'
    msg['To'] = TO
    FROM = 'from_user@domain.com'
    msg['From'] = FROM
    msg['Subject'] = 'email subject |' + filename

    # SMTP
    send = smtplib.SMTP('smtp.zoho.com', 587)
    send.starttls()
    send.login('from_user@domain.com', 'password')
    send.sendmail(FROM, TO, msg.as_string())
    send.quit()

0

เป็นที่น่าสังเกตว่าโมดูล SMTP รองรับตัวจัดการบริบทดังนั้นจึงไม่จำเป็นต้องเรียกเลิกด้วยตนเอง () ซึ่งจะรับประกันว่าจะถูกเรียกเสมอแม้ว่าจะมีข้อยกเว้นก็ตาม

    with smtplib.SMTP_SSL('smtp.gmail.com', 465) as server:
        server.ehlo()
        server.login(user, password)
        server.sendmail(from, to, body)

-1

เท่าที่รหัสของคุณเกี่ยวข้องดูเหมือนจะไม่มีอะไรผิดปกติกับมันยกเว้นว่ามันชัดเจนว่าคุณกำลังเรียกฟังก์ชั่นนั้นจริง ๆ ทั้งหมดที่ฉันคิดคือเมื่อเซิร์ฟเวอร์ของคุณไม่ตอบสนองคุณจะได้รับข้อผิดพลาด SMTPServerDisconnected นี้ หากคุณค้นหาฟังก์ชั่น getreply () ใน smtplib (ตัดตอนมาด้านล่าง) คุณจะได้รับแนวคิด

def getreply(self):
    """Get a reply from the server.

    Returns a tuple consisting of:

      - server response code (e.g. '250', or such, if all goes well)
        Note: returns -1 if it can't read response code.

      - server response string corresponding to response code (multiline
        responses are converted to a single, multiline string).

    Raises SMTPServerDisconnected if end-of-file is reached.
    """

ตรวจสอบตัวอย่างได้ที่https://github.com/rreddy80/sendEmails/blob/master/sendEmailAttachments.pyซึ่งใช้การเรียกฟังก์ชั่นเพื่อส่งอีเมลหากนั่นคือสิ่งที่คุณกำลังพยายามทำ (DRY approach)

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.