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的,都是出错了。

____________________________________________________________

python模块学习 ---- smtplib 邮件发送

在基于互联网的应用中,程序经常需要自动地发送电子邮件。如:一个网站的注册系统会在用户注册时发送一封邮件来确认注册;当用户忘记登陆密码的时 候,通过邮件来取回密码。smtplib模块是python中smtp(简单邮件传输协议)的客户端实现。我们可以使用smtplib模块,轻松的发送电 子邮件。下面的例子用了不到十行代码来发送电子邮件:

[python] view plain copy
  1. #coding=gbk
  2. import smtplib
  3. smtp = smtplib.SMTP()
  4. smtp.connect("smtp.yeah.net", "25")
  5. smtp.login('用户名', '密码')
  6. smtp.sendmail('from@yeah.net', 'to@21cn.com', 'From: from@yeah.net/r/nTo: to@21cn.com/r/nSubject: this is a email from python demo/r/n/r/nJust for test~_~')
  7. smtp.quit()

  这个例子够简单吧^_^!下面详细介绍stmplib模块中的类和方法。

smtplib.SMTP([host[, port[, local_hostname[, timeout]]]])

  SMTP类构造函数,表示与SMTP服务器之间的连接,通过这个连接我们可以向smtp服务器发送指令,执行相关操作(如:登陆、发送邮件)。 该类提供了许多方法,将在下面介绍。它的所有参数都是可选的,其中host参数表示smtp服务器主机名,上面例子中的smtp主机 为"smtp.yeah.net";port表示smtp服务的端口,默认是25;如果在创建SMTP对象的时候提供了这两个参数,在初始化的时候会自动 调用connect方法去连接服务器。
  smtplib模块还提供了SMTP_SSL类和LMTP类,对它们的操作与SMTP基本一致。
  smtplib.SMTP提供的方法:

SMTP.set_debuglevel(level)

  设置是否为调试模式。默认为False,即非调试模式,表示不输出任何调试信息。

SMTP.connect([host[, port]])

  连接到指定的smtp服务器。参数分别表示smpt主机和端口。注意: 也可以在host参数中指定端口号(如:smpt.yeah.net:25),这样就没必要给出port参数。

SMTP.docmd(cmd[, argstring])

  向smtp服务器发送指令。可选参数argstring表示指令的参数。下面的例子完全通过调用docmd方法向服务器发送指令来实现邮件的发送(在smtp.yeah.net邮件服务器上试验通过。其他邮件服务器没有试过):

[python] view plain copy
  1. import smtplib, base64, time
  2. userName = base64.encodestring('from').strip()
  3. password = base64.encodestring('password').strip()
  4. smtp = smtplib.SMTP()
  5. smtp.connect("smtp.yeah.net:25")
  6. print smtp.docmd('helo', 'from')
  7. print smtp.docmd('auth login')
  8. print smtp.docmd(userName)
  9. print smtp.docmd(password)
  10. print smtp.docmd('mail from:', '<from@yeah.net>')
  11. print smtp.docmd('rcpt to:', '<from@yeah.net>')
  12. #data 指令表示邮件内容
  13. print smtp.docmd('data')
  14. print smtp.docmd('''''from: from@yeah.net
  15. to: from@yeah.net
  16. subject: subject
  17. email body
  18. .
  19. ''')
  20. smtp.quit()

SMTP.helo([hostname])

  使用"helo"指令向服务器确认身份。相当于告诉smtp服务器“我是谁”。

SMTP.has_extn(name)

  判断指定名称在服务器邮件列表中是否存在。出于安全考虑,smtp服务器往往屏蔽了该指令。

SMTP.verify(address)

  判断指定邮件地址是否在服务器中存在。出于安全考虑,smtp服务器往往屏蔽了该指令。

SMTP.login(user, password)

  登陆到smtp服务器。现在几乎所有的smtp服务器,都必须在验证用户信息合法之后才允许发送邮件。

SMTP.sendmail(from_addr, to_addrs, msg[, mail_options, rcpt_options])

  发送邮件。这里要注意一下第三个参数,msg是字符串,表示邮件。我们知道邮件一般由标题,发信人,收件人,邮件内容,附件等构成,发送邮件的时候,要注意msg的格式。这个格式就是smtp协议中定义的格式。在上面的例子中,msg的值为:

[python] view plain copy
  1. '''''From: from@yeah.net
  2. To: to@21cn.com
  3. Subject: test
  4. just for test'''

  这个字符串的的意思表示邮件发件人为"from@yeah.net",收件人为" to@21cn.com", 邮件标题为"test",邮件内容为"just for test"。细心的你可能会疑问:如果要发送的邮件内容很复杂,包含图片、视频、附件等内容,按照MIME的格式来拼接字符串,将是一件非常麻烦的事。不 用担心,python已经考虑到了这点,它为我们提供了email模块,使用该模块可以轻松的发送带图片、视频、附件等复杂内容的邮件。在介绍完 smtplib模块之后,我会简单介绍email模块的基本使用。

SMTP.quit()

  断开与smtp服务器的连接,相当于发送"quit"指令。

email及其相关子模块

  emial模块用来处理邮件消息,包括MIME和其他基于RFC 2822 的消息文档。使用这些模块来定义邮件的内容,是非常简单的。下面是一些常用的类:

classemail.mime.multipart.MIMEMultipart: 多个MIME对象的集合。

classemail.mime.audio.MIMEAudio: MIME音频对象。

classemail.mime.image.MIMEImage: MIME二进制文件对象。

classemail.mime.text.MIMEText: MIME文本对象。

  看上面的解释可能会觉得云里雾里,其实我对smtp, MIME的理解也很肤浅。但在大多数时候,我们只要会用就可以了。下面是一个简单的例子来演示如何使用这些类来发送带附件的邮件:

[python] view plain copy
  1. #coding=gbk
  2. import smtplib, mimetypes
  3. from email.mime.text import MIMEText
  4. from email.mime.multipart import MIMEMultipart
  5. from email.mime.image import MIMEImage
  6. msg = MIMEMultipart()
  7. msg['From'] = "from@yeah.net"
  8. msg['To'] = 'to@21cn.com'
  9. msg['Subject'] = 'email for tesing'
  10. #添加邮件内容
  11. txt = MIMEText("这是邮件内容~~")
  12. msg.attach(txt)
  13. #添加二进制附件
  14. fileName = r'e:/PyQt4.rar'
  15. ctype, encoding = mimetypes.guess_type(fileName)
  16. if ctype is None or encoding is not None:
  17. ctype = 'application/octet-stream'
  18. maintype, subtype = ctype.split('/', 1)
  19. att1 = MIMEImage((lambda f: (f.read(), f.close()))(open(fileName, 'rb'))[0], _subtype = subtype)
  20. att1.add_header('Content-Disposition', 'attachment', filename = fileName)
  21. msg.attach(att1)
  22. #发送邮件
  23. smtp = smtplib.SMTP()
  24. smtp.connect('smtp.yeah.net:25')
  25. smtp.login('from', '密码')
  26. smtp.sendmail('from@yeah.net', 'to@21cn.com', msg.as_string())
  27. smtp.quit()
  28. print '邮件发送成功'

  是不是很简单。简单就是美,用最少的代码把问题解决,这就是Python。更多关于smtplib的信息,请参考Python手册 smtplib模块。

___________________________________________________

Code Example:

'''
# -*- coding: cp936 -*-
# 甄码农,20120307
import smtplib
from email.mime.text import MIMEText
 
mail_host = 'smtp.126.com'
mail_user = 'xxx@126.com'
mail_pwd = 'hellopwd'
mail_to = 'xxao@gmail.com'
mail_cc = 'xx@xx.com'          
mail_bcc = 'xx@qq.com'
content = 'this is a mail sent with python'
 
#表头信息
msg = MIMEText(content)
msg['From'] = mail_user
msg['Subject'] = 'this is a python test mail'
msg['To'] = mail_to
msg['Cc'] = mail_cc
msg['Bcc'] = mail_bcc
try:
    s = smtplib.SMTP()
    s.connect(mail_host)
    #login
    s.login(mail_user,mail_pwd)
 
    #send mail
    s.sendmail(mail_user,[mail_to,mail_cc,mail_bcc],msg.as_string())
    s.close()
    print 'success'
except Exception ,e:
    print e
'''

转载于:https://my.oschina.net/alphajay/blog/123504

python的smtplib相关推荐

  1. Python发送邮件smtplib.SMTP各报错问题的解决方法

    Python发送邮件smtplib.SMTP各报错问题的解决方法 参考文章: (1)Python发送邮件smtplib.SMTP各报错问题的解决方法 (2)https://www.cnblogs.co ...

  2. Python 用smtplib库发邮件报错:[WinError 10061] 由于目标计算机积极拒绝,无法连接。解决办法

    看了菜鸟的教程,有这段代码: mail = smtplib.SMTP("localhost") 然后就报错了.菜鸟的教程太老了,Python迭代这么快,根本跟不上. 把这个里面的参 ...

  3. Python+request+ smtplib 测试结果html报告邮件发送(上)《五》

    此方法通用适合所有邮箱的使用,只需注意几个点,如下: QQ邮箱.其他非QQ邮箱的写法,区别点如下: #--------------------------使用腾讯企业邮箱作为发件人的操作如下----- ...

  4. [Python] [邮件发送] 用Python的smtplib和email库进行邮件发送

    目录 1.Intro 2.Details 3.Theory 4.Environment 5.Source 6.Conclusion 1.Intro 眼看就到了12月中旬,除了帮朋友码竞赛题,前半个月可 ...

  5. email邮件中 内嵌iframe_邮件发送,使用Python中 smtplib与email 模块实现自动发送QQ邮件...

    在 Python 的实际应用中,特别是在执行周期性定时任务的场景中,我们希望能够一种简单.方便的方式获取任务的运行结果和状态.一般我们通过支持邮件发送功能的方式,实现任务结果的反馈.本文主要介绍,如何 ...

  6. python:smtplib --- SMTP 协议客户端

    python:smtplib --- SMTP 协议客户端 简介 SMTP 对象 SMTP 示例 简介 smtplib 模块定义了一个 SMTP 客户端会话对象,该对象可将邮件发送到互联网上任何带有 ...

  7. 使用Python的smtplib模块发送带附件的邮件

      上一篇文章<使用Python的smtplib模块发送简单邮件>介绍了调用smtplib模块发送包含简单内容的邮件,本文继续学习参考文献1中的发送带附件的邮件的示例代码,同时由于参考文献 ...

  8. smtplib python_伪造邮件发件人系列:一、python之smtplib库

    这两日用到了python的发送邮件功能,恰好又想起来wordpress发送给我的邮件都是形如wordpress@leniy.info 的虚拟地址,于是我就上网查找了下伪造邮件发件人的方案.网上这些资料 ...

  9. Python通过smtplib发送邮件(2020最新最全版)

    smtplib 邮件自动发送 SMTP(Simple Mail Transfer Protocol)即简单邮件传输协议,它是一组用于由源地址到目的地址传送邮件的规则,由它来控制信件的中转方式. pyt ...

  10. 【Python】Smtplib正确模拟发送QQ邮件

    以前也试过模拟发Email,但好像都忘了,于是按照菜鸟教程重新试了一下: import smtplib from email.mime.text import MIMEText from email. ...

最新文章

  1. 雷军深情告白:在我心里,武汉大学是全球最好的大学
  2. MATLAB_no.1:入门作业_histeq():_imhist()_(男孩的三个图,以及文字描述)
  3. java中垃圾收集_Java中的垃圾收集器是什么?
  4. abcde依次进入一个队列_详解队列队形及口令(新教师必看)
  5. 唐山师范学院计算机宿舍,唐山师范学院宿舍条件怎么样宿舍图片内景
  6. 【报告分享】2020中国消费品牌发展报告.pdf(附下载链接)
  7. 软件工程师的技能知识图谱0.2
  8. 【揭秘】一个小团队真正能落地的微服务架构实践
  9. 编写一个java小程序输出学生姓名在Unicode表中的位置
  10. 2019数据安装勾选_【登陆、勾选、签名......,你在发票平台遇到的各类问题这里都有答案!】增值税发票综合服务平台常见问题整理(一)...
  11. 管家婆mysql 数据库_Java数据库小项目02--管家婆项目
  12. 期货交易结算信息(期货结算系统)
  13. 给eclipse添加字体
  14. Keil_uvision 基本使用教程
  15. 虚拟机VMware的安装和Ubuntu安装过程
  16. win7 蓝牙4.0 ble驱动_恩智浦发布行业领先的2x2 Wi-Fi 6 +蓝牙解决方案,彻底改变游戏、音频、工业和物联网市场...
  17. python中文居中对齐处理
  18. CentOS下mysql 8.0.16 安装完整版教程
  19. 【C语言】指针终结者-初阶
  20. ZZULIOJ 2327: 打印图形

热门文章

  1. AIX ksh使用小技巧
  2. android webview richeditor,GitHub - IllegalCreed/react-native-webview-richeditor
  3. golang 程序休眠_golang package time的用法具体详解
  4. HTML和CSS面试题
  5. PHP Mysql or条件排序问题
  6. Git 输入命令git branch -a 后怎么返回
  7. Layui数据表格动态cols(字段)动态变化(2)
  8. CENTOS安装后没有图形界面GUI,怎么办?
  9. 使用Rufus制作安装U盘报错,使用UltraISO成功
  10. LINUX下载编译uuid