Python编程:email模块+smtplib模块+poplib模块实现邮件收取和发送

本文涉及的产品
全局流量管理 GTM,标准版 1个月
云解析 DNS,旗舰版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
简介: Python编程:email模块+smtplib模块+poplib模块实现邮件收取和发送

发送邮件

# email负责构造邮件,smtplib负责发送邮件
from email import encoders
from email.header import Header
from email.mime.base import MIMEBase
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.utils import parseaddr, formataddr
import os
import smtplib
class EmailSender(object):
    def __init__(self, from_addr, password, server="smtp.163.com", port=25):
        # 发信人账号密码
        self.from_addr = from_addr
        self.password = password
        # 收件人地址
        self.to_addrs = []
        # SMTP服务器地址
        self.smtp_server = server
        self.smtp_port = port
        self.msg =self._get_email()
        self._add_sender(self.from_addr)
    # 添加标题
    def set_header(self, text):
        self.msg['Subject'] = Header(text, 'utf-8').encode()
    # 添加文本
    def add_text(self, text):
        self._add_content(text, "plain")
    # 添加邮件(优先)
    def add_html(self, html):
        self._add_content(html, "html")
    # 增加邮件地址
    def add_receiver(self, address):
        # msg['To'] 接收的是字符串而不是list,如果有多个邮件地址,用,分隔即可
        self.to_addrs.append(address)
    # 增加多个邮件地址
    def add_receivers(self, addresses):
        self.to_addrs.extend(addresses)
    # 添加附件
    def add_attach(self, fullname):
        # 加上一个MIMEBase,从本地读取一个图片:
        filename = os.path.basename(fullname)
        with open(fullname, 'rb') as f:
            # 设置附件的MIME和文件名,这里是png类型:
            name, ext = os.path.splitext(filename)
            ext = ext.strip(".")
            mime = MIMEBase('image', ext, filename=filename)
            # 加上必要的头信息:
            mime.add_header('Content-Disposition', 'attachment', filename=filename)
            mime.add_header('Content-ID', '<0>')
            mime.add_header('X-Attachment-Id', '0')
            # 把附件的内容读进来:
            mime.set_payload(f.read())
            # 用Base64编码:
            encoders.encode_base64(mime)
            # 添加到MIMEMultipart:
            self.msg.attach(mime)
    # 发送
    def send(self):
        self._add_receivers()
        server = smtplib.SMTP(self.smtp_server, self.smtp_port)  # SMTP协议默认端口是25
        # server.set_debuglevel(1)  # 打印出和SMTP服务器交互的所有信息
        server.login(self.from_addr, self.password)
        server.sendmail(self.from_addr, self.to_addrs, self.msg.as_string())
        server.quit()
    # 邮件对象添加内容
    def _add_content(self, text, text_type):
        # 'plain'表示纯文本, 'html'表示html文本,utf-8编码保证多语言兼容性
        self.msg.attach(MIMEText(text, text_type, 'utf-8'))
    # 格式化一个邮件地址
    def _format_addr(self, s):
        # 如果包含中文,需要通过Header对象进行编码
        name, addr = parseaddr(s)
        return formataddr((Header(name, 'utf-8').encode(), addr))
    # 获取邮件对象
    def _get_email(self):
        # 同时支持HTML和Plain格式
        return  MIMEMultipart("alternative")
    # 邮件对象添加发送者
    def _add_sender(self, from_addr):
        self.msg['From'] = self._format_addr('%s <%s>'% (from_addr, from_addr))
    # 邮件对象添加收件人
    def _add_receivers(self):
        addrs = [self._format_addr('%s <%s>' % (addr, addr)) for addr in self.to_addrs]
        self.msg['To'] = ",".join(addrs)
if __name__ == '__main__':
    email = EmailSender("xxx@163.com", "xxx")
    email.set_header("你好")
    email.add_text("hello1")
    email.add_text("hello2")
    # email.add_attach("images/guilunmei.jpeg")
    # email.add_attach("images/guilunmei.jpeg")
    email.add_receiver("mouday@qq.com")
    email.add_receiver("xxx@qq.com")
    email.send()

接收邮件

# poplib模块负责接收, email模块负责解析
from email.parser import Parser
from email.header import decode_header
from email.utils import parseaddr
import poplib
class EmailReceiver(object):
    def __init__(self, email, password, server="pop.163.com"):
    # 输入邮件地址, 口令和POP3服务器地址:
        self.email = email
        self.password = password
        self.pop3_server = server
        self._connect()
        self.message = {
            "From": None,
            "To": None,
            "Subject": None,
            "text": [],
            "attachment": []
        }  # 解析后的邮件内容
    # stat()返回邮件数量和占用空间:
    def get_stat(self):
        return self.server.stat()
    # list()返回所有邮件的编号:
    def get_list(self):
        resp, mails, octets = self.server.list()
        # 可以查看返回的列表类似[b'1 82923', b'2 2184', ...]
        return mails
    # 获取一封邮件
    def get_email(self, index):
        self._get_email(index)
        return self.message
    # 获取最新一封邮件, 注意索引号从1开始:
    def get_last_email(self):
        index = len(self.get_list())
        return self.get_email(index)
    # 连接到POP3服务器:
    def _connect(self):
        self.server = poplib.POP3(self.pop3_server)
        # 身份认证:
        self.server.user(self.email)
        self.server.pass_(self.password)
    # 可以打开或关闭调试信息:
    # server.set_debuglevel(1)
    def _get_welcome(self):
        # 可选:打印POP3服务器的欢迎文字:
        return self.server.getwelcome().decode('utf-8')
    # 获取一封邮件
    def _get_email(self, index):
        resp, lines, octets = self.server.retr(index)
        # lines存储了邮件的原始文本的每一行,
        # 可以获得整个邮件的原始文本:
        msg_content = b'\r\n'.join(lines).decode('utf-8')
        # 稍后解析出邮件:
        msg = Parser().parsestr(msg_content)
        # 可以根据邮件索引号直接从服务器删除邮件:
        # server.dele(index)
        return self._get_email_content(msg)
    def __del__(self):
        # 关闭连接:
        self.server.quit()
    # 解码
    def _decode_str(self, s):
        value, charset = decode_header(s)[0]
        if charset:
            value = value.decode(charset)
        return value
    # 获取编码
    def _guess_charset(self, msg):
        charset = msg.get_charset()
        if charset is None:
            content_type = msg.get('Content-Type', '').lower()
            pos = content_type.find('charset=')
            if pos >= 0:
                charset = content_type[pos + 8:].strip()
        return charset
    # 解析邮件 indent用于缩进显示:
    def _parse_email(self, msg, indent=0):
        if indent == 0:
            for header in ['From', 'To', 'Subject']:
                value = msg.get(header, '')
                if value:
                    if header == 'Subject':
                        value = self._decode_str(value)
                    else:
                        hdr, addr = parseaddr(value)
                        name = self._decode_str(hdr)
                        value = u'%s <%s>' % (name, addr)
                self.message[header] = value
        if (msg.is_multipart()):
            parts = msg.get_payload()
            for n, part in enumerate(parts):
                self._parse_email(part, indent + 1)
        else:
            content_type = msg.get_content_type()
            if content_type == 'text/plain' or content_type == 'text/html':
                content = msg.get_payload(decode=True)
                charset = self._guess_charset(msg)
                if charset:
                    content = content.decode(charset)
                self.message["text"].append(content)
            else:
                self.message["attachment"].append(content_type)
    # 获取邮件内容
    def _get_email_content(self, msg):
        self._parse_email(msg)
        return self.message
if __name__ == '__main__':
    email = EmailReceiver("xxx@163.com", "xxx")
    msg = email.get_last_email()
    print(msg)

项目地址:

https://github.com/mouday/email_helper


参考:

廖雪峰python 电子邮件

相关文章
|
21天前
|
开发者 Python
如何在Python中管理模块和包的依赖关系?
在实际开发中,通常会结合多种方法来管理模块和包的依赖关系,以确保项目的顺利进行和可维护性。同时,要及时更新和解决依赖冲突等问题,以保证代码的稳定性和可靠性
35 4
|
19天前
|
算法 数据安全/隐私保护 开发者
马特赛特旋转算法:Python的随机模块背后的力量
马特赛特旋转算法是Python `random`模块的核心,由松本真和西村拓士于1997年提出。它基于线性反馈移位寄存器,具有超长周期和高维均匀性,适用于模拟、密码学等领域。Python中通过设置种子值初始化状态数组,经状态更新和输出提取生成随机数,代码简单高效。
101 63
|
20天前
|
测试技术 Python
手动解决Python模块和包依赖冲突的具体步骤是什么?
需要注意的是,手动解决依赖冲突可能需要一定的时间和经验,并且需要谨慎操作,避免引入新的问题。在实际操作中,还可以结合使用其他方法,如虚拟环境等,来更好地管理和解决依赖冲突😉。
|
20天前
|
持续交付 Python
如何在Python中自动解决模块和包的依赖冲突?
完全自动解决所有依赖冲突可能并不总是可行,特别是在复杂的项目中。有时候仍然需要人工干预和判断。自动解决的方法主要是提供辅助和便捷,但不能完全替代人工的分析和决策😉。
|
26天前
|
JSON Linux 数据格式
Python模块:从入门到精通,只需一篇文章!
Python中的模块是将相关代码组织在一起的单元,便于重用和维护。模块可以是Python文件或C/C++扩展,Python标准库中包含大量模块,如os、sys、time等,用于执行各种任务。定义模块只需创建.py文件并编写代码,导入模块使用import语句。此外,Python还支持自定义模块和包,以及虚拟环境来管理项目依赖。
Python模块:从入门到精通,只需一篇文章!
|
21天前
|
Python
Python的模块和包
总之,模块和包是 Python 编程中非常重要的概念,掌握它们可以帮助我们更好地组织和管理代码,提高开发效率和代码质量
31 5
|
20天前
|
数据可视化 Python
如何在Python中解决模块和包的依赖冲突?
解决模块和包的依赖冲突需要综合运用多种方法,并且需要团队成员的共同努力和协作。通过合理的管理和解决冲突,可以提高项目的稳定性和可扩展性
|
1月前
|
Python
在Python中,可以使用内置的`re`模块来处理正则表达式
在Python中,可以使用内置的`re`模块来处理正则表达式
41 5
|
1月前
|
Java 程序员 开发者
Python的gc模块
Python的gc模块
|
1月前
|
数据采集 Web App开发 JavaScript
python-selenium模块详解!!!
Selenium 是一个强大的自动化测试工具,支持 Python 调用浏览器进行网页抓取。本文介绍了 Selenium 的安装、基本使用、元素定位、高级操作等内容。主要内容包括:发送请求、加载网页、元素定位、处理 Cookie、无头浏览器设置、页面等待、窗口和 iframe 切换等。通过示例代码帮助读者快速掌握 Selenium 的核心功能。
138 5