smtplib_smtplib安装 - CSDN
精华内容
参与话题
  • smtplib模块学习

    千次阅读 2016-11-07 15:18:35
    python的smtplib提供了一种很方便的途径发送电子邮件。它对smtp协议进行了简单的封装。 smtp协议的基本命令包括:  HELO 向服务器标识用户身份  MAIL 初始化邮件传输 mail from:  RCPT 标识单个的邮件接收人...

    原文章地址:点击打开链接


    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和email模块详解

    万次阅读 多人点赞 2018-09-06 18:20:56
    在介绍具体的实现python发邮件的具体操作之前,我觉得有必要介绍下SMTP,更有助于理解python发邮件的实现原理。SMTP协议属于TCP/IP协议簇,即简单邮件传输协议,它是一组用于由源地址到目的地址传送邮件的规则,由它...

    在介绍具体的实现python发邮件的具体操作之前,我觉得有必要介绍下SMTP,更有助于理解python发邮件的实现原理。SMTP协议属于TCP/IP协议簇,即简单邮件传输协议,它是一组用于由源地址到目的地址传送邮件的规则,由它来控制信件的中转方式,python实现发邮件也是基于此基础上进行封装的。

    1.python发邮件所需要的基础包

    python发送邮件需要用到python自带的两个模块,smtplib和email。直接import导入,无需下载。
    python的smtplib提供了一种很方便的途径发送电子邮件,它对smtp协议进行了简单的封装。

    2.smtplib的用法

    smtplib用法相对来说很简单,就是分为两步。

    • 创建SMTP的操作对象并连接smtp目标服务器,可以是163、QQ等
    • 根据自己的账号登录目标服务器(自己的邮箱地址和邮箱授权码)
    • 调用对象中的方法,发送邮件到目标地址

    python与smtp服务器之间的具体交互的通用代码:

    import smtplib
    server = smtplib.SMTP(mailserver, port)  # 发件人邮箱中的SMTP服务器,端口是25
    server.login(sender, passwd)  # 发件人邮箱账号、邮箱授权码
    # msg.as_string()中as_string()是将msg(MIMEText或MIMEMultipart对象)变为str。
    server.sendmail(sender, receive, msg.as_string())  
    server.quit()

    具体的python连接目标服务器的代码如下:注:本文章用的是qq的smtp服务器。
    常用邮箱的smtp服务器地址:
    新浪邮箱:smtp.sina.com,搜狐邮箱:smtp.sohu.com,qq邮箱:smtp.qq.com

    sender_maile='80617252@qq.com' # 发送方的邮箱地址
    sender_pass = 'lsjdfsljdfk' # 邮箱提供的授权码,可在第三方登录,我这个是随便打的。
    sftp_obj =smtplib.SMTP('smtp.qq.com', 25)
    sftp_obj.login(sender_mail, sender_pass)
    #三个参数分别是:发件人邮箱账号,收件人邮箱账号,发送的邮件体
    sftp_obj.sendmail(sender_mail, receiver_mail, msg_root.as_string())
    sftp_obj.quit()
    3.email模块的详细理解和使用

    email模块下的mime模块下有常用的三个模块,三个模块中有三个大类。其实就是下边这三个了,说的很绕,下边为导入方式,一目了然。

    from email.mime.text import MIMEText    
    from email.mime.image import MIMEImage
    from email.mime.multipart import MIMEMultipart    

    简单说下他们的关系,如果构造一个MIMEText对象,就表示一个文本邮件对象,如果构造一个MIMEImage对象,就表示一个作为附件的图片对象,要把多个对象组合起来,就用MIMEMultipart对象,他代表的是整个邮件。这样说应该还不是很清晰,下边就分开来说,最后会总的总结,在最后边就是完整的代码(可以发送一切内容的代码)。

    A.MIMEText对象中有三个需要我们设置的参数,一个是正文内容,一个是正文内容的类型,例如:”text/plain”和”text/html”,一个是正文内容的编码。

    构造普通文本:

    text_info = 'hello world '
    text_sub = MIMEText(text_info,'plain', 'utf-8')  

    构造超文本:

    url = "https://blog.csdn.net/chinesepython"
    html_info = """
        <p>点击以下链接,你会去向一个更大的世界</p>
        <p><a href="%s">click me</a></p>
        <p>i am very glasses for you</p>
        """ % url
    html_sub = MIMEText(html_info, 'html', 'utf-8')  
    # 如果不加下边这行代码的话,上边的文本是不会正常显示的,会把超文本的内容当做文本显示
    html_sub["Content-Disposition"] = 'attachment; filename="csdn.html"'

    构造base64数据流,用于发送文件的时候使用,构造附件代码:

    txt_file = open(r'D:\python_files\files\hello_world.txt', 'rb').read()
    txt = MIMEText(txt_file, 'base64', 'utf-8')
    txt["Content-Type"] = 'application/octet-stream'
    # 命名发送的附件
    txt.add_header('Content-Disposition', 'attachment', filename='hello_world.txt')
    B.MIMEImage对象中只需要把读取的文件传入就行

    构造图片:

    image_file = open(r'D:\python_files\images\test.png', 'rb').read()
    image = MIMEImage(image_file)
    image.add_header('Content-ID', '<image1>')
    # 命名发送的图片
    image["Content-Disposition"] = 'attachment; filename="red_people.png"'
    C.MIMEMultipart对象创建的类型有三种,此模块主要是通过attach方法把上边构造的内容传入到邮件的整体内容中。
    • 邮件类型为”multipart/alternative”的邮件正文中包括纯文本正文(text/plain)和超文本正文(text/html)。
    • 邮件类型为”multipart/related”的邮件正文中包括图片,声音等内嵌资源。
    • 邮件类型为”multipart/mixed”的邮件包含附件,图片,文本等都可以添加,所以发的内容多的话一般是用这个的,选择mixed类型,什么内容都可以发。
    3.邮件头添加内容

    直接上示例代码:

    from email.mime.multipart import MIMEMultipart
    
    
    msg_root = MIMEMultipart('mixed')
    # 发件人
    msg_root['From'] = 'aaa@qq.com<aaa@qq.com>'
    # 收件人
    msg_root['To'] = '666666@qq.com'
    # 邮件主题
    subject = 'python sendemail test successful'
    msg_root['subject'] = Header(subject, 'utf-8')
    
    4.特别的用法说明:

    注:以下的msg_root为:
    msg_root = MIMEMultipart(‘mixed’)

    msg_root.as_string()是将msg_root对象变为str。
    msg_root.attach(MIMEText或者MIMEImage对象),因为MIMEMultipart对象代表邮件本身,其他连个是代表邮件正文,所以这个方法还是很强大的,把其他的构造内容添加到MIMEMultipart对象中就可以把文本,html,附件等一起发送了。

    5.发送各种内容的具体代码实现:

    所有代码合到一块,发送文本,html,图片,txt内容,用的时候你可以把需要的部分摘出来,也就是把没有加入到msg_root的对象拿出来,直接通过下边命令发送,例如只发送文本。
    sftp_obj.sendmail(sender_mail, receiver_mail, text_sub.as_string())。

    import smtplib
    from email.header import Header
    from email.mime.text import MIMEText
    from email.mime.image import MIMEImage
    from email.mime.multipart import MIMEMultipart
    
    
    def send_email_by_qq(to):
        sender_mail = '80617252@qq.com'
        sender_pass = 'aljflsjdf'#同样是乱打的
    
        # 设置总的邮件体对象,对象类型为mixed
        msg_root = MIMEMultipart('mixed')
        # 邮件添加的头尾信息等
        msg_root['From'] = '80617252@qq.com<80617252@qq.com>'
        msg_root['To'] = to
        # 邮件的主题,显示在接收邮件的预览页面
        subject = 'python sendemail test successful'
        msg_root['subject'] = Header(subject, 'utf-8')
    
        # 构造文本内容
        text_info = 'hello world'
        text_sub = MIMEText(text_info, 'plain', 'utf-8')
        msg_root.attach(text_sub)
    
        # 构造超文本
        url = "https://blog.csdn.net/chinesepython"
        html_info = """
        <p>点击以下链接,你会去向一个更大的世界</p>
        <p><a href="%s">click me</a></p>
        <p>i am very galsses for you</p>
        """% url
        html_sub = MIMEText(html_info, 'html', 'utf-8')
        # 如果不加下边这行代码的话,上边的文本是不会正常显示的,会把超文本的内容当做文本显示
        html_sub["Content-Disposition"] = 'attachment; filename="csdn.html"'   
        # 把构造的内容写到邮件体中
        msg_root.attach(html_sub)
    
        # 构造图片
        image_file = open(r'D:\python_files\images\test.png', 'rb').read()
        image = MIMEImage(image_file)
        image.add_header('Content-ID', '<image1>')
        # 如果不加下边这行代码的话,会在收件方方面显示乱码的bin文件,下载之后也不能正常打开
        image["Content-Disposition"] = 'attachment; filename="red_people.png"'
        msg_root.attach(image)
    
        # 构造附件
        txt_file = open(r'D:\python_files\files\hello_world.txt', 'rb').read()
        txt = MIMEText(txt_file, 'base64', 'utf-8')
        txt["Content-Type"] = 'application/octet-stream'
        #以下代码可以重命名附件为hello_world.txt  
        txt.add_header('Content-Disposition', 'attachment', filename='hello_world.txt')
        msg_root.attach(txt)
    
        try:
            sftp_obj =smtplib.SMTP('smtp.qq.com', 25)
            sftp_obj.login(sender_mail, sender_pass)
            sftp_obj.sendmail(sender_mail, to, msg_root.as_string())
            sftp_obj.quit()
            print('sendemail successful!')
    
        except Exception as e:
            print('sendemail failed next is the reason')
            print(e)
    
    
    if __name__ == '__main__':
        # 可以是一个列表,支持多个邮件地址同时发送,测试改成自己的邮箱地址
        to = '666666@qq.com'
        send_email_by_qq(to)
    6.总结

    为了让不是很理解发邮件的朋友能更好的理解,在这里是把所有的参数都写死了,比如说发送文件的具体内容,在真正开发使用过程中,可以把具体的内容通过预留出来参数去传入之后发送你想要发送的内容。
    发邮件功能还是很实用的,在真正的开发中或者大多数场合都能用到,比如说项目中一个重要的模块如果出问题了,你需要第一时间知道,就可以加入这个功能,把项目出问题报的具体内容发到你的邮箱,也可以第一时间想下处理的对策。
    下面以我通过此程序发送的邮件内容的截图做结尾吧。
    这里写图片描述

    展开全文
  • 转载请注明原文出自 http://blog.csdn.net/zhaoweikid/ python的smtplib提供了一种很方便的途径发送电子邮件。它对smtp协议进行了简单的封装。smtp协议的基本命令包括: HELO 向服务器标识用户身份 MAIL 初始化...
        转载请注明原文出自 http://blog.csdn.net/zhaoweikid/
        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模块发送邮件

    千次阅读 2018-06-22 16:15:10
      在使用django/flask时,框架本身已经为我们封装好了发送邮件的函数,python的smtplib提供了一种很方便的途径发送电子邮件。它对smtp协议进行了简单的封装。 对于smtp的使用相对来说比较简单,代码如下: 一...

      在使用django/flask时,框架本身已经为我们封装好了发送邮件的函数,python的smtplib提供了一种很方便的途径发送电子邮件。它对smtp协议进行了简单的封装。

    对于smtp的使用相对来说比较简单,代码如下:

    一、发送文本内容

    直接使用smtplib发送文本内容,以下两步是使用smtplib发送任何形式邮件都可以遵循的。

    1. 准备工作

    构建邮件内容, From(发件人)、To(收件人)、Subject(邮件标题)和Text(邮件内容)。

    import smtplib
    import string
    
    
    smtpserver = 'smtp.163.com'     # 邮件smtp的地址
    subject = '这是邮件标题'         # 定义邮件的标题
    sender = 'youremail@163.com'    # 发件人
    receiver = 'toemail@qq.com'     # 收件人
    msg = '这是一封测试邮件,由<%s>发出'%From  # 发送的邮件文本内容
    msg_content = '\r\n'.join(['From:%s'%sender, 'To:%s'%receiver, 'Subject:%s'%subject, '', msg])
    

    2. 构造SMTP对象发送邮件

    smtp_server = smtplib.SMTP()       # 构造smtp服务对象,可以在构造对象时将host和port传入直接连接服务器
    smtp_server.set_debuglevel(1)                  # 开启发送debug模式,把发送邮件的过程显示出来
    smtp_server.connect(host=smtpserver, port='25')           # 连接邮箱服务器,端口可以不写,默认为25
    smtp_server.starttls()                                             # 启动安全传输模式
    smtp_server.login(FROM, 'yourpassword')                            # 登录邮箱服务器
    smtp_server.sendmail(from_addr=sender, to_addrs=receiver, msg=msg_content) # 发送邮件
    smtp_server.quit()                                                 # 关闭smtp服务器连接
    

    二、使用email模块发送多样化的内容

      email模块配合smtplib进行邮件的发送和接收,包含自定义邮件的中文、主题、日期、附件等信息,具体概念及其函数参考官方文档,链接奉上https://docs.python.org/3/library/email.html#module-email
    如果要使用email模块的功能,可以参考网上的以下7个例子:

    1. 文件形式的邮件

    import smtplib  
    from email.mime.text import MIMEText  
    from email.header import Header  
    
    sender = '***'  
    receiver = '***'  
    subject = 'python email test'  
    smtpserver = 'smtp.163.com'  
    username = '***'  
    password = '***'  
    
    msg = MIMEText('你好','text','utf-8') # 中文需参数‘utf-8',单字节字符不需要  
    msg['Subject'] = Header(subject, 'utf-8')  
    
    smtp = smtplib.SMTP()  
    smtp.connect('smtp.163.com')  
    smtp.login(username, password)  
    smtp.sendmail(sender, receiver, msg.as_string())  
    smtp.quit()  
    

    2. html形式的邮件

    import smtplib  
    from email.mime.text import MIMEText  
    
    sender = '***'  
    receiver = '***'  
    subject = 'python email test'  
    smtpserver = 'smtp.163.com'  
    username = '***'  
    password = '***'  
    
    msg = MIMEText('</pre>  
    <h1>你好</h1>  
    <pre>','html','utf-8')   
    
    msg['Subject'] = subject   
    
    smtp = smtplib.SMTP()  
    smtp.connect('smtp.163.com')  
    smtp.login(username, password)  
    smtp.sendmail(sender, receiver, msg.as_string())  
    smtp.quit()  
    

    3. 带图片的html邮件

    import smtplib  
    from email.mime.multipart import MIMEMultipart  
    from email.mime.text import MIMEText  
    from email.mime.image import MIMEImage   
    
    sender = '***'  
    receiver = '***'  
    subject = 'python email test'  
    smtpserver = 'smtp.163.com'  
    username = '***'  
    password = '***'   
    
    msgRoot = MIMEMultipart('related')  
    msgRoot['Subject'] = 'test message'   
    
    msgText = MIMEText('<b>Some <i>HTML</i> text</b> and an image.  
    <img alt="" src="cid:image1" />  
    good!','html','utf-8')  
    msgRoot.attach(msgText)   
    
    fp = open('h:\\python\\1.jpg', 'rb')  
    msgImage = MIMEImage(fp.read())  
    fp.close()   
    
    msgImage.add_header('Content-ID', '')  
    msgRoot.attach(msgImage)   
    
    smtp = smtplib.SMTP()  
    smtp.connect('smtp.163.com')  
    smtp.login(username, password)  
    smtp.sendmail(sender, receiver, msgRoot.as_string())  
    smtp.quit()  
    

    4. 带附件的邮件

    import smtplib  
    from email.mime.multipart import MIMEMultipart  
    from email.mime.text import MIMEText  
    from email.mime.image import MIMEImage   
    
    sender = '***'  
    receiver = '***'  
    subject = 'python email test'  
    smtpserver = 'smtp.163.com'  
    username = '***'  
    password = '***'   
    
    msgRoot = MIMEMultipart('related')  
    msgRoot['Subject'] = 'test message'   
    
    #构造附件  
    att = MIMEText(open('h:\\python\\1.jpg', 'rb').read(), 'base64', 'utf-8')  
    att["Content-Type"] = 'application/octet-stream'  
    att["Content-Disposition"] = 'attachment; filename="1.jpg"'  
    msgRoot.attach(att)   
    
    smtp = smtplib.SMTP()  
    smtp.connect('smtp.163.com')  
    smtp.login(username, password)  
    smtp.sendmail(sender, receiver, msgRoot.as_string())  
    smtp.quit()  
    

    5. 群邮件

    import smtplib  
    from email.mime.text import MIMEText   
    
    sender = '***'  
    receiver = ['***','****',……]  
    subject = 'python email test'  
    smtpserver = 'smtp.163.com'  
    username = '***'  
    password = '***'   
    
    msg = MIMEText('你好', 'text', 'utf-8')   
    
    msg['Subject'] = subject   
    
    smtp = smtplib.SMTP()  
    smtp.connect('smtp.163.com')  
    smtp.login(username, password)  
    smtp.sendmail(sender, receiver, msg.as_string())  
    smtp.quit()  
    

    6. 包含各种元素的邮件

    import smtplib  
    from email.mime.multipart import MIMEMultipart  
    from email.mime.text import MIMEText  
    from email.mime.image import MIMEImage   
    
    sender = '***'  
    receiver = '***'  
    subject = 'python email test'  
    smtpserver = 'smtp.163.com'  
    username = '***'  
    password = '***'   
    
    # Create message container - the correct MIME type is multipart/alternative.  
    msg = MIMEMultipart('alternative')  
    msg['Subject'] = "Link"   
    
    # Create the body of the message (a plain-text and an HTML version).  
    text = "Hi!\nHow are you?\nHere is the link you wanted:\nhttp://www.python.org"  
    html = """\ 
    
    
    Hi! 
    
           How are you? 
    
           Here is the <a href="http://www.python.org">link</a> you wanted. 
    
    
    
    """   
    
    # 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.  
    msg.attach(part1)  
    msg.attach(part2)  
    #构造附件  
    att = MIMEText(open('h:\\python\\1.jpg', 'rb').read(), 'base64', 'utf-8')  
    att["Content-Type"] = 'application/octet-stream'  
    att["Content-Disposition"] = 'attachment; filename="1.jpg"'  
    msg.attach(att)   
    
    smtp = smtplib.SMTP()  
    smtp.connect('smtp.163.com')  
    smtp.login(username, password)  
    smtp.sendmail(sender, receiver, msg.as_string())  
    smtp.quit()  
    

    7. 基于ssl的邮件

    import smtplib  
    from email.mime.text import MIMEText  
    from email.header import Header  
    sender = '***'  
    receiver = '***'  
    subject = 'python email test'  
    smtpserver = 'smtp.163.com'  
    username = '***'  
    password = '***'   
    
    msg = MIMEText('你好','text','utf-8') # 中文需参数‘utf-8',单字节字符不需要  
    msg['Subject'] = Header(subject, 'utf-8')   
    
    smtp = smtplib.SMTP()  
    smtp.connect('smtp.163.com')  
    smtp.ehlo()  
    smtp.starttls()  
    smtp.ehlo()  
    smtp.set_debuglevel(1)  
    smtp.login(username, password)  
    smtp.sendmail(sender, receiver, msg.as_string())  
    smtp.quit()  
    
    展开全文
  • 使用smtplib库发送邮件

    千次阅读 2019-06-14 19:46:27
    以下代码经过测试,代码如下: from email.mime.text import MIMEText ...import smtplib # smtp服务器以及相关配置信息 smtp_server = 'smtp.163.com' from_addr = 'XXXX@163.com' password = 'XXXXXX' #...
  • smtplib来发送邮件

    千次阅读 2018-07-13 22:00:48
    先安装pip install smtplib发送qq,163邮件,带有附件的邮件1.qq邮件# 用于发送邮件的模块 import smtplib # QQ邮箱/163邮箱的邮件发送:py文件发送邮件内容相当于一个第三方的客户端,借助于QQ/163邮箱服务器来发送...
  • PYTHON模块学习之smtplib

    万次阅读 2012-06-13 13:45:42
    python的smtplib提供了一种很方便的途径发送电子邮件。它对smtp协议进行了简单的封装。 smtp协议的基本命令包括:  HELO 向服务器标识用户身份  MAIL 初始化邮件传输 mail from:  RCPT 标识单个的邮件接收人...
  • smtplib模块

    千次阅读 2019-05-24 16:36:26
    smtplib模块 python实现发邮件使用到的是smtplib模块。 import smtplib # smtp 服务 import email.mime.multipart # 处理邮件头部信息的函数 import email.mime.text # 处理发送的文本函数 emai_user = '19...
  • python模块学习 ---- smtplib 邮件发送

    万次阅读 2009-07-08 09:11:00
    在基于互联网的应用中,程序经常...smtplib模块是python中smtp(简单邮件传输协议)的客户端实现。我们可以使用smtplib模块,轻松的发送电子邮件。下面的例子用了不到十行代码来发送电子邮件:#coding=gbkimport smtplib
  • python pip安装smtplib库的方法

    万次阅读 2020-10-18 22:04:46
    **首先是:pip search smtplib 然后会出现很多的可供选择的库,按照需要下载就好了** PyEmail (0.0.1) - Python library to send emails using SMTPLIB library micropython-smtplib (0.0.0) - Dummy smtplib ...
  • 通过smtplib发送邮件时,报错module 'smtplib' has no attribute 'SMTP'一个可能的原因的文件的名字是email.py,需要改一个其他的名字就行。
  • Py之smtplibsmtplib(aiosmtplib)的简介、安装、使用方法之详细攻略 目录 smtplib(aiosmtplib)的简介 smtplib(aiosmtplib)的安装 smtplib(aiosmtplib)的使用方法 smtplib(aiosmtplib)的...
  • smtplib.SMTPDataError: 554, 'DT:SPM

    万次阅读 2015-09-28 13:33:55
    smtplib使用心得
  • import smtplib from email.mime.text import MIMEText # 第三方 SMTP 服务 mail_host = "smtp.163.com" # SMTP服务器 mail_user = "username" # 用户名 mail_pass = "passwd" # ...
  • python smtplib.SMTPAuthenticationError: (535, b’Error: authentication failed’) 出现这个问题: 运行报错: 解决办法使用163邮箱服务器来发送邮件,我们需要去163邮箱开启POP3/SMTP服务,这时163邮件会让我们...
  • smtplib.SMTPDataError: (554, b'DT:SPM的异常

    万次阅读 2019-08-16 09:08:08
    python 发送邮件,出现如下...smtplib.SMTPDataError: (554, b'DT:SPM 163 smtp12,EMCowxxn7yO5rI9bT0uuEg--.45230S2 1226142521,please see http://mail.163.com/help/help_spam_16.htm?ip=133.13.132.12&hos...
  • 解决smtplib.SMTPServerDisconnected: Connection unexpectedly closed问题
  • 先把问题的callback贴一下,linux环境下提示AttributeError: module 'smtplib' has no attribute 'SMTP' Traceback (most recent call last): File "/home/roy/python/email.py", line 1, in &lt;...
  • python使用邮件出现module 'smtplib' has no attribute 'SMTP_SSL'报错问题,通过安装相关依赖解决
  • smtplib发送带SSL认证的邮箱系统

    千次阅读 2016-11-19 14:42:39
    应朋友需要,做一个能从excel读取 发送人 发送主题 发送内容的一个小工具 当前查阅了下 发送待SSL认证的邮箱系统,先实现发送邮件的方式,其余待后续开发: 代码正文如下(本代码主要基于腾讯企业...from smtplib i
1 2 3 4 5 ... 20
收藏数 10,306
精华内容 4,122
关键字:

smtplib