1.发送电子邮件

1.1 SMTP发送电子邮件

smtplib模块用于实现SMTP协议发送邮件,email模块帮我们构造邮件格式。

SMTP:简单邮件传输协议,是一组由源地址到目的地址传送邮件的规则,用来控制邮件的中转方式

python创建SMTP对象的语法:

smtpObj = smtplib.SMTP([host,port,local_hostname)

host:SMTP服务器主机,可选参数

port:端口,一般为25

local_hostnane:如果SMTP在本机,指定localhost即可

 

SMTP对象使用sendmail方法发送邮件的语法:

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

from_addr:邮件发送者地址

to_addrs:字符串列表,邮件发送地址

msg:发送消息,一般字符串

 

import smtplib

from email.mime.text import MIMEText
from email.header import Header

#邮箱用户名
sender = "1@qq.com"
#邮箱密码
password = "1"
#收件人无论是否一个收件人都必须是列表
receiver = ["2@qq.com"]

#邮件正文
message = MIMEText("这是测试邮件","plain","utf-8")

#发件人显式的名字
message["From"] = Header("python发送邮件","utf-8")

#收件人显式的名字
message["To"] = Header("python接收邮件","utf-8")

#邮件标题
message["Subject"] = "Python SMTP 发送邮件"

try:
    #使用QQ邮箱发送
    smtp = smtplib.SMTP_SSL("smtp.exmail.qq.com",465)
    #登录
    smtp.login(sender,password)
    #发送
    smtp.sendmail(sender,receiver,message.as_string())
    print("邮件已发送")

except smtplib.SMTPException as e:
    print("发送失败",e)

 

1.2 发送HTTP格式邮箱

HTTP格式的邮箱可以发送很丰富的内容,不仅仅是文本

import smtplib

from email.mime.text import MIMEText
from email.header import Header

#邮箱用户名
sender = "1@qq.com"
#邮箱密码
password = "1"
#收件人无论是否一个收件人都必须是列表
receiver = ["2@qq.com",]

#邮件正文
mail_msg = "<p>使用python发送邮件</p>"

#制定消息体使用HTML格式
message = MIMEText(mail_msg,"html","utf-8")

#发件人显式的名字
message["From"] = Header("python发送邮件","utf-8")

#收件人显式的名字
message["To"] = Header("python接收邮件","utf-8")

#邮件标题
message["Subject"] = "Python SMTP 发送邮件"

try:
    #使用QQ邮箱发送
    smtp = smtplib.SMTP_SSL("smtp.exmail.qq.com",465)
    #登录
    smtp.login(sender,password)
    #发送
    smtp.sendmail(sender,receiver,message.as_string())
    print("邮件已发送")

except smtplib.SMTPException as e:
    print("发送失败",e)

 

1.3 发送带附件的邮件

另一种格式的MIME,需要使用MIMEMultipart来构建复合类型消息体,然后把文本和附件加进去

import smtplib

from email.mime.text import MIMEText
from email.header import Header
from email.mime.multipart import MIMEMultipart

#邮箱用户名
sender = "1@qq.com"
#邮箱密码
password = "1"
#收件人无论是否一个收件人都必须是列表
receiver = ["2@qq.com",]

#制定消息体使用复合类型
message = MIMEMultipart()

#邮件正文
mail_msg = "<p>使用python发送邮件</p>"

message.attach(MIMEText(mail_msg,"html","utf-8"))

#添加附件
attached_file = MIMEText(open(__file__,encoding="utf-8").read(),"base64","utf-8")
#吸顶附件的文件名可以和原先的文件名不一样
attached_file["Content-Disposition"] = 'attachment;filename="mail.py"'

message.attach(attached_file)

#发件人显式的名字
message["From"] = Header("python发送邮件","utf-8")

#收件人显式的名字
message["To"] = Header("python接收邮件","utf-8")

#邮件标题
message["Subject"] = "Python SMTP 发送邮件"

try:
    #使用QQ邮箱发送
    smtp = smtplib.SMTP_SSL("smtp.exmail.qq.com",465)
    #登录
    smtp.login(sender,password)
    #发送
    smtp.sendmail(sender,receiver,message.as_string())
    print("邮件已发送")

except smtplib.SMTPException as e:
    print("发送失败",e)

 

1.4 发送图片

import smtplib

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

#邮箱用户名
sender = "1@qq.com"
#邮箱密码
password = "1"
#收件人无论是否一个收件人都必须是列表
receiver = ["2@qq.com",]

#采用related定义内嵌资源的邮件体
message = MIMEMultipart("related")

#发件人显式的名字
message["From"] = Header("python发送邮件","utf-8")

#收件人显式的名字
message["To"] = Header("python接收邮件","utf-8")

#邮件标题
message["Subject"] = "Python SMTP 发送邮件"

#邮件正文
msg_content = MIMEMultipart("alternative")
mail_msg = "<p>使用python发送邮件</p>"
msg_content.attach(MIMEText(mail_msg,"html","utf-8"))
message.attach(msg_content)

#添加图片
with open("test.png","rb") as f:
    img1 = MIMEImage(f.read())

#定义资源的名字为img1
img1.add_header("Content-ID","img1")
message.attach(img1)

try:
    #使用QQ邮箱发送
    smtp = smtplib.SMTP_SSL("smtp.exmail.qq.com",465)
    #登录
    smtp.login(sender,password)
    #发送
    smtp.sendmail(sender,receiver,message.as_string())
    print("邮件已发送")

except smtplib.SMTPException as e:
    print("发送失败",e)

 关于multipart里面的参数,如下:

python邮件模块 python处理邮件数据_python

 

2.接收邮件

接收邮件有两种常用的协议:POP3和IMAP

POP3:允许电子邮件客户端下载服务器上的邮件,但是在客户端的操作不会反馈到服务器上。

IMAP:提供下载功能,同事提供摘要浏览。另外还支持在不同设备上随时访问新邮件。

 

2.1 使用POP3下载邮件

import poplib
from email.parser import Parser

#登录邮箱的用户名
username = "1@qq.com"
#登录邮箱的密码
password = "111"

#连接邮箱服务器
pop_server = poplib.POP3_SSL("pop.exmail.qq.com",995)

#打印出邮箱服务器的欢迎文字
print(pop_server.getwelcome().decode("utf-8"))

#登录邮箱服务器
pop_server.user(username)
pop_server.pass_(password)

#打印出当前账号的状态,第一个返回值为邮件数,第二个返回值为占用空间
print("Server stat",pop_server.stat())

#获取所有邮件列表
resp,mails,octets = pop_server.list()
print(mails)

#获取最新的一封邮件(序号最大的),索引从1开始计算
index = len(mails)
resp,lines,octets = pop_server.retr(index)

msg_content = b"\r\n".join(lines).decode("utf-8")

#解析出邮件
msg = Parser().parsestr(msg_content)

#可以根据邮件索引号直接从服务器删除邮件
pop_server.dele(index)

#关闭连接
pop_server.quit()

 

2.2 使用IMAP协议下载邮件

import imaplib
import email

#登录邮箱的用户名
username = "1@qq.com"
#登录邮箱的密码
password = "111"

#连接邮箱服务器
imap_server = imaplib.IMAP4_SSL("pop.exmail.qq.com",995)

#登录邮箱服务器
imap_server.login(username,password)

print("============LOG================")
imap_server.print_log()
print("===============================")

#获取邮箱目录
resp,data = imap_server.list()
print(data)

#选择默认收件箱并打印邮件数量
res,data = imap_server.select("INBOX")
print(res,data)
print(data[0])

#获取最新的一封邮件
typ,lines = imap_server.fetch(data[0],"(RFC822)")

#解析出邮件
msg = email.message_from_string(lines[0][1].decode("utf-8"))

#关闭连接
imap_server.close()

 

2.3 解析邮件

解析邮件的过程正好和发送邮件相反

import poplib
from email.parser import Parser
from email.header import decode_header
from email.utils import parseaddr

#登录邮箱的用户名
username = "1@qq.com"
#登录邮箱的密码
password = "111"

#连接邮箱服务器
pop_server = poplib.POP3_SSL("pop.exmail.qq.com",995)

#打印出邮箱服务器的欢迎文字
print(pop_server.getwelcome().decode("utf-8"))

#登录邮箱服务器
pop_server.user(username)
pop_server.pass_(password)

#打印出当前账号的状态,第一个返回值为邮件数,第二个返回值为占用空间
print("Server stat",pop_server.stat())

#获取所有邮件列表
resp,mails,octets = pop_server.list()
print(mails)

#获取最新的一封邮件(序号最大的),索引从1开始计算
index = len(mails)
resp,lines,octets = pop_server.retr(index)

msg_content = b"\r\n".join(lines).decode("utf-8")

#解析出邮件
msg = Parser().parsestr(msg_content)

#可以根据邮件索引号直接从服务器删除邮件
pop_server.dele(index)

#关闭连接
pop_server.quit()

def decode_email(s):
    if not s:
        return ""
    value,charset = decode_header(s)[0]
    if charset:
        value = value.decode(charset)
    return value

#打印邮件的发件人、收件人和主题
mail_from = msg.get("From","")
hdr,mail_from_addr = parseaddr(mail_from)
mail_from_name = decode_email(hdr)
print("发件人",mail_from_name,mail_from_addr)

mail_to = msg.get("To","")
hdr,mail_to_addr = parseaddr(mail_to)
mail_to_name = decode_email(hdr)
print("收件人",mail_to_name,mail_to_addr)

subject = decode_email(msg.get("Subject",""))
print("主题",subject)

#递归解析邮件
def decode_mime(msg):
    if msg.is_multipart():
        parts = msg.get_payload()
        for part in parts:
            print(decode_mime(part))
    else:
        content_type = msg.get_content_type()
        if content_type in ("text/plain","text/html"):
            content = msg.get_payload(decode=True)
            print(content)
        else:
            print("Attachment",content_type)

decode_mime(msg)