python3发邮件,python3之发送和读取邮件

一、发送邮件

发送邮件使用SMTP协议【Simple Mail Transfer Protocol简单的邮件传输协议】,SMTP协议是SMTP客户端与SMTP服务器之间的通信协议。

python中发送邮件使用的模块有smtplib和email:

使用smtplib模块进行发送邮件;

使用email模块来添加发送的邮件内容。

1. smtplib模块

导入模块:import smtplib

1.1. 创建SMTP对象

smtplib.SMTP和smtplib.SMTP_SSL:均可以用来创建SMTP对象;

smtplib.SMTP_SSL:使用安全加密的SSL协议连接到SMTP服务器;

smtplib.SMTP:没有进行安全加密。

故若待测试邮箱不允许使用非SSL和非TLS频道通信时,则无法使用smtp.SMTP方式来创建客户端对象。

【查看邮箱的通信方式:邮箱设置菜单中,查看邮箱的接收服务器和发送服务器信息。】

如:腾讯企业邮箱

接收服务器:

imap.exmail.qq.com(使用SSL,端口号993)

发送服务器:

smtp.exmail.qq.com(使用SSL,端口号465)

smtplib.SMTP(host, port, local_hostname, timeout, source_address)

smtplib.SMTP_SSL(host, port, local_hostname, keyfile, certfile, timeout, source_address, context)

创建SMTP对象。

host:SMTP发送服务器主机

port:SMTP服务器端哭口号

1.2. SMTP对象操作

login(user, password, *, initial_response_ok=True)

SMTP对象登录

user:授权登录的用户名

password:授权登录的密码

sendmail(from_addr, to_addrs, msg, mail_options=[], rcpt_options=[])

SMTP对象发送邮件

from_addr:发件人地址,字符串类型。

to_addr:收件人地址,包括收件人和抄送人。

多个收件人时to_addr参数为列表,单个收件人时to_addr参数可以为列表或字符串。

msg:要发送的信息

quite()

终止SMTP会话

2. 发送邮件的实例

2.1. 添加邮件内容,包括收件人、抄送人、正文、附件

from email.mime.multipart import MIMEMultipart

from email.header import Header

from email.mime.text import MIMEText

from email.mime.image import MIMEImage

import os

class EmailContent:

def __init__(self, senderAdr, emailSubject, toReceivers, ccReceivers):

# 邮件对象

self.msg = MIMEMultipart()

# 添加发件人头

self.msg['From'] = Header("测试" + "", 'utf-8')

# 添加收件人

if isinstance(toReceivers, str):

self.msg["To"] = toReceivers

elif isinstance(toReceivers, list):

self.msg['To'] = ";".join(toReceivers)

# 添加抄送人

if isinstance(ccReceivers, str):

self.msg["Cc"] = ccReceivers

elif isinstance(ccReceivers, list):

self.msg["Cc"] = ";".join(ccReceivers)

# 添加邮件主题

self.msg['Subject'] = Header(emailSubject, "utf-8")

def addBody(self, bodyType):

"""

添加不同的邮件正文的实例

1. body为字符串:(如)"这是一个邮件正文内容"

2. body为html格式的字符串:(如)"

第一段

第二段"

3. body正文中包含有图片:

"""

if bodyType == "string":

body = "这是一个邮件正文内容"

mimeText = MIMEText(body, "plain", "utf-8")

self.msg.attach(mimeText)

elif bodyType == "html":

body = "

第一段

第二段"

mimeText = MIMEText(body, "html", "utf-8")

self.msg.attach(mimeText)

elif "image" in bodyType:

imageFile = "E://log//test.png"

imageId = os.path.split(imageFile)[1]

# 添加内容

body = '''

测试图片为:

'''.format(imageId=imageId)

mimeText = MIMEText(body, "html", "utf-8")

self.msg.attach(mimeText)

# 读取图片,并设置图片id用于邮件正文引用

with open(imageFile, "rb") as fp:

mimeImage = MIMEImage(fp.read())

mimeImage.add_header("Content-ID", imageId)

self.msg.attach(mimeImage)

def addAttachment(self, attachmentName):

"""

添加附件

:return:

"""

file = "E://log//test.txt"

# file = "E://log//test.zip"

# file = "E://log//test.png"

filePath, fileName = os.path.split(file)

print("fileName =", fileName)

enclosure = MIMEText(open(file, 'rb').read(), 'base64', 'utf-8')

enclosure['Content-Type'] = 'application/octet-stream'

if attachmentName == "英文":

enclosure['Content-Disposition'] = 'attachment; filename="%s"' % fileName

elif attachmentName == "中文":

enclosure.add_header("Content-Disposition", "attachment", filename=("gbk", "", fileName))

self.msg.attach(enclosure)

2.2. 发送邮件

import smtplib

def SendEmail():

"""发送邮件"""

# SMTP的服务器信息

smtpHost = "smtp.exmail.qq.com"

sslPort = 465

senderAdr = "xx@xx.cn"

senderPwd = "XXXX"

# 创建SMTP对象

smtpServer = smtplib.SMTP_SSL(smtpHost, sslPort)

# # 设置debug模块

# smtpServer.set_debuglevel(True)

# 登录

smtpServer.login(senderAdr, senderPwd)

# 添加邮件内容

toReceivers = ["a@xx.cn", "b@xx.cn"]

ccReceivers = ["d@xx.cn", "e@xx.cn"]

toAddrs = toReceivers + ccReceivers

emailSubject = "这是个自动发送的邮件"

emailContent = EmailContent(senderAdr, emailSubject, toReceivers, ccReceivers)

emailContent.addBody("html")

emailContent.addAttachment("英文")

message = emailContent.msg

# 发送

smtpServer.sendmail(senderAdr, toAddrs, message.as_string())

# 终止SMTP会话

smtpServer.quit()

SendEmail()

二、读取邮件

收取邮件使用POP3协议;

解析邮件:需要将收取的邮件转化为email.message.Message对象,再使用email模块解析内容。

1. 读取邮件的实例

1.1. 获取某封邮件的对象

import poplib

from email.parser import Parser

"""POP的服务器信息"""

popHost = "pop.exmail.qq.com"

userAdr = "xx@xx.cn"

userPwd = "xxxxx"

""" 创建POP3对象,添加用户名和密码"""

pop3Server = poplib.POP3(popHost)

pop3Server.user(userAdr)

pop3Server.pass_(userPwd)

"""获取邮件数量和占用空间"""

messageCount, mailboxSize = pop3Server.stat()

"""获取邮件请求返回状态码、每封邮件的字节大小(b'第几封邮件 此邮件字节大小')、"""

response, msgNumOctets, octets = pop3Server.list()

""" 获取任意一封邮件的邮件对象【第一封邮件的编号为1,而不是0】"""

msgIndex = random.randint(1,messageCount)

print(msgIndex)

# 获取第msgIndex封邮件的信息

response, msgLines, octets = pop3Server.retr(msgIndex)

# msgLines中为该邮件的每行数据,先将内容连接成字符串,再转化为email.message.Message对象

msgLinesToStr = b"\r\n".join(msgLines).decode("utf8", "ignore")

messageObject = Parser().parsestr(msgLinesToStr)

print(messageObject)

""" 终止POP3服务"""

pop3Server.quit()

1.2. 解析邮件对象

1.2.1. 获取邮件日期

msgDate = messageObject["date"]

print(msgDate)

1.2.2. 获取邮件发件人实名、邮箱地址

获取邮件实名时,名称一般是加密的,此时就需要对头文件进行解码才可获取它的实际内容

from email.header import decode_header

def decodeMsgHeader(header):

"""

解码头文件

:param header: 需解码的内容

:return:

"""

value, charset = decode_header(header)[0]

if charset:

value = value.decode(charset)

return value

from email.utils import parseaddr

senderContent = messageObject["From"]

# parseaddr()函数返回的是一个元组(realname, emailAddress)

senderRealName, senderAdr = parseaddr(senderContent)

# 将加密的名称进行解码

senderRealName = decodeMsgHeader(senderRealName)

print(senderRealName)

print(senderAdr)

1.2.3. 获取邮件主题

获取的邮件的主题也是加密的,此时就需要对头文件进行解码才可获取它的实际内容

msgHeader = messageObject["Subject"]

# 对头文件进行解码

msgHeader = decodeMsgHeader(msgHeader )

print(msgHeader)

1.2.4. 获取邮件正文

一封邮件的正文内容,可能是由几部分构成,每部分的格式不同。

"""获取邮件正文内容"""

msgBodyContents = []

if messageObject.is_multipart(): # 判断邮件是否由多个部分构成

messageParts = messageObject.get_payload() # 获取邮件附载部分

for messagePart in messageParts:

bodyContent = decodeBody(messagePart)

if bodyContent:

msgBodyContents.append(bodyContent)

else:

bodyContent = decodeBody(messageObject)

if bodyContent:

messageBodyContents.append(bodyContent)

print(msgBodyContents)

def decodeBody(msgPart):

"""

解码内容

:param msgPart: 邮件某部分

"""

contentType = msgPart.get_content_type() # 判断邮件内容的类型,text/html

textContent = ""

if contentType == 'text/plain' or contentType == 'text/html':

content = msgPart.get_payload(decode=True)

charset = msgPart.get_charset()

if charset is None:

contentType = msgPart.get('Content-Type', '').lower()

position = contentType.find('charset=')

if position >= 0:

charset = contentType[position + 8:].strip()

if charset:

textContent = content.decode(charset)

return textContent

1.2.5. 获取邮件附件

邮件附件名为中文时,需借助头文件解码方式进行解码,否则会为乱码。

messageAttachments = []

if messageObject.is_multipart(): # 判断邮件是否由多个部分构成

messageParts = messageObject.get_payload() # 获取邮件附载部分

for messagePart in messageParts:

name = messagePart.get_param("name") # 名字存在,则表示此部分为附件

if name:

fileName = decodeMsgHeader(name) # 解码

messageAttachments.append(fileName)

else:

name = messageObject.get_param("name")

if name:

fileName = decodeMsgHeader(name) # 解码

messageAttachments.append(fileName)

print(messageAttachments)

2. 读取邮件时遇到的问题

2.1. 提示“poplib.error_proto: line too long”

File "XXX/EmailInfo.py", line 22, in getMessageObject

return parser.Parser().parsestr(b"\n".join(self.popServer.retr(i)[1]).decode("utf8", "ignore"))

File "/usr/local/lib/python3.6/poplib.py", line 248, in retr

return self._longcmd('RETR %s' % which)

File "/usr/local/lib/python3.6/poplib.py", line 183, in _longcmd

return self._getlongresp()

File "/usr/local/lib/python3.6/poplib.py", line 168, in _getlongresp

line, o = self._getline()

File "/usr/local/lib/python3.6/poplib.py", line 130, in _getline

raise error_proto('line too long')

poplib.error_proto: line too long

POP3对行长度做了限制,默认为_MAXLINE = 2048,故若是邮件超过此长度就会提示“poplib.error_proto: line too long”。

解决方案:在读取邮件代码中重新定义最大行长度,即给poplib._MAXLINE设置新值。

import poplib

poplib._MAXLINE=20480

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值