热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

12网络编程

文章目录1.协议1.1网络模型1.2TCPIP协议族1.3TCPUDP协议2.编程2.1SOCKET编程2.2UDP编程2.3TCP编程2.4FTP编程3.Mail编程3.1电子邮


文章目录

        • 1. 协议
          • 1.1 网络模型
          • 1.2 TCP/IP协议族
          • 1.3 TCP/UDP协议
        • 2. 编程
          • 2.1 SOCKET编程
          • 2.2 UDP 编程
          • 2.3 TCP编程
          • 2.4 FTP编程
        • 3. Mail编程
          • 3.1 电子邮件的历史
          • 3.2 邮件工作流程
          • 3.3 编写程序


1. 协议

网络协议: 一套规则

1.1 网络模型

- 七层模型-七层
- 物理层
- 数据链路层
- 网络层
- 传输层
- 会话层
- 表示层
- 应用层
- 四层模型-实际应用
- 链路层
- 网络
- 传输层
- 应用层
每一层都有相应的协议负责交换信息或者协同工作

1.2 TCP/IP协议族

IP地址:负责在网络上唯一定位一个机器
- IP地址分ABCDE类
- 是由四个数字段组成,每个数字段的取值是0-255
- 192.168.xxx.xxx:局域网ip
- 127.0.0.1:本机
- IPv4, IPv6
端口
- 范围: 0-65535
- 知名端口:0-1023
- 非知名端口:1024-

1.3 TCP/UDP协议

UDP:非安全的不面向链接的传输
- 安全性差
- 大小限制64kb
- 没有顺序
- 速度快
TCP
- 基于链接的通信

2. 编程


2.1 SOCKET编程

socket(套接字): 是一个网络通信的端点, 能实现不同主机的进程通信,网络大多基于Socket通信
- 通过IP+端口定位对方并发送消息的通信机制
- 分为UDP和TCP
- 客户端Client: 发起访问的一方
- 服务器端Server:接受访问的一方
语法:socket.socket([family[, type[, proto]]])
- family: 套接字家族可以使AF_UNIX或者AF_INET
- type: 套接字类型可以根据是面向连接的还是非连接分为SOCK_STREAM或SOCK_DGRAM
- protocol: 一般不填默认为0
参考资料
https://www.runoob.com/python3/python3-socket.html

2.2 UDP 编程

Server端流程
1. 建立socket,socket是负责具体通信的一个实例
2. 绑定,为创建的socket指派固定的端口和ip地址
3. 接受对方发送内容
4. 给对方发送反馈,此步骤为非必须步骤
Client端流程
1. 建立通信的socket
2. 发送内容到指定服务器
3. 接受服务器给定的反馈内容


模拟客户端案例01


# 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__':
print("Starting server.........")
serverFunc()
print("Ending server........")

模拟客户端案例02

import socket
## 模拟客户端
def clientFunc():
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
text = "I love jingjing"
# 发送的数据必须是bytes格式
data = text.encode()
# 发送
sock.sendto(data, ("127.0.0.1", 7852))
data, addr = sock.recvfrom(200)
data = data.decode()
print(data)
if __name__ == '__main__':
clientFunc()

服务器程序要求永久运行,一般用死循环处理
改造的服务器案例03

# 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 = "明天应该会下雨"
# 发送的数据需要编码成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)

2.3 TCP编程

面向链接的传输,即每次传输之前需要先建立一个链接
客户端和服务器端两个程序需要编写
- Server端的编写流程
1. 建立socket负责具体通信,这个socket其实只负责接受对方的请求,真正通信的是链接后从新建立的socket
2. 绑定端口和地址
3. 监听接入的访问socket
4. 接受访问的socket,可以理解接受访问即建立了一个通讯的链接通路
5. 接受对方的发送内容,利用接收到的socket接收内容
6. 如果有必要,给对方发送反馈信息
7. 关闭链接通路
- Client端流程
1. 建立通信socket
2. 链接对方,请求跟对方建立通路
3. 发送内容到对方服务器
4. 接受对方的反馈
5. 关闭链接通路


tcp服务案例04

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.......")

tcp客户端案例05

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()

2.4 FTP编程

FTP(FileTransferProtocal)文件传输协议
- 用途: 定制一些特殊的上传下载文件的服务
- 用户分类: 登陆FTP服务器必须有一个账号
- Real账户: 注册账户
- Guest账户: 可能临时对某一类人的行为进行授权
- Anonymous账户: 匿名账户,允许任何人
- FTP工作流程
1. 客户端链接远程主机上的FTP服务器
2. 客户端输入用户名和密码(或者“anonymous”和电子邮件地址)
3. 客户端和服务器进行各种文件传输和信息查询操作
4. 客户端从远程FTP服务器退出,结束传输
FTP文件表示
- 分三段表示FTP服务器上的文件
- HOST: 主机地址,类似于 ftp.mozilla.org, 以ftp开头
- DIR:目录, 表示文件所在本地的路径,例如 pub/android/focus/1.1-RC1/
- File: 文件名称, 例如 Klar-1.1-RC1.apk
- 如果想完整精确表示ftp上某一个文件,需要上述三部分组合在一起


ftp案例06

# 需要导入相应包,主要是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()

3. Mail编程


3.1 电子邮件的历史

起源
- 1969 Leonard K. 教授发给同时的 “LO”
- 1971 美国国防部自主的阿帕网(Arpanet)的通讯机制
- 通讯地址里用@
- 1987年中国的第一份电子邮件
“Across the Great Wall we can reach every corner in the world"
管理程序
- Euroda使邮件普及
- Netscape,outlook,forxmail后来居上
- Hotmal使用浏览器发送邮件i
参考资料
- [官网](https://docs.python.org/3/library/email.mime.html)

3.2 邮件工作流程

- MUA(MailUserAgent)邮件用户代理
- MTA(MailTransferAgent)邮件传输代理
- MDA(MailDeliveryAgent)邮件投递代理
流程
1. MUA->MTA, 邮件已经在服务器上了
2. qq MTA->.........->sina MTA, 邮件在新浪的服务器上
3. sina MTA-> sina MDA, 此时邮件已经在你的邮箱里了
4. sina MDA -> MUA(Foxmail/Outlook), 邮件下载到本地电脑

3.3 编写程序

流程
- 发送: MUA->MTA with SMTP:SimpleMailTransferProtocal,包含MTA->MTA
- 接受: MDA->MUA with POP3 and IMAP:PostOfficeProtocal v3 and InternetMessageAccessProtocal v4
准备工作
- 注册邮箱(以qq邮箱为例)
- 第三方邮箱需要特殊设置, 以qq邮箱为例
- 进入设置中心
- 取得授权码

Python for mail
- SMTP协议负责发送邮件
- 使用email模块构建邮件
- 纯文本邮件
- HTML格式邮件发送
- 准备HTML代码作为内容
- 把邮件的subtpye设为html
- 发送
- 案例v08
- 发送带附件的邮件
- 可以把邮件看作是一个文本邮件和一个附件的合体
- 一封邮件如果涉及多个部分,需要使用MIMEMultipart格式构建
- 添加一个MIMEText正文
- 添加一个MIMEBase或者MEMEText作为附件
- 案例v09

- 添加邮件头, 抄送等信息
- mail["From"] 表示发送着信息,包括姓名和邮件
- mail["To"] 表示接收者信息,包括姓名和邮件地址
- mail["Subject"] 表示摘要或者主题信息
- 案例v10
- 同时支持html和text格式
- 构建一个MIMEMultipart格式邮件
- MIMEMultipart的subtype设置成alternative格式
- 添加HTML和text邮件
- 案例v11

- 使用smtplib模块发送邮件


纯文本邮件案例07

# 导入相应的包
import smtplib
from email.mime.text import MIMEText
# MIMEText三个主要参数
# 1. 邮件内容
# 2. MIME子类型,在此案例我们用plain表示text类型
# 3. 邮件编码格式
msg = MIMEText("这是一封python测试邮件", "plain", "utf-8")
# 发送email地址,此处地址直接使用我的qq邮箱,密码一般需要临时输入,此处偷懒
from_addr = "784366503@qq.com"
# 此处密码是经过申请设置后的授权码,不是不是不是你的qq邮箱密码
from_pwd = "ihlkcvpctefmbcha"
# 收件人信息
# 此处使用qq邮箱,我给自己发送
to_addr = "784366503@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邮件案例08

from email.mime.text import MIMEText
mail_cOntent= """







这是一封HTML格式邮件


"""
msg = MIMEText(mail_content, "html", "utf-8")
from_addr = "784366503@qq.com"
# 此处密码是经过申请设置后的授权码,不是不是不是你的qq邮箱密码
from_pwd = "ihlkcvpctefmbcha"
# 收件人信息
# 此处使用qq邮箱,我给自己发送
to_addr = "784366503@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)

带附件的邮件案例09

from email.mime.text import MIMEText #构建附件使用
from email.mime.multipart import MIMEBase, MIMEMultipart # 构建基础邮件使用
mail_mul = MIMEMultipart()
# 构建邮件正文
mail_text = MIMEText("Hello, i am liudana", "plain", "utf-8")
# 把构建好的邮件正文附加入邮件中
mail_mul.attach(mail_text)
# 构建附加
# 构建附件,需要从本地读入附件
# 打开一个本地文件
# 以rb格式打开
with open("02.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='02.html'"
# 添加到MIMEMultipart
mail_mul.attach(m)
# 发送email地址,此处地址直接使用我的qq有偶像,密码一般需要临时输入,此处偷懒
from_addr = "1366798119@qq.com"
# 此处密码是经过申请设置后的授权码,不是不是不是你的qq邮箱密码
from_pwd = "hjpovygcxmrshhcj"
# 收件人信息
# 此处使用qq邮箱,我给自己发送
to_addr = "1366798119@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)

邮件头、抄送等信息案例10

from email.mime.text import MIMEText
from email.header import Header
msg = MIMEText("Hello wold", "plain", "utf-8")
# 下面代码故意写错,说明,所谓的发送者的地址,只是从一个Header的第一个参数作为字符串构建的内容
# 用utf8编码是因为很可能内容包含非英文字符
header_from = Header("从图灵学院邮箱发出去的", "utf-8")
msg['From'] = header_from
# 填写接受者信息
header_to = Header("去王晓静的地方", 'utf-8')
msg['To'] = header_to
header_sub = Header("这是图灵学院的主题", 'utf-8')
msg['Subject'] = header_sub
# 构建发送者地址和登录信息
from_addr = "1366798119@qq.com"
from_pwd = "hjpovygcxmrshhcj"
# 构建邮件接受者信息
to_addr = "1366798119@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)

同时支持html和text格式案例11

from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
# 构建一个MIMEMultipart邮件
msg = MIMEMultipart("alternative")
# 构建一个HTML邮件内容
html_cOntent= """







这是一封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 = "1366798119@qq.com"
#from_pwd = input('163邮箱密码: ')
from_pwd = "hjpovygcxmrshhcj"
# 收件人信息:
# 此处使用我注册的163邮箱
to_addr = "1366798119@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)

- POP3协议接受邮件
- 本质上是MDA到MUA的一个过程
- 从 MDA下载下来的是一个完整的邮件结构体,需要解析才能得到每个具体可读的内容
- 步骤:
1. 用poplib下载邮件结构体原始内容
1. 准备相应的内容(邮件地址,密码,POP3实例)
2. 身份认证
3. 一般会先得到邮箱内邮件的整体列表
4. 根据相应序号,得到某一封信的数据流
5. 利用解析函数进行解析出相应的邮件结构体
2. 用email解析邮件的具体内容


POP3协议接受邮件案例 12

# 导入相关包
# 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 = "784366503@qq.com"
# 邮箱的授权码
pwd = "ihlkcvpctefmbcha"
# 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'\r\n'.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字段,则内容大概是 "我的邮箱“这种格式
else:
hdr, addr = parseaddr(value)
name = decodeStr(hdr)
# 最终返回形如 "我的邮箱的格式
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)


推荐阅读
  • 本文介绍了计算机网络的定义和通信流程,包括客户端编译文件、二进制转换、三层路由设备等。同时,还介绍了计算机网络中常用的关键词,如MAC地址和IP地址。 ... [详细]
  • 本文介绍了解决Netty拆包粘包问题的一种方法——使用特殊结束符。在通讯过程中,客户端和服务器协商定义一个特殊的分隔符号,只要没有发送分隔符号,就代表一条数据没有结束。文章还提供了服务端的示例代码。 ... [详细]
  • http:my.oschina.netleejun2005blog136820刚看到群里又有同学在说HTTP协议下的Get请求参数长度是有大小限制的,最大不能超过XX ... [详细]
  • 本文介绍了如何使用iptables添加非对称的NAT规则段,以实现内网穿透和端口转发的功能。通过查阅相关文章,得出了解决方案,即当匹配的端口在映射端口的区间内时,可以成功进行端口转发。详细的操作步骤和命令示例也在文章中给出。 ... [详细]
  • 本文介绍了在Linux下安装和配置Kafka的方法,包括安装JDK、下载和解压Kafka、配置Kafka的参数,以及配置Kafka的日志目录、服务器IP和日志存放路径等。同时还提供了单机配置部署的方法和zookeeper地址和端口的配置。通过实操成功的案例,帮助读者快速完成Kafka的安装和配置。 ... [详细]
  • 解决nginx启动报错epoll_wait() reported that client prematurely closed connection的方法
    本文介绍了解决nginx启动报错epoll_wait() reported that client prematurely closed connection的方法,包括检查location配置是否正确、pass_proxy是否需要加“/”等。同时,还介绍了修改nginx的error.log日志级别为debug,以便查看详细日志信息。 ... [详细]
  • 本文讨论了在VMWARE5.1的虚拟服务器Windows Server 2008R2上安装oracle 10g客户端时出现的问题,并提供了解决方法。错误日志显示了异常访问违例,通过分析日志中的问题帧,找到了解决问题的线索。文章详细介绍了解决方法,帮助读者顺利安装oracle 10g客户端。 ... [详细]
  • 本文介绍了如何使用go语言实现一个一对一的聊天服务器和客户端,包括服务器开启、等待客户端连接、关闭连接等操作。同时提供了一个相关的多人聊天的链接供参考。 ... [详细]
  • SQL Server 2008 到底需要使用哪些端口?
    SQLServer2008到底需要使用哪些端口?-下面就来介绍下SQLServer2008中使用的端口有哪些:  首先,最常用最常见的就是1433端口。这个是数据库引擎的端口,如果 ... [详细]
  • NFS文件共享系统
    1、概述:NFS(NetworkFileSystem)意为网络文件系统,它最大的功能就是可以通过网络,让不同的机器不同的操作系统可以共享 ... [详细]
  • Nginx使用AWStats日志分析的步骤及注意事项
    本文介绍了在Centos7操作系统上使用Nginx和AWStats进行日志分析的步骤和注意事项。通过AWStats可以统计网站的访问量、IP地址、操作系统、浏览器等信息,并提供精确到每月、每日、每小时的数据。在部署AWStats之前需要确认服务器上已经安装了Perl环境,并进行DNS解析。 ... [详细]
  • 本文介绍了RPC框架Thrift的安装环境变量配置与第一个实例,讲解了RPC的概念以及如何解决跨语言、c++客户端、web服务端、远程调用等需求。Thrift开发方便上手快,性能和稳定性也不错,适合初学者学习和使用。 ... [详细]
  • centos安装Mysql的方法及步骤详解
    本文介绍了centos安装Mysql的两种方式:rpm方式和绿色方式安装,详细介绍了安装所需的软件包以及安装过程中的注意事项,包括检查是否安装成功的方法。通过本文,读者可以了解到在centos系统上如何正确安装Mysql。 ... [详细]
  • 微软评估和规划(MAP)的工具包介绍及应用实验手册
    本文介绍了微软评估和规划(MAP)的工具包,该工具包是一个无代理工具,旨在简化和精简通过网络范围内的自动发现和评估IT基础设施在多个方案规划进程。工具包支持库存和使用用于SQL Server和Windows Server迁移评估,以及评估服务器的信息最广泛使用微软的技术。此外,工具包还提供了服务器虚拟化方案,以帮助识别未被充分利用的资源和硬件需要成功巩固服务器使用微软的Hyper - V技术规格。 ... [详细]
  • 基于移动平台的会展导游系统APP设计与实现的技术介绍与需求分析
    本文介绍了基于移动平台的会展导游系统APP的设计与实现过程。首先,对会展经济和移动互联网的概念进行了简要介绍,并阐述了将会展引入移动互联网的意义。接着,对基础技术进行了介绍,包括百度云开发环境、安卓系统和近场通讯技术。然后,进行了用户需求分析和系统需求分析,并提出了系统界面运行流畅和第三方授权等需求。最后,对系统的概要设计进行了详细阐述,包括系统前端设计和交互与原型设计。本文对基于移动平台的会展导游系统APP的设计与实现提供了技术支持和需求分析。 ... [详细]
author-avatar
高小原gy_941
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有