从Python通过sendmail发送邮件

84 投票
8 回答
97531 浏览
提问于 2025-04-11 09:21

如果我想通过 sendmail 而不是 SMTP 来发送邮件,Python 有没有什么库可以帮我简化这个过程呢?

更好的是,有没有一个好的库可以让我不用考虑 'sendmail 和 smtp 的选择',直接使用就行?

我会在一些 Unix 主机上运行这个脚本,其中只有部分主机在 localhost:25 上监听;而且其中有一些是嵌入式系统,无法设置为接受 SMTP。

作为一种良好的实践,我希望这个库能够自动处理邮件头注入的安全问题——所以直接用 popen('/usr/bin/sendmail', 'w') 这种方式对我来说有点太底层了。

如果答案是 '去写一个库吧,' 那也没关系 ;-)

8 个回答

12

吉姆的回答在我使用Python 3.4时没有效果。我需要在subprocess.Popen()中添加一个额外的参数universal_newlines=True

from email.mime.text import MIMEText
from subprocess import Popen, PIPE

msg = MIMEText("Here is the body of my message")
msg["From"] = "me@example.com"
msg["To"] = "you@example.com"
msg["Subject"] = "This is the subject."
p = Popen(["/usr/sbin/sendmail", "-t", "-oi"], stdin=PIPE, universal_newlines=True)
p.communicate(msg.as_string())

如果没有universal_newlines=True,我会得到

TypeError: 'str' does not support the buffer interface
38

这是一个简单的Python函数,它使用Unix系统中的sendmail命令来发送邮件。

def sendMail():
    sendmail_location = "/usr/sbin/sendmail" # sendmail location
    p = os.popen("%s -t" % sendmail_location, "w")
    p.write("From: %s\n" % "from@somewhere.com")
    p.write("To: %s\n" % "to@somewhereelse.com")
    p.write("Subject: thesubject\n")
    p.write("\n") # blank line separating headers from body
    p.write("body of the mail")
    status = p.close()
    if status != 0:
           print "Sendmail exit status", status
133

头部注入问题跟你发送邮件的方式无关,而是跟你构建邮件的方式有关。你可以查看一下email这个包,用它来构建邮件,然后把邮件序列化(也就是转换成可以发送的格式),最后通过subprocess模块发送到/usr/sbin/sendmail

import sys
from email.mime.text import MIMEText
from subprocess import Popen, PIPE


msg = MIMEText("Here is the body of my message")
msg["From"] = "me@example.com"
msg["To"] = "you@example.com"
msg["Subject"] = "This is the subject."
p = Popen(["/usr/sbin/sendmail", "-t", "-oi"], stdin=PIPE)
# Both Python 2.X and 3.X
p.communicate(msg.as_bytes() if sys.version_info >= (3,0) else msg.as_string()) 

# Python 2.X
p.communicate(msg.as_string())

# Python 3.X
p.communicate(msg.as_bytes())

撰写回答