对码当歌,猿生几何?

Python学习笔记---网络(net)编程(- TCP/UDP协议(SOCKET-UDP-TCP 编程)-- FTP 编程-- Mail 编程)

网络编程

  • 网络:

  • 网络协议:一套规则

  • 网络模型:

    • 链路层

    • 网络

    • 传输层

    • 应用层

    • 物理层

    • 数据链路层

    • 网络层

    • 传输层

    • 会话层

    • 表示层

    • 应用层

    • 七层模型:

    • 四层模型-实际应用

    • 每一层都有相应的协议负责交换信息或者协同工作

    • TCP/IP 协议族

    • IP地址:负责在网络上唯一定位一个机器

      • IP地址分ABCDE类

      • 是由四个数字段组成,每个数字段的取值是0-255

      • 192.168.xxx.xxx:局域网ip

      • 127.0.0.1:本机

      • IPv4,IPv6

    • 端口

      • 范围:0-65535

      • 知名端口:0-1023

      • 非知名端口:1024-

    TCP/UDP协议

    • UDP:非安全的不面向链接的传输

      • 安全性差

      • 大小限制64kb

      • 没有顺序

      • 速度快

    • TCP

      • 基于链接的通信

    • SOCKET 编程

      • socket(套接字): 是一个网络通信的端点, 能实现不同主机的进程通信,网络大多基于Socket通信

      • 通过IP+端口定位对方并发送消息的通信机制

      • 分为UDP和TCP

      • 客户端Client:发起访问的一方

      • 服务器端Server:接受访问的一方

    • UDP 编程

      • 1.建立通信的socket

      • 2.发送内容到指定服务器

      • 3.接受服务器给定的反馈内容

      • 1.建立socket,socket是负责具体通信的一个实例

      • 2.绑定,为创建的socket指派固定的端口和IP地址

      • 3.接受对方发送内容

      • 4.给对方发送反馈,次步骤为非必须步骤

      • Server端流程:

      • Client端流程:

      • 服务器案例v1.py

      • '''
        Server端流程
         1. 建立socket,socket是负责具体通信的一个实例
         2. 绑定,为创建的socket指派固定的端口和ip地址
         3. 接受对方发送内容
         4. 给对方发送反馈,此步骤为非必须步骤
        '''
        
        # socket模块负责socket编程
        import socket
        
        # 模拟服务器的函数
        def serverFunc():
            # 1.建立socket
        
            # socket.AF_INET:使用IPv4协议族
            # socket.SOCK_DGRAM:使用UDP通信
            sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        
            # 2.绑定IP和port
            # 127.0.0.1:这个IP地址代表的是机器本身
            # 端口:7852:随手指定的端口
            # 地址是一个tuple类型,(ip, port)
            addr = ("127.0.0.1", 8125)
            sock.bind(addr)
        
            # 3.接受对方消息
            # 等待方式为死等,没有任何其他可能性
            # recvfrom接受的返回值是一个元组,前一项表示数据,后一项表示地址
            # 参数的含义是缓冲区大小
            # rst = sock.recvfrom(500)
            data, addr = sock.recvfrom(500)
        
            print(data)
            print(type(data))
        
            # 发送过来的数据是bytes格式,必须通过解码才能得到str格式内容
            # decode默认参数是utf8
            text = data.decode()
            print(type(text))
            print(text)
        
            # 给对方返回的消息
            rsp = "Ich hab keine Hunge"
        
            # 发送的数据需要编码成bytes格式
            # 默认是utf8
            data = rsp.encode()
            sock.sendto(data, addr)
        
        if __name__ == "__main__":
            print("Starting server....")
            serverFunc()
            print("Ending server....")
      • 客户端案例v2.py

        '''
        - Client端流程
                    1. 建立通信的socket
                    2. 发送内容到指定服务器
                    3. 接受服务器给定的反馈内容
        '''
        
        import socket
        def clientFunc():
            sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        
            text = "I love feifei"
        
            # 发送的数据必须是bytes
            data = text.encode()
        
            # 发送
            sock.sendto(data, ("127.0.0.1", 8125))
        
            data, addr = sock.recvfrom(200)
        
            data = data.decode()
            print(data)
        
        if __name__ == "__main__":
            clientFunc()
      • 服务器程序要求永久运行,一般用死循环处理

      • 改造的服务器版本v3.py

        # socket模块负责socket编程
        import socket
        
        # 模拟服务器的函数
        def serverFunc():
            # 1. 建立socket
        
            # socket.AF_INET:使用ipv4协议族
            # socket.SOCK_DGRAM: 使用UDP通信
            sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        
            # 2. 绑定ip和port
            # 127.0.0.1: 这个ip地址代表的是机器本身
            # 7852: 随手指定的端口号
            # 地址是一个tuple类型,(ip, port)
            addr = ("127.0.0.1", 7852 )
            sock.bind( addr )
        
        
            # 接受对方消息
            # 等待方式为死等, 没有其他可能性
            # recvfrom接受的返回值是一个tuple,前一项表示数据,后一项表示地址
            # 参数的含义是缓冲区大小
            # rst = sock.recvfrom(500)
            data, addr = sock.recvfrom(500)
        
            print(data)
            print(type(data))
        
            # 发送过来的数据是bytes格式,必须通过解码才能得到str格式内容
            # decode默认参数是utf8
            text = data.decode()
            print(type(text))
            print(text)
        
        
            # 给对方返回的消息
            rsp = "Ich hab keine Hunge"
        
            # 发送的数据需要编码成bytes格式
            # 默认是utf8
            data = rsp.encode()
            sock.sendto(data, addr)
        
        
        if __name__ == '__main__':
            import time
            while 1:
                try:
                    serverFunc()
                except Exception as e:
                    print(e)
        
                time.sleep(1)
      • TCP编程

        • a.建立通信socket

        • b.链接对方,请求跟对方建立通路

        • c.发送内容到对方服务器

        • d.接收对方的反馈

        • e.关闭链接通路

        • a.建立socket负责具体通信,这个socket其实只负责接收对方的请求,真正通信的是链接后重新建立的socket

        • b.绑定端口和地址

        • c.监听接入的访问socket

        • d.接收访问的socket,可以理解接收访问即建立了一个通讯的链接通路

        • e.接收对方的发送内容,利用接收到的socket接收内容

        • f.如果有必要,给对方发送反馈消息

        • g.关闭链接通路

        • 面向链接的传输,即每次传输之前需要建立一个链接

        • 客户端和服务器端两个程序需要编写

        • Server端的编写流程

        • Client端流程

        • 案例v4.py

          import socket
          def  tcp_srv():
              # 1. 建立socket负责具体通信,这个socket其实只负责接受对方的请求,真正通信的是链接后从新建立的socket
              # 需要用到两个参数
              # AF_INET: 含义同udp一致
              # SOCK_STREAM: 表明是使用的tcp进行通信
              sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
              # 2. 绑定端口和地址
              # 此地址信息是一个元祖类型内容,元祖分两部分,第一部分为字符串,代表ip,第二部分为端口,是一个整数,推荐大于10000
              addr = ("127.0.0.1", 8998)
              sock.bind(addr)
              # 3. 监听接入的访问socket
              sock.listen()
          
              while True:
                  # 4. 接受访问的socket,可以理解接受访问即建立了一个通讯的链接通路
                  # accept返回的元祖第一个元素赋值给skt,第二个赋值给addr
                  skt,addr = sock.accept()
                  # 5. 接受对方的发送内容,利用接收到的socket接收内容
                  # 500代表接收使用的buffersize
                  #msg = skt.receive(500)
                  msg = skt.recv(500)
                  # 接受到的是bytes格式内容
                  # 想得到str格式的,需要进行解码
                  msg = msg.decode()
          
                  rst = "Received msg: {0} from {1}".format(msg, addr)
                  print(rst)
                  # 6. 如果有必要,给对方发送反馈信息
                  skt.send(rst.encode())
          
                  # 7. 关闭链接通路
                  skt.close()
          
          
          if __name__ == "__main__":
              print("Starting tcp server.......")
              tcp_srv()
              print("Ending tcp server.......")
        • 案例v5.py

          import socket
          
          def tcp_clt():
              # 1. 建立通信socket
              sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
              # 2. 链接对方,请求跟对方建立通路
              addr = ("127.0.0.1", 8998)
              sock.connect(addr)
              # 3. 发送内容到对方服务器
              msg = "I love wangxiaojing"
              sock.send(msg.encode())
              # 4. 接受对方的反馈
              rst =  sock.recv(500)
              print(rst.decode())
              # 5. 关闭链接通路
              sock.close()
          
          
          if __name__ == "__main__":
              tcp_clt()

        FTP编程

        • FTP(FileTransferProtocal)文件传输协议

        • 用途:定制一些特殊的上传下载文件的服务

        • 用户分类:登录FTP服务器必须有一个账号

          • Real账号:注册账号

          • Guest账号:可能临时对某一类人的行为进行授权

          • Anonymous账号:匿名账号,允许任何人

        • FTP工作流程:

          • i.客户端连接远程主机上的FTP服务器

          • ii.客户端输入用户名和密码(或者"anonymous"和电子邮件地址)

          • iii.客户端和服务器进行各种文件传输和信息查询操作

          • iv.客户端从远程FTP服务器退出,结束传输

        • FTP文件表示

          • 分三段表示FTP服务器上的文件

          • HOST:主机地址,类似于ftp.mozilla.org,以ftp开头

          • DIR:目录,表示文件所在本地的路径,例如pub/android/focus/1.1-RC1

          • File:文件名称,例如Klar-1.1-RC1.apk

          • 如果想完整精确表示ftp上某一个文件,需要上述三部分组合在一起

          • 案例v6.py

            # 需要导入相应包,主要是ftplib
            import ftplib # 关于FTP的操作都在这个包里边
            import os
            import socket
            
            # 三部分精确表示在ftp服务器上的某一个文件
            # 好多公开ftp服务器访问会出错或者没有反应
            HOST = "ftp.acc.umu.se"
            DIR = 'Public/EFLIB/'
            FILE = 'README'
            
            # 1. 客户端链接远程主机上的FTP服务器
            try:
                f = ftplib.FTP()
                # 通过设置调试级别可以方便调试
                f.set_debuglevel(2)
                # 链接主机地址
                f.connect(HOST)
            except Exception as e:
                print(e)
                exit()
            print("***Connected to host {0}".format(HOST))
            
            
            
            # 2. 客户端输入用户名和密码(或者“anonymous”和电子邮件地址)
            try:
                # 登录如果没有输入用户信息,则默认使用匿名登录
                f.login()
            except Exception as e:
                print(e)
                exit()
            print("***Logged in as 'anonymous'")
            
            
            # 3. 客户端和服务器进行各种文件传输和信息查询操作
            try:
                # 更改当前目录到指定目录
                f.cwd(DIR)
            except Exception as e:
                print(e)
                exit()
            print("*** Changed dir to {0}".format(DIR))
            
            try:
                # 从FTP服务器上下载文件
                # 第一个参数是ftp命令
                # 第二个参数是回调函数
                # 此函数的意思是,执行RETR命令,下载文件到本地后,运行回调函数
                f.retrbinary('RETR {0}'.format(FILE), open(FILE, 'wb').write)
            except Exception as e:
                print(e)
                exit()
            
            # 4. 客户端从远程FTP服务器退出,结束传输
            f.quit()

        Mail编程

        电子邮件的历史

        • 起源:

          • 1969 Leonard K.教授发给同事的"LO"

          • 1971美国国防部自主研发的阿帕网(Arpanet)的通讯机制

          • 通讯地址里用@

          • 1978年中国的第一份电子邮件 "Across the Great Wall we can reach every corner in the world"

        • 管理程序

          • Euroda使用邮件普及

          • Netscape, outlook, forxmail后来居上

          • Hotmal使用浏览器发送邮件

        • 参考资料

        邮件工作流程

        • MUA(MailUseraAgent)邮件用户代理

        • MTA(MailTransferAgent)邮件传输代理

        • MDA(MailDeliveAgent)邮件投递代理

        • feifei.@qq.com, 老师, 北京海淀

        • feifei.@sina.com, 学生, 北京海淀

        • 流程

          • i.MUA-->MTA,邮件已经在服务器上了

          • ii.qq MTA-->....-->sina MTA,邮件在新浪的服务器上

          • iii.sina MTA-->sina MDA,此时邮件已经在你的邮箱里了

          • iv.sina MDA-->MUA(Foxmail/Outlook),邮件下载到本地电脑

        • 编写程序

          • 发送:MUA-->MTA with SMTP:SimpleMailTransferProtocal,包含MTA-->MTA

          • 接受:MDA-->MUA with POP3 and IMAP:PostOfficeProtocal v3 and InternetMessageAcessProtocal v4

        • 准备工作

          • 进入设置中心

          • 取得授权码

          • 注册邮箱(以qq邮箱为例)

          • 第三方邮箱需要特殊设置,以qq邮箱为例

        • Python for mail

          • 本质上是MDA到MUA的一个过程

          • 从MDA下载下来的是一个完整的邮件结构体,需要解析才能得到每个具体可读的内容

          • 步骤:

          • 案例v12.py

            # 导入相关包
            # poplib负责从MDA到MUA下载
            import poplib
            
            # 以下包负责相关邮件结构解析
            from email.parser import Parser
            from email.header import decode_header
            from email.utils import parseaddr
            
            # 得到邮件的原始内容
            # 这个过程主要负责从MDA到MUA的下载并使用Parse粗略解析
            def getMsg():
                # 准备相应的信息
                email = "1771784239@qq.com"
                # 邮箱的授权码
                pwd = "amvekroyscapjihh"
            
                # pop3服务器地址
                pop3_srv = "pop.qq.com" # 端口995
            
                # ssl代表是安全通道
                srv = poplib.POP3_SSL(pop3_srv)
            
                # user代表email地址
                srv.user(email)
                # pass_代表密码
                srv.pass_(pwd)
            
                # 以下操作根据具体业务具体使用
                # stat返回邮件数量和占用空间
                # 注意stat返回一个tuple格式
                msgs, counts = srv.stat()
                print("Messages: {0}, Size: {1}".format(msgs, counts))
            
                # list返回所有邮件编号列表
                # mails是所有邮件编号列表
                rsp, mails, octets = srv.list()
                # 可以查看返回的mails列表类似[b'1 82923', b'2 2184', ...]
                print(mails)
            
            
                # 获取最新一封邮件,注意,邮件索引号是从1开始, 最新代表索引号最高
                index = len(mails)
                # retr负责返回一个具体索引号的一封信的内容,此内容不具有可读性
                # lines 存储邮件的最原始文本的每一行
                rsp, lines, octets = srv.retr(index)
            
                # 获得整个邮件的原始文本
                msg_count = b'
            '.join(lines).decode("utf-8")
                # 解析出邮件整个结构体
                # 参数是解码后的邮件整体
                msg = Parser().parsestr(msg_count)
            
                #关闭链接
                srv.quit()
            
                return msg
            
            
            # 详细解析得到的邮件内容
            # msg代表是邮件的原始内容
            # idnent代表的是邮件嵌套的层级
            def parseMsg(msg, indent=0):
                '''
                1. 邮件完全可能是有嵌套格式
                2. 邮件只有一个From,To,Subject之类的信息
                :param msg:
                :param indent: 描述邮件里面有几个邮件MIMEXXX类型的内容,展示的时候进行相应缩进
                :return:
                '''
            
                # 想办法提取出头部信息
                # 只有在第一层的邮件中才会有相关内容,
                # 此内容只有一个
                if indent == 0:
                    for header in ['From', "To", 'Subject']:
                        # 使用get可以避免如果没有相关关键字报错的可能性
                        # 如果没有 关键字”From“, 我们使用 msg["From"]会报错
                        value = msg.get(header, '')
                        if value:
                            # Subject中的内容直接解码就可以,他是字符串类型
                            if header == 'Subject':
                                value = decodeStr(value)
                            # 如果是From和To字段,则内容大概是 "我的邮箱<xxxxx@qq.com>“这种格式
                            else:
                                hdr, addr = parseaddr(value)
                                name = decodeStr(hdr)
                                # 最终返回形如  "我的邮箱<xxx@qq.com>的格式
                                value = "{0}<{1}>".format(name, addr)
                        print("{0}, {1}: {2}".format(indent, header, value))
            
                # 下面代码关注邮件内容本身
                # 邮件内容中,有可能是multipart类型,也有可能是普通邮件类型
                # 下面的解析使用递归方式
                if (msg.is_multipart()):
                    # 如果是multipart类型,则调用递归解析
            
                    # 得到多部分邮件的一个基础邮件部分
                    parts = msg.get_payload()
                    # enumerate 函数是内置函数
                    # 作用是将一个列表,此处是parts,生成一个有索引和parts原内容构成的新的列表
                    # 例如 enumerate(['a', 'b', 'c']) 结果是:  [(1,'a'), (2, 'b'), (3, 'c')]
                    for n,part in enumerate(parts):
                        # 一个字符串乘以一个数字的意思是对这个字符串进行n倍扩展
                        # 比如 ”aa" * 2 -> "aaaa"
                        print("{0}spart: {1}".format(' '*indent, n))
                        parseMsg(part, indent+1)
                else: # 基础类型
                    # get_content_type是系统提供函数,得到内容类型
                    content_type = msg.get_content_type()
                    # text/plain 或者 text/html是固定值
                    if content_type == 'text/plain' or content_type == 'text/html':
                        content = msg.get_payload(decode=True)
                        charset = guessCharset(msg)
                        if charset:
                            content = content.decode(charset)
                        print("{0}Text: {1}".format(indent, content))
            
                    else: #不是文本内容,则应该是附件
                        print('{0}Attachment: {1}'.format(indent, content_type))
            
            def decodeStr(s):
                '''
                s代表一封邮件中From,To,Subject中的任一项
                对s进行解码,解码是编码的逆过程
                :param s:
                :return:
                '''
                value, charset = decode_header(s)[0]
                # charset完全可能为空
                if charset:
                    # 如果指定编码,则用指定编码格式进行解码
                    value = value.decode(charset)
            
                return value
            
            def guessCharset(msg):
                '''
                猜测邮件的编码格式
                :param msg:
                :return:
                '''
                # 调用现成的函数
                charset = msg.get_charset()
            
                if charset is None:
                    # 找到内容类型,并转换成小写
                    content_type = msg.get("Content-Type", "").lower()
                    pos = content_type.find("charset=")
                    if pos >= 0:
                        # 如果包含chraset,则内容形如 charset=xxxx
                        charset = content_type[pos+8:].strip()
            
                return  charset
            
            
            
            
            if __name__ == "__main__":
                # 得到邮件的原始内容
                msg = getMsg()
                print(msg)
                # 精确解析邮件内容
                parseMsg(msg, 0)


          • a.准备相应的内容(邮件地址,密码,POP3实例)

          • b.身份认证

          • c.一般会先得到邮箱内邮件的整体列表

          • d.根据相应序号,得到某一封信的数据流

          • e.利用解析函数进行解析出相应的邮件结构体

          • 1.用poplib下载邮件结构体原始内容

          • 2.用email解析邮件的具体内容

          • 使用email模块构建邮件

          • HTML格式邮件发送

          • 发送带附件的邮件

          • <!DOCTYPE html>
            
            <html lang="en" xmlns="http://www.w3.org/1999/xhtml">
            <head>
                <meta charset="utf-8" />
                <title></title>
            </head>
            <body>
                <h1>Hello, my name is feifei.</h1>
            </body>
            </html>
          • 添加邮件头,抄送等信息

          • 同时支持html和text格式

          • 使用smtplib模块发送邮件

          • 纯文本邮件

          • 案例v7.py

            # 导入相应的包
            import smtplib
            from email.mime.text import MIMEText
            # MIMEText三个主要参数
            # 1. 邮件内容
            # 2. MIME子类型,在此案例我们用plain表示text类型
            # 3. 邮件编码格式
            
            msg = MIMEText("Hello, i am 飞飞 ", "plain", "utf-8")
            
            # 发送email地址,此处地址直接使用我的qq有偶像,密码一般需要临时输入,此处偷懒
            from_addr = "1771784239@qq.com"
            # 此处密码是经过申请设置后的授权码,不是不是不是你的qq邮箱密码
            from_pwd = "amvekroyscapjihh"
            
            # 收件人信息
            # 此处使用qq邮箱,我给自己发送
            to_addr = "1771784239@qq.com"
            
            
            # 输入SMTP服务器地址
            # 此处根据不同的邮件服务商有不同的值,
            # 现在基本任何一家邮件服务商,如果采用第三方收发邮件,都需要开启授权选项
            # 腾讯qq邮箱所的smtp地址是 smtp.qq.com
            
            smtp_srv = "smtp.qq.com"
            
            try:
                # 两个参数
                # 第一个是服务器地址,但一定是bytes格式,所以需要编码
                # 第二个参数是服务器的接受访问端口
                srv = smtplib.SMTP_SSL(smtp_srv.encode(), 465) #SMTP协议默认端口25
                #登录邮箱发送
                srv.login(from_addr, from_pwd)
                # 发送邮件
                # 三个参数
                # 1. 发送地址
                # 2. 接受地址,必须是list形式
                # 3. 发送内容,作为字符串发送
                srv.sendmail(from_addr, [to_addr], msg.as_string())
                srv.quit()
            except Exception as e:
                print(e)
          • 准备HTML代码作为内容

          • 把邮件的subtpye设为html

          • 发送

          • 案例v8.py

          • from email.mime.text import  MIMEText
            
            mail_content = """
                    <!DOCTYPE html>
                    <html lang="en">
                    <head>
                        <meta charset="UTF-8">
                        <title>Title</title>
                    </head>
                    <body>
                    <h1> 这是一封HTML格式邮件</h1>
                    <p>我是飞飞</p>
                    </body>
                    </html>
                    """
            
            msg = MIMEText(mail_content, "html", "utf-8")
            
            # 构建发送者地址和登录信息
            from_addr = "1771784239@qq.com"
            from_pwd = "amvekroyscapjihh"
            
            
            # 构建邮件接受者信息
            to_addr = "1771784239@qq.com"
            
            smtp_srv = "smtp.qq.com"
            
            
            try:
                import smtplib
            
                srv = smtplib.SMTP_SSL(smtp_srv.encode(), 465)
            
                srv.login(from_addr, from_pwd)
                srv.sendmail(from_addr, [to_addr], msg.as_string())
                srv.quit()
            
            except Exception as e:
                print(e)
          • 可以把邮件看作是一个文本邮件和一个附件的合体

          • 一封邮件如果涉及多个部分,需要使用MIMEMultipart格式构建

          • 添加一个MIMEText正文

          • 添加一个MIMEBase或者MIMEText作为附件

          • 案例v9.py + email.html

            from email.mime.text import MIMEText #构建附件使用
            from email.mime.multipart import MIMEBase, MIMEMultipart # 构建基础邮件使用
            
            
            mail_mul = MIMEMultipart()
            # 构建邮件正文
            mail_text = MIMEText("Hello, i am 飞飞", "plain", "utf-8")
            # 把构建好的邮件正文附加入邮件中
            mail_mul.attach(mail_text)
            
            # 构建附加
            # 构建附件,需要从本地读入附件
            # 打开一个本地文件
            # 以rb格式打开
            with open("C:Usersleesource
            eposhellohello
            et编程email.html", "rb") as f:
                s = f.read()
                # 设置附件的MIME和文件名
                m = MIMEText(s, 'base64', "utf-8")
                m["Content-Type"] = "application/octet-stream"
                # 需要注意,
                # 1. attachment后分好为英文状态
                # 2. filename 后面需要用引号包裹,注意与外面引号错开
                m["Content-Disposition"] = "attachment; filename='email.html'"
                # 添加到MIMEMultipart
                mail_mul.attach(m)
            
            
            # 发送email地址,此处地址直接使用我的qq有偶像,密码一般需要临时输入,此处偷懒
            from_addr = "1771784239@qq.com"
            # 此处密码是经过申请设置后的授权码,不是不是不是你的qq邮箱密码
            from_pwd = "amvekroyscapjihh"
            
            # 收件人信息
            # 此处使用qq邮箱,我给自己发送
            to_addr = "1771784239@qq.com"
            
            
            # 输入SMTP服务器地址
            # 此处根据不同的邮件服务商有不同的值,
            # 现在基本任何一家邮件服务商,如果采用第三方收发邮件,都需要开启授权选项
            # 腾讯qq邮箱所的smtp地址是 smtp.qq.com
            
            smtp_srv = "smtp.qq.com"
            
            try:
                import smtplib
                srv = smtplib.SMTP_SSL(smtp_srv.encode(), 465) #SMTP协议默认端口25
                #登录邮箱发送
                srv.login(from_addr, from_pwd)
                # 发送邮件
                # 三个参数
                # 1. 发送地址
                # 2. 接受地址,必须是list形式
                # 3. 发送内容,作为字符串发送
                srv.sendmail(from_addr, [to_addr], mail_mul.as_string())
                srv.quit()
            except Exception as e:
                print(e)
          • mail['Form']表示发送着消息,包括姓名和邮件

          • mail['To']表示接受者消息,包括姓名和邮件地址

          • mail["subject"]表示摘要或者主题信息

          • 案例v10.py

            from email.mime.text import MIMEText
            from email.header import Header
            
            msg = MIMEText("Hello world",  "plain", "utf-8")
            # 下面代码故意写错,说明,所谓的发送者的地址,只是从一个Header的第一个参数作为字符串构建的内容
            # 用utf8编码是因为很可能内容包含非英文字符
            header_from = Header("从我的邮箱发出去的<Me@qq.cn>", "utf-8")
            msg['From'] = header_from
            
            # 填写接受者信息
            header_to = Header("去刘亦菲的地方<刘亦菲@sina.com>", 'utf-8')
            msg['To'] = header_to
            
            header_sub = Header("这是我的主题", 'utf-8')
            msg['Subject'] = header_sub
            
            
            
            # 构建发送者地址和登录信息
            from_addr = "1771784239@qq.com"
            from_pwd = "amvekroyscapjihh"
            
            
            # 构建邮件接受者信息
            to_addr = "1771784239@qq.com"
            
            smtp_srv = "smtp.qq.com"
            
            
            try:
                import smtplib
            
                srv = smtplib.SMTP_SSL(smtp_srv.encode(), 465)
            
                srv.login(from_addr, from_pwd)
                srv.sendmail(from_addr, [to_addr], msg.as_string())
                srv.quit()
            
            except Exception as e:
                print(e)
          • 构建一个MIMEMultipart格式邮件

          • MIMEMultipart的subtype设置成alternative格式

          • 添加HTML和text邮件

          • 案例v11.py

            from email.mime.text import  MIMEText
            from email.mime.multipart import  MIMEMultipart
            
            # 构建一个MIMEMultipart邮件
            msg = MIMEMultipart("alternative")
            
            # 构建一个HTML邮件内容
            html_content = """
                        <!DOCTYPE html>
                        <html lang="en">
                        <head>
                            <meta charset="UTF-8">
                            <title>Title</title>
                        </head>
                        <body>
                        <h1> 这是一封HTML格式邮件</h1>
                        </body>
                        </html>
                    """
            #
            msg_html = MIMEText(html_content, "html", "utf-8")
            msg.attach(msg_html)
            
            
            msg_text = MIMEText("just text content", "plain", "utf-8")
            msg.attach(msg_text)
            
            
            
            # 发送email地址,此处地址直接使用我的qq邮箱,密码临时输入
            from_addr = "1771784239@qq.com"
            #from_pwd = input('163邮箱密码: ')
            from_pwd = "amvekroyscapjihh"
            
            # 收件人信息:
            # 此处使用我注册的163邮箱
            to_addr = "1771784239@qq.com"
            
            # 输入SMTP服务器地址:
            # 此地址根据每隔邮件服务商有不同的值,这个是发信邮件服务商的smtp地址
            # 我用的是qq邮箱发送,此处应该填写腾讯qq邮箱的smtp值,即smtp.163.com,
            # 需要开启授权码,
            smtp_srv = "smtp.qq.com"
            
            try:
                import smtplib
                # 加密传输
                #server = smtplib.SMTP_SSL(smtp_srv.encode(), 465) # SMTP协议默认端口是25
                # qq邮箱要求使用 TLS加密传输
                server = smtplib.SMTP(smtp_srv.encode(), 25) # SMTP协议默认端口是25
                server.starttls()
                # 设置调试级别
                # 通过设置调试等级,可以清楚的看到发送邮件的交互步骤
                server.set_debuglevel(1)
                # 登录发送邮箱
                server.login(from_addr, from_pwd)
                server.sendmail(from_addr, [to_addr], msg.as_string())
                server.quit()
            except Exception as e:
                print(e)
          • SMTP协议负责发送邮件

          • POP3协议接受邮件



          阅读更多