python最全邮件收发pop3与smtp

27 篇文章 0 订阅
25 篇文章 0 订阅

smtplib 发送

流程
  1. 连接服务器 连接 SMTP 服务器,并使用用户名、密码登录服务器
  2. 创建邮件 创建 EmailMessage 对象,该对象代表邮件本身
  3. 发送邮件 调用代表与 SMTP 服务器连接的对象的 sendmail() 方法发送邮件
模块
  • smtplib模块
    • smtplib.SMTP 得到邮件连接对象
  • email.message.EmailMessage 构建复杂邮件内容
    • set_content()
    • add_attachment(maintype,subtype,filename,cid=img)
发送经验
  • 早期SMTP 服务器都采用普通的网络连接,因此默认端口是 25
  • 现在绝大部分 SMTP 都是基于 SSL(Secure Socket Layer), 默认端口是465
  • 有些公司的免费邮箱(比如 QQ 邮箱)默认是关闭了 SMTP
  • 邮件太简单,比如没主题,邮箱服务商可能会被当成垃圾邮件拦截
  • java成员变量有初始值,而局部变量没有初始值得,否则会导致编译不通过
发送示例
# py -3.7

import smtplib
import email.utils
from email.message import EmailMessage


smtp_server = 'smtp.qq.com'
from_addr = '2121995655@qq.com'
# qq授权码
password = 'xxxxxxxx'
to_addr = 'pardon110@163.com'

# 建立连接
# conn = smtplib.SMTP(smtp_server, 25)
conn = smtplib.SMTP_SSL(smtp_server, 465)
conn.set_debuglevel(1)
conn.login(from_addr, password)

# 创建邮件对象
msg = EmailMessage()
# 随机生成两个图片id
first_id, second_id = email.utils.make_msgid(), email.utils.make_msgid()

msg.set_content('<h2>邮件内容</h2><p>您好,这是一封来自Python的邮件' +
                '<img src="cid:' + second_id[1:-1]+'"><p>')

msg['subject'] = '一封html邮件'
msg['from'] = '李刚<%s>' % from_addr
msg['to'] = '新用户<%s>' % to_addr

# 添加附件
with open('C:/Users/Public/Pictures/logo/coffee.png', 'rb') as f:
    # 添加第一个附件
    msg.add_attachment(f.read(), maintype='image',
                       subtype='jpeg', filename='coffee.png', cid=first_id)
with open('C:/Users/Public/Pictures/lyn/s009.jpg', 'rb') as f:
    # 添加第二个附件
    msg.add_attachment(f.read(), maintype='image',
                       subtype='jpeg', filename='test.jpeg', cid=second_id)
with open('E:/Manual/pdf/laravel-source-analysis.pdf', 'rb') as f:
    # 添加第三个附件,邮件正文不需引用该附件,因此不指定cid
    msg.add_attachment(f.read(), maintype='application',
                       subtype='pdf', filename='test.pdf',)

# 发送邮件
conn.sendmail(from_addr, [to_addr], msg.as_string())

conn.quit()

poplib 收件

模块类
  • poplib.POP3
  • poplib.POP3_SSL
pop3协议
  • 请求,响应式交互协议
  • POP3 的命令和响应数据都是基于 ASCII 文本的,并以 CR 和 LF(/r/n) 作为行结束符
  • pop3协议命令
    • user name,pass string,stat,quit,list[msg_no],retr_msg_no,dele_msg_no,noop,rset
poplib收取流程
  1. 使用 poplib.POP3poplib.POP3_SSL 按 POP3 协议从服务器端下载邮件
  2. 使用 email.parser.Parseremail.parser.BytesParser 解析邮件内容,得到 EmailMessage 对象
小结
  • 默认端口110,ssl端口995
  • email.parser.BytesParser 解析字节串格式的邮件数据
  • email.parser.Parser 解析字符串格式的邮件数据
  • 若读取 EmailMessage 的各部分,则需要调用该对象的 walk() 方法,该方法返回一个可迭代对象
  • 创建解析器时,*需要指定解析策略 policy=default*否则,解析出来的对象就是 Message,而不是新的 EmailMessage
  • 读取 EmailMessage 的各部分,则需要调用该对象的 walk() 方法,该方法返回一个可迭代对象
收件示例
import poplib
import os.path
import mimetypes
from email.parser import BytesParser, Parser
from email.policy import default


# 输入邮件地址, 口令和POP3服务器地址
email = 'pardon110@qq.com'
# 授权码
password = 'pkvxxxxxxec'
pop3_server = 'pop.qq.com'

# 连接pop3服务器
# conn = poplib.POP3(pop3_server, 110)
conn = poplib.POP3_SSL(pop3_server, 995)

# 打开调试信息
conn.set_debuglevel(1)
# 可选:打印POP 3服务器的欢迎文字
print(conn.getwelcome().decode('utf-8'))

# 输入用户密码
conn.user(email)
conn.pass_(password)

# 获取邮件的统计信息,相当于发送pop3的stat命令
message_num, total_size = conn.stat()
print('邮件数:%s, 总大小:%s' % (message_num, total_size))

# 获取服务器上的邮件列表,相当于发送POP 3的list命令
# resp保存服务器的响应码
# mails列表保存每封邮件的编号、大小
resp, mails, octets = conn.list()
print(resp, mails)

# 获取指定邮件的内容(此处传入总长度,也就是获取最后一封邮件)
# 相当于发送POP 3的retr命令
# resp保存服务器的响应码
# data保存该邮件的内容
resp, data, octets = conn.retr(len(mails))
# 将data的所有数据(原本是一个字节列表)拼接在一起
msg_data = b'\r\n'.join(data)

# 将字符串内容解析成邮件,需指定解析策略
msg = BytesParser(policy=default).parsebytes(msg_data)
print(type(msg))

print('发件人:' + msg['from'])
print('收件人:' + msg['to'])
print('主题:' + msg['subject'])
print('第一个收件人名字:' + msg['to'].addresses[0].username)
print('第一个发件人名字:' + msg['from'].addresses[0].username)

for part in msg.walk():
    counter = 1
    # 如果maintype是multipart,说明是容器(用于包含正文、附件等)
    if part.get_content_maintype() == 'multipart':
        continue
    elif part.get_content_maintype() == 'text':
        print(part.get_content())
    # 处理附件
    else:
        filename = part.get_filename()
        if not filename:
            # 根据附件的contnet_type来推测它的后缀名
            ext = mimetypes.guess_extension(part.get_content_type())
            if not ext:
                ext = '.bin'
            # 程序为附件来生成文件名
            filename = 'part-%03d%s' % (counter, ext)
        counter += 1
        # 将附件写入本地文件
        with open(os.path.join('.', filename), 'wb') as fp:
            fp.write(part.get_payload(decode=True))

# 退出服务器,相当于发送POP 3的quit命令
conn.quit()
  • 1
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值