python的smtplib提供了一种很方便的途径发送电子邮件。它对smtp协议进行了简单的封装。

smtp协议的基本命令包括:

HELO 向服务器标识用户身份

MAIL 初始化邮件传输 mail from:

RCPT 标识单个的邮件接收人;常在MAIL命令后面,可有多个rcpt to:

DATA 在单个或多个RCPT命令后,表示所有的邮件接收人已标识,并初始化数据传输,以.结束

VRFY 用于验证指定的用户/邮箱是否存在;由于安全方面的原因,服务器常禁止此命令

EXPN 验证给定的邮箱列表是否存在,扩充邮箱列表,也常被禁用

HELP 查询服务器支持什么命令

NOOP 无操作,服务器应响应OK

QUIT 结束会话

RSET 重置会话,当前传输被取消

MAIL FROM 指定发送者地址

RCPT TO 指明的接收者地址

一般smtp会话有两种方式,一种是邮件直接投递,就是说,比如你要发邮件給zzz@163.com,那就直接连接163.com的邮件服务器,把信投給zzz@163.com; 另一种是验证过后的发信,它的过程是,比如你要发邮件給zzz@163.com,你不是直接投到163.com,而是通过自己在sina.com的另一个邮箱来发。这样就要先连接sina.com的smtp服务器,然后认证,之后在把要发到163.com的信件投到sina.com上,sina.com会帮你把信投递到163.com。

第一种方式的命令流程基本是这样:

1. helo

2. mail from

3. rcpt to

4. data

5. quit

但是第一种发送方式一般有限制的,就是rcpt to指定的这个邮件接收者必须在这个服务器上存在,否则是不会接收的。 先看看代码:

#-*- encoding: gb2312 -*-

import os, sys, string

import smtplib

# 邮件服务器地址

mailserver = "smtp.163.com"

# smtp会话过程中的mail from地址

from_addr = "asfgysg@zxsdf.com"

# smtp会话过程中的rcpt to地址

to_addr = "zhaoweikid@163.com"

# 信件内容

msg = "test mail"

svr = smtplib.SMTP(mailserver)

# 设置为调试模式,就是在会话过程中会有输出信息

svr.set_debuglevel(1)

# helo命令,docmd方法包括了获取对方服务器返回信息

svr.docmd("HELO server")

# mail from, 发送邮件发送者

svr.docmd("MAIL FROM: <%s>" % from_addr)

# rcpt to, 邮件接收者

svr.docmd("RCPT TO: <%s>" % to_addr)

# data命令,开始发送数据

svr.docmd("DATA")

# 发送正文数据

svr.send(msg)

# 比如以 . 作为正文发送结束的标记,用send发送的,所以要用getreply获取返回信息

svr.send(" . ")

svr.getreply()

# 发送结束,退出

svr.quit()

注意的是,163.com是有反垃圾邮件功能的,想上面的这种投递邮件的方法不一定能通过反垃圾邮件系统的检测的。所以一般不推荐个人这样发送。

第二种有点不一样:

1.ehlo

2.auth login

3.mail from

4.rcpt to

5.data

6.quit

相对于第一种来说,多了一个认证过程,就是auth login这个过程。

#-*- encoding: gb2312 -*-

import os, sys, string

import smtplib

import base64

# 邮件服务器地址

mailserver = "smtp.163.com"

# 邮件用户名

username = "xxxxxx@163.com"

# 密码

password = "xxxxxxx"

# smtp会话过程中的mail from地址

from_addr = "xxxxxx@163.com"

# smtp会话过程中的rcpt to地址

to_addr = "yyyyyy@163.com"

# 信件内容

msg = "my test mail"

svr = smtplib.SMTP(mailserver)

# 设置为调试模式,就是在会话过程中会有输出信息

svr.set_debuglevel(1)

# ehlo命令,docmd方法包括了获取对方服务器返回信息

svr.docmd("EHLO server")

# auth login 命令

svr.docmd("AUTH LOGIN")

# 发送用户名,是base64编码过的,用send发送的,所以要用getreply获取返回信息

svr.send(base64.encodestring(username))

svr.getreply()

# 发送密码

svr.send(base64.encodestring(password))

svr.getreply()

# mail from, 发送邮件发送者

svr.docmd("MAIL FROM: <%s>" % from_addr)

# rcpt to, 邮件接收者

svr.docmd("RCPT TO: <%s>" % to_addr)

# data命令,开始发送数据

svr.docmd("DATA")

# 发送正文数据

svr.send(msg)

# 比如以 . 作为正文发送结束的标记

svr.send(" . ")

svr.getreply()

# 发送结束,退出

svr.quit()

上面说的是最普通的情况,但是不能忽略的是现在好多企业邮件是支持安全邮件的,就是通过SSL发送的邮件,这个怎么发呢?SMTP对SSL安全邮件的支持有两种方案,一种老的是专门开启一个465端口来接收ssl邮件,另一种更新的做法是在标准的25端口的smtp上增加一个starttls的命令来支持。

看看第一种怎么办:

#-*- encoding: gb2312 -*-

import os, sys, string, socket

import smtplib

class SMTP_SSL (smtplib.SMTP):

def __init__(self, host='', port=465, local_hostname=None, key=None, cert=None):

self.cert = cert

self.key = key

smtplib.SMTP.__init__(self, host, port, local_hostname)

def connect(self, host='localhost', port=465):

if not port and (host.find(':') == host.rfind(':')):

i = host.rfind(':')

if i >= 0:

host, port = host[:i], host[i+1:]

try: port = int(port)

except ValueError:

raise socket.error, "nonnumeric port"

if not port: port = 654

if self.debuglevel > 0: print>>stderr, 'connect:', (host, port)

msg = "getaddrinfo returns an empty list"

self.sock = None

for res in socket.getaddrinfo(host, port, 0, socket.SOCK_STREAM):

af, socktype, proto, canonname, sa = res

try:

self.sock = socket.socket(af, socktype, proto)

if self.debuglevel > 0: print>>stderr, 'connect:', (host, port)

self.sock.connect(sa)

# 新增加的创建ssl连接

sslobj = socket.ssl(self.sock, self.key, self.cert)

except socket.error, msg:

if self.debuglevel > 0:

print>>stderr, 'connect fail:', (host, port)

if self.sock:

self.sock.close()

self.sock = None

continue

break

if not self.sock:

raise socket.error, msg

# 设置ssl

self.sock = smtplib.SSLFakeSocket(self.sock, sslobj)

self.file = smtplib.SSLFakeFile(sslobj);

(code, msg) = self.getreply()

if self.debuglevel > 0: print>>stderr, "connect:", msg

return (code, msg)

if __name__ == '__main__':

smtp = SMTP_SSL('192.168.2.10')

smtp.set_debuglevel(1)

smtp.sendmail("zzz@xxx.com", "zhaowei@zhaowei.com", "xxxxxxxxxxxxxxxxx")

smtp.quit()

这里我是从原来的smtplib.SMTP派生出了新的SMTP_SSL类,它专门来处理ssl连接。我这里测试的192.168.2.10是我自己的测试服务器.

第二种是新增加了starttls的命令,这个很简单,smtplib里就有这个方法,叫smtplib.starttls()。当然,不是所有的邮件系统都支持安全邮件的,这个需要从ehlo的返回值里来确认,如果里面有starttls,才表示支持。相对于发送普通邮件的第二种方法来说,只需要新增加一行代码就可以了:

#-*- encoding: gb2312 -*-

import os, sys, string

import smtplib

import base64

# 邮件服务器地址

mailserver = "smtp.163.com"

# 邮件用户名

username = "xxxxxx@163.com"

# 密码

password = "xxxxxxx"

# smtp会话过程中的mail from地址

from_addr = "xxxxxx@163.com"

# smtp会话过程中的rcpt to地址

to_addr = "yyyyyy@163.com"

# 信件内容

msg = "my test mail"

svr = smtplib.SMTP(mailserver)

# 设置为调试模式,就是在会话过程中会有输出信息

svr.set_debuglevel(1)

# ehlo命令,docmd方法包括了获取对方服务器返回信息,如果支持安全邮件,返回值里会有starttls提示

svr.docmd("EHLO server")

svr.starttls() # <------ 这行就是新加的支持安全邮件的代码!

# auth login 命令

svr.docmd("AUTH LOGIN")

# 发送用户名,是base64编码过的,用send发送的,所以要用getreply获取返回信息

svr.send(base64.encodestring(username))

svr.getreply()

# 发送密码

svr.send(base64.encodestring(password))

svr.getreply()

# mail from, 发送邮件发送者

svr.docmd("MAIL FROM: <%s>" % from_addr)

# rcpt to, 邮件接收者

svr.docmd("RCPT TO: <%s>" % to_addr)

# data命令,开始发送数据

svr.docmd("DATA")

# 发送正文数据

svr.send(msg)

# 比如以 . 作为正文发送结束的标记

svr.send(" . ")

svr.getreply()

# 发送结束,退出

svr.quit()

注意:以上的代码为了方便我都没有判断返回值,严格说来,是应该判断一下返回的代码的,在smtp协议中,只有返回代码是2xx或者3xx才能继续下一步,返回4xx或5xx的,都是出错了。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

smtplib python_python模块smtplib学习相关推荐

  1. smtplib python_python模块:smtplib模块

    1.使用本地的sendmail协议进行邮件发送 格式(1):smtpObj=smtplib.SMTP([host [,port [,local_hostname]]]) host:SMTP服务器主机的 ...

  2. smtplib python_python的smtplib无法发送邮件的解决办法

    本来一直使用python的smtplib通过189信箱发邮件的(因为189邮箱的短信提醒功能对我很有用).但前些天突然不能用了.仔细查看发送记录,发现使用python返回登录错误,代码334.开启sm ...

  3. [转]python各模块的学习

    [-] 01 关于本书 02 代码约定 03 关于例子 04 如何联系我们 1 核心模块 11 介绍 111 内建函数和异常 112 操作系统接口模块 113 类型支持模块 114 正则表达式 115 ...

  4. Pynput模块的学习与创新,基于python的操作录制脚本

    pynput模块是个好东西,它可以代理你完成一些重复且简单的操作.由于涉及到控制鼠键,我去年发布的博文始终没过审,本文会提供一些易使用的函数和我的学习过程. 时隔一年,我重新回到了pynput模块的学 ...

  5. STM32单片机 关于超声波模块的学习(1)

    分享一篇我刚刚弄完的一个超声波模块的学习 超声波模块的介绍: 1.单片机的一个IO口发送高电平的信号给Trig,信号时间要大于10us 2.然后模块的内部会发送方波 3.然后Echo会给单片机的IO口 ...

  6. CBAM(卷积块注意模块)学习笔记

    论文地址:https://arxiv.org/abs/1807.06521 一.简介 我们提出了Convolutional Block Attention Module(CBAM), 一个简单而有效的 ...

  7. Python 模块 UUID 学习使用

    Python 模块 UUID 学习使用 一.UUID介绍 UUID: 通用唯一标识符 ( Universally Unique Identifier ), 对于所有的UUID它可以保证在空间和时间上的 ...

  8. Numpy模块的学习(下)

    上一篇:Numpy模块的学习(上) 12. 位运算 Numpy中以"bitwise_"开头的函数是位运算函数. 函数 描述 bitwise_and 对数组元素执行位与操作. bit ...

  9. 合宙 724UG 模块GPIO学习

    2.合宙 724UG 模块GPIO学习 一.需要准备 官方API手册 硬件设计手册 724UG开发板原理图 二.GPIO配置讲解 打开官方API手册找到对应的家接口文档,里面提供了很多api接口根据自 ...

最新文章

  1. R语言生存分析(survival analysis)与生存资料有关的概念详解
  2. css 中 border 断线解决,简单实用
  3. mac osx wine 1.7.5 源码编译方法及中文乱码的解决
  4. 洛谷P4727:图的同构计数(Polya引理)(dfs)
  5. 硬盘序列号示例_序列化代理模式示例
  6. 特征筛选9——根据重要性SelectFromModel筛选特征(有监督筛选)
  7. Discuz常见小问题-如何为每个板块设置不同的图标
  8. Pytorch学习笔记总结
  9. Google深度学习TensorFlow最好的入门文章!
  10. dms mysql 工具_数据库管理工具DMS
  11. h5php大转盘抽奖,html5转盘抽奖 完整代码下载(网页版)
  12. 【easyui】combobox 静态数据时,设置默认值时,不触发onselect事件
  13. batch size设置技巧
  14. 腾讯产品策划运营类笔经(带题目)
  15. 今天刚到货的小米平板2,就出现dnx fastboot mode一直卡死黑屏
  16. 关于网易云音乐的一些感想
  17. s一般怎么称呼自己的m_“老公、老婆、亲爱的”?快来围观明星怎么称呼自己的另一半!...
  18. .net rar zip压缩包解压
  19. 华三H3C交换机如何配置堆叠irf虚拟化之如何配置检测机制(配置BFD MAD检测)
  20. RxJava 与 Retrofit 结合的最佳实践

热门文章

  1. ora-01031 linux,ORA-01031 :insufficient privileges
  2. 用定时器实现页面跳转
  3. C语言、JAVA与JavaScript的区别
  4. 用UILocalNotification实现一个闹钟(Swift)
  5. 【Spring】Spring Framework Reference Documentation中文版18
  6. 水星450r虚拟服务器,水星MW450R V4无线桥接设置教程 | 192路由网
  7. 帆软对话框标题字体大小和位置更改
  8. STM32外设系列—DHT11
  9. ts定义返回函数类型
  10. c语言带头节点单链表创建,C语言建立带头结点的单链表