这段代码工作,并向我发送电子邮件就好:
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
有人能告诉我为什么吗?
在摆弄了很多例子之后,例如这里
这对我来说很管用:
import smtplib
from email.mime.text import MIMEText
# SMTP sendmail server mail relay
host = 'mail.server.com'
port = 587 # starttls not SSL 465 e.g gmail, port 25 blocked by most ISPs & AWS
sender_email = 'name@server.com'
recipient_email = 'name@domain.com'
password = 'YourSMTPServerAuthenticationPass'
subject = "Server - "
body = "Message from server"
def sendemail(host, port, sender_email, recipient_email, password, subject, body):
try:
p1 = f'<p><HR><BR>{recipient_email}<BR>'
p2 = f'<h2><font color="green">{subject}</font></h2>'
p3 = f'<p>{body}'
p4 = f'<p>Kind Regards,<BR><BR>{sender_email}<BR><HR>'
message = MIMEText((p1+p2+p3+p4), 'html')
# servers may not accept non RFC 5321 / RFC 5322 / compliant TXT & HTML typos
message['From'] = f'Sender Name <{sender_email}>'
message['To'] = f'Receiver Name <{recipient_email}>'
message['Cc'] = f'Receiver2 Name <>'
message['Subject'] = f'{subject}'
msg = message.as_string()
server = smtplib.SMTP(host, port)
print("Connection Status: Connected")
server.set_debuglevel(1)
server.ehlo()
server.starttls()
server.ehlo()
server.login(sender_email, password)
print("Connection Status: Logged in")
server.sendmail(sender_email, recipient_email, msg)
print("Status: Email as HTML successfully sent")
except Exception as e:
print(e)
print("Error: unable to send email")
# Run
sendemail(host, port, sender_email, recipient_email, password, subject, body)
print("Status: Exit")
在缩进函数中的代码时(这是可以的),还缩进了原始消息字符串的行。但是前导空白意味着标题行的折叠(连接),如RFC 2822 - Internet Message Format的2.2.3和3.2.3节所述:
每个报头字段在逻辑上是由一行字符组成的
字段名、冒号和字段主体。为了方便
但是,为了处理每行998/78个字符的限制,
报头字段的字段主体部分可以分成多个
线表示;这叫做“折叠”。
在sendmail调用的函数形式中,所有行都以空白开始,因此是“展开的”(连接),您正在尝试发送
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.
这将不起作用,因此出现异常。
解决方案很简单:只保留原来的消息字符串。这可以通过一个函数来完成(正如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.
这就是您的旧代码所做的工作。
请注意,我还保留了标题和正文之间的空行,以适应RFC的第3.5节(这是必需的),并根据Python风格指南PEP-0008(这是可选的)将include放在函数之外。
我建议您使用标准包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()
如您所见,MIMEText对象中的报头To必须是由逗号分隔的电子邮件地址组成的字符串。另一方面,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中有所了解,这是必须的——标准库的文档大部分都很出色。
下面是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!')
以下仅限中国用户使用:
If you use 126/163, NetEase Mail, you need to set" Client Authorization Password ", like below:
裁判:https://stackoverflow.com/a/41470149/2803344
https://docs.python.org/3/library/email.examples.html#email-examples