如何在Python3中优雅地发送电子邮件?
我正在用一个Python3脚本发送邮件(使用smtplib
库)。到目前为止,我发送的邮件总是能在Gmail账户里收到。但是,有个问题就是,尽管我把CSS样式写在了邮件内容里,但它们并没有显示出来。而且,就连这个简单的消息也无法发送:
title = 'My title'
msg_content = '<h2>{title}: <font color="green">OK</font></h2>\n'.format(title=title)
不过,如果我把{title}后面的两个点去掉,它就能发送了。如果我把结尾的\n去掉,它又发送不出去。为什么会这样呢?我该怎么在Python3里发送这样的内容呢?
title = 'My title'
msg_content = '<h2>{title}: <span style="color: green">OK</span></h2>'.format(title=title)
编辑
import smtplib
msg_header = 'From: Sender Name <sender@server>\n' \
'To: Receiver Name <receiver@server>\n' \
'Cc: Receiver2 Name <receiver2@server>\n' \
'MIME-Version: 1.0\n' \
'Content-type: text/html\n' \
'Subject: Any subject\n'
title = 'My title'
msg_content = '<h2>{title} > <font color="green">OK</font></h2>\n'.format(
title=title)
msg_full = (''.join([msg_header, msg_content])).encode()
server = smtplib.SMTP('smtp.gmail.com:587')
server.starttls()
server.login('sender@server.com', 'senderpassword')
server.sendmail('sender@server.com',
['receiver@server.com', 'receiver@server.com'],
msg_full)
server.quit()
2 个回答
虽然这个回答有点晚,但截至2021年,我用来用Python发送邮件的方法是这样的:
import smtplib
from email.mime.text import MIMEText
sender = 'sender@tld'
receivers = ['receiver1@tld', 'receiver2@tld']
body_of_email = 'The body of the email'
msg = MIMEText(body_of_email, 'plain')
# html_body_of_email = '<h1>The html body of the email</h1>'
# msg = MIMEText(html_body_of_email, 'html')
msg['Subject'] = 'The Subject'
msg['From'] = sender
msg['To'] = ','.join(receivers)
s = smtplib.SMTP_SSL(host = 'smtp.gmail.com', port = 465)
s.login(user = 'username', password = 'password')
s.sendmail(sender, receivers, msg.as_string())
s.quit()
在用Gmail发送邮件之前,记得在你的谷歌账户上开启不太安全的应用
选项:
- 访问你的(谷歌账户)。
- 在左边的导航面板上,点击
安全
。 - 在页面底部的“不太安全的应用访问”面板中,点击
开启访问
。 - 点击保存按钮。
编辑后说明
你提供的msg_full结果看起来是这样的:
From: Sender Name <sender@server>
To: Receiver Name <receiver@server>
Cc: Receiver2 Name <receiver2@server>
MIME-Version: 1.0
Content-type: text/html
Subject: Any subject
<h2>My title > <font color="green">OK</font></h2>
你的电子邮件格式不符合RFC 2822的要求:
- 你必须使用CRLF('\r\n')作为换行符,单独使用LF('\n')是不合法的。
- 邮件的头部和正文之间必须用CRLF分隔(也就是要有一个空行)。如果你用
''.join([msg_header, msg_body])
来连接,这样不会插入这个空行。因此,你想要发送的正文内容会被当作头部处理。
同样邮件的正确版本应该是这样的:
Content-Type: text/html; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
From: Sender Name <sender@server>
To: Receiver Name <receiver@server>
Cc: Receiver2 Name <receiver2@server>
Subject: Any subject
<h2>My title > <font color="green">OK</font></h2>
我强烈建议你使用Python内置的库来构建符合RFC标准的邮件内容。
import smtplib
from email.mime.text import MIMEText
title = 'My title'
msg_content = '<h2>{title} > <font color="green">OK</font></h2>\n'.format(title=title)
message = MIMEText(msg_content, 'html')
message['From'] = 'Sender Name <sender@server>'
message['To'] = 'Receiver Name <receiver@server>'
message['Cc'] = 'Receiver2 Name <receiver2@server>'
message['Subject'] = 'Any subject'
msg_full = message.as_string()
server = smtplib.SMTP('smtp.gmail.com:587')
server.starttls()
server.login('sender@server.com', 'senderpassword')
server.sendmail('sender@server.com',
['receiver@server.com', 'receiver@server.com'],
msg_full)
server.quit()
另外,最好还添加一个文本/plain版本的邮件,这样任何收件人都能在任何地方阅读(我禁用了HTML邮件,在我的客户端上看不到这些内容)。你可以很简单地使用email.mime.text来做到这一点:
from email.mime.multipart import MIMEMultipart
message = MIMEMultipart('alternative')
message['From'] = 'Sender Name <sender@server>'
message['To'] = 'Receiver Name <receiver@server>'
message['Cc'] = 'Receiver2 Name <receiver2@server>'
message['Subject'] = 'Any subject'
# Record the MIME types of both parts - text/plain and text/html.
part1 = MIMEText(text, 'plain')
part2 = MIMEText(html, 'html')
# Attach parts into message container.
# According to RFC 2046, the last part of a multipart message, in this case
# the HTML message, is best and preferred.
message.attach(part1)
message.attach(part2)
之前的回答
你的问题中缺少了你用来发送邮件的代码。我强烈怀疑你是直接把msg_content作为消息传给了SMTP.sendmail。
但是,SMTP.sendmail会原样传输这个字符串,也就是按照RFC 5321的规定,作为邮件的内容。这部分内容包括邮件的头部和正文,头部在邮件的最上面(见RFC 2822)。
你的消息"My title: <span..."因此被解释为头部"My title:",而在接收端不会显示。如果你去掉{title}:
后面的冒号,那么接收者显然就不会把结果当作头部处理了。
关于HTML格式的邮件,可以查看https://docs.python.org/2/library/email-examples.html上的示例——基本上你需要创建一个合适的text/html MIME编码的消息才能发送你的邮件。