14.2. smtplib — smtp 协议客户端 | 邮件模块 |《python 3 标准库实例教程》| python 技术论坛-380玩彩网官网入口

未匹配的标注

目的:与smtp服务器交互,包括发送邮件

smtplib 包含 smtp 类,可以用来连接邮件服务器发送邮件。

注意

邮箱地址,主机名,ip 地址参数在接下来的示例中将被隐藏,但代码的执行结果将被正确呈现。

发送一封电子邮件

 smtp 最常见的作用是连接邮件服务器并发送消息。邮件服务器主机名和端口被传送到构造函数, connect() 明确被调用。一旦建立连接,调用 sendmail() 并加入收件人信息及邮件内容参数。信息文本必须遵循rfc 5322,因为 smtplib 对内容和头不做修改。也就意味着 from 和 to 头需要被请求者加入。

smtplib_sendmail.py

import smtplib
import email.utils
from email.mime.text import mimetext
# 创建邮件
msg = mimetext('this is the body of the message.')
msg['to'] = email.utils.formataddr(('recipient',
                                    '[email protected]'))
msg['from'] = email.utils.formataddr(('author',
                                      '[email protected]'))
msg['subject'] = 'simple test message'
server = smtplib.smtp('localhost', 1025)
server.set_debuglevel(true)  # 展示与服务器的交互信息
try:
    server.sendmail('[email protected]',
                    ['[email protected]'],
                    msg.as_string())
finally:
    server.quit()

在这个示例中,调试信息被打开,来显示客服端与服务端的交互,否则将不输出任何信息。

$ python3 smtplib_sendmail.py
send: 'ehlo 1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.
0.0.0.0.0.0.ip6.arpa\r\n'
reply: b'250-1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0
.0.0.0.0.0.0.ip6.arpa\r\n'
reply: b'250-size 33554432\r\n'
reply: b'250 help\r\n'
reply: retcode (250); msg: b'1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0
.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa\nsize 33554432\nhelp'
send: 'mail from:<[email protected]> size=236\r\n'
reply: b'250 ok\r\n'
reply: retcode (250); msg: b'ok'
send: 'rcpt to:<[email protected]>\r\n'
reply: b'250 ok\r\n'
reply: retcode (250); msg: b'ok'
send: 'data\r\n'
reply: b'354 end data with .\r\n'
reply: retcode (354); msg: b'end data with .'
data: (354, b'end data with .')
send: b'content-type: text/plain; charset="us-ascii"\r\nmime-ver
sion: 1.0\r\ncontent-transfer-encoding: 7bit\r\nto: recipient [email protected]>\r\nfrom: author <[email protected]>\r\nsu
bject: simple test message\r\n\r\nthis is the body of the messag
e.\r\n.\r\n'
reply: b'250 ok\r\n'
reply: retcode (250); msg: b'ok'
data: (250, b'ok')
send: 'quit\r\n'
reply: b'221 bye\r\n'
reply: retcode (221); msg: b'bye'

 sendmail() 的第二个参数,收件地址,以列表的形式传递。邮件将逐个发送到列表内的所有收件地址。因发/收件人信息与邮件内容是分开的,所以在方法中加入参数来密件抄送 (bcc) 给某人,但不是在内容头里。

认证和加密

如果服务器支持, smtp 类还可以处理认证和 tls (安全传输层协议) 加密。要确定服务器是否支持tls,直接调用 ehlo() 来识别客户端到服务器并询问支持何种扩展。然后调用 has_extn()来检查返回的结果。tls开始后, 在认证前 ehlo() 必须要再次被调用。 现在大部分邮件提供商支持基于 tls 的连接. 为了与此类服务器建立连接,用 smtp_ssl 来使用加密连接。

smtplib_authenticated.py

import smtplib
import email.utils
from email.mime.text import mimetext
import getpass
# 提示用户输入连接信息
to_email = input('recipient: ')
servername = input('mail server name: ')
serverport = input('server port: ')
if serverport:
    serverport = int(serverport)
else:
    serverport = 25
use_tls = input('use tls? (yes/no): ').lower()
username = input('mail username: ')
password = getpass.getpass("%s's password: " % username)
# 创建消息
msg = mimetext('test message from pymotw.')
msg.set_unixfrom('author')
msg['to'] = email.utils.formataddr(('recipient', to_email))
msg['from'] = email.utils.formataddr(('author',
                                      '[email protected]'))
msg['subject'] = 'test from pymotw'
if use_tls == 'yes':
    print('starting with a secure connection')
    server = smtplib.smtp_ssl(servername, serverport)
else:
    print('starting with an insecure connection')
    server = smtplib.smtp(servername, serverport)
try:
    server.set_debuglevel(true)
    # 识别自己,服务器支持的特征
    server.ehlo()
    # 如果支持加密,执行
    if server.has_extn('starttls'):
        print('(starting tls)')
        server.starttls()
        server.ehlo()  # reidentify ourselves over tls connection
    else:
        print('(no starttls)')
    if server.has_extn('auth'):
        print('(logging in)')
        server.login(username, password)
    else:
        print('(no auth)')
    server.sendmail('[email protected]',
                    [to_email],
                    msg.as_string())
finally:
    server.quit()

tsl 在使用中, starttls 扩展在 ehlo 不会出现。

$ python3 source/smtplib/smtplib_authenticated.py
recipient: [email protected]
mail server name: localhost
server port: 1025
use tls? (yes/no): no
mail username: test
test's password:
starting with an insecure connection
send: 'ehlo 1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0
.0.0.0.0.0.ip6.arpa\r\n'
reply: b'250-1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.
0.0.0.0.0.0.ip6.arpa\r\n'
reply: b'250-size 33554432\r\n'
reply: b'250 help\r\n'
reply: retcode (250); msg: b'1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.
0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa\nsize 33554432\nhelp'
(no starttls)
(no auth)
send: 'mail from:<[email protected]> size=220\r\n'
reply: b'250 ok\r\n'
reply: retcode (250); msg: b'ok'
send: 'rcpt to:<[email protected]>\r\n'
reply: b'250 ok\r\n'
reply: retcode (250); msg: b'ok'
send: 'data\r\n'
reply: b'354 end data with .\r\n'
reply: retcode (354); msg: b'end data with .'
data: (354, b'end data with .')
send: b'content-type: text/plain; charset="us-ascii"\r\n
mime-version: 1.0\r\ncontent-transfer-encoding: 7bit\r\nto:
recipient <[email protected]>\r\nfrom: author <[email protected]>
\r\nsubject: test from pymotw\r\n\r\ntest message from pymotw.
\r\n.\r\n'
reply: b'250 ok\r\n'
reply: retcode (250); msg: b'ok'
data: (250, b'ok')
send: 'quit\r\n'
reply: b'221 bye\r\n'
reply: retcode (221); msg: b'bye'
$ python3 source/smtplib/smtplib_authenticated.py
recipient: [email protected]
mail server name: mail.isp.net
server port: 465
use tls? (yes/no): yes
mail username: [email protected]
[email protected]'s password:
starting with a secure connection
send: 'ehlo 1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0
.0.0.0.0.0.ip6.arpa\r\n'
reply: b'250-mail.isp.net\r\n'
reply: b'250-pipelining\r\n'
reply: b'250-size 71000000\r\n'
reply: b'250-enhancedstatuscodes\r\n'
reply: b'250-8bitmime\r\n'
reply: b'250-auth plain login\r\n'
reply: b'250 auth=plain login\r\n'
reply: retcode (250); msg: b'mail.isp.net\npipelining\nsize
71000000\nenhancedstatuscodes\n8bitmime\nauth plain login\n
auth=plain login'
(no starttls)
(logging in)
send: 'auth plain agrvdwdozwxsbwfubkbmyxn0bwfpbc5mbqbutuz3mdbmzmf
zdg1haww=\r\n'
reply: b'235 2.0.0 ok\r\n'
reply: retcode (235); msg: b'2.0.0 ok'
send: 'mail from:<[email protected]> size=220\r\n'
reply: b'250 2.1.0 ok\r\n'
reply: retcode (250); msg: b'2.1.0 ok'
send: 'rcpt to:<[email protected]>\r\n'
reply: b'250 2.1.5 ok\r\n'
reply: retcode (250); msg: b'2.1.5 ok'
send: 'data\r\n'
reply: b'354 end data with .\r\n'
reply: retcode (354); msg: b'end data with .'
data: (354, b'end data with .')
send: b'content-type: text/plain; charset="us-ascii"\r\n
mime-version: 1.0\r\ncontent-transfer-encoding: 7bit\r\nto:
recipient <[email protected]>\r\nfrom: author <[email protected]>
\r\nsubject: test from pymotw\r\n\r\ntest message from pymotw.
\r\n.\r\n'
reply: b'250 2.0.0 ok: queued as a0ef7f2983\r\n'
reply: retcode (250); msg: b'2.0.0 ok: queued as a0ef7f2983'
data: (250, b'2.0.0 ok: queued as a0ef7f2983')
send: 'quit\r\n'
reply: b'221 2.0.0 bye\r\n'
reply: retcode (221); msg: b'2.0.0 bye'

邮箱地址核实

smtp 协议包含了向服务器确认邮箱地址的有效性。 通常 vrfy 无法阻止垃圾邮件制造者找到正常使用者的邮箱地址,但是如果可行,它可以让客户端询问服务器关于一个邮箱地址,并且返回一个带有使用者全名的,且可以验证有效性的状态码。

smtplib_verify.py

import smtplib
server = smtplib.smtp('mail')
server.set_debuglevel(true)  #显示与服务器的通讯
try:
    dhellmann_result = server.verify('dhellmann')
    notthere_result = server.verify('notthere')
finally:
    server.quit()
print('dhellmann:', dhellmann_result)
print('notthere :', notthere_result)

在最后两行的输出结果中可以看出,地址 dhellmann 是有效的,但 notthere 不是有效的。

$ python3 smtplib_verify.py
send: 'vrfy \r\n'
reply: '250 2.1.5 doug hellmann \r\n'
reply: retcode (250); msg: 2.1.5 doug hellmann 
send: 'vrfy \r\n'
reply: '550 5.1.1 ... user unknown\r\n'
reply: retcode (550); msg: 5.1.1 ... user unknown
send: 'quit\r\n'
reply: '221 2.0.0 mail closing connection\r\n'
reply: retcode (221); msg: 2.0.0 mail closing connection
dhellmann: (250, '2.1.5 doug hellmann ')
notthere : (550, '5.1.1 ... user unknown')

补充

  •  --简易邮件传输协议(smtp) 规范。
  •  -- 对基础传输的扩展,smtp 服务扩展。
  •  -- 「format of arpa internet text messages标准」,原始邮件格式协议。
  •  -- 「internet message format」, 对邮件格式的升级。
  • email -- 创建和获取邮件的标准库。
  • 「smtpd: 包含了执行smtp服务的类。」 -- 执行一个简单的 smtp 服务。

本文章首发在 380玩彩网官网入口 网站上。

本译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接
我们的翻译工作遵照 cc 协议,如果我们的工作有侵犯到您的权益,请及时联系380玩彩网官网入口。

原文地址:https://learnku.com/docs/pymotw/smtplib-...

译文地址:https://learnku.com/docs/pymotw/smtplib-...

上一篇 下一篇
讨论数量: 0



暂无话题~
网站地图