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

简介: 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 电子邮件

相关文章
|
15天前
|
机器学习/深度学习 存储 Python
|
1天前
|
Python Windows
python中的异常与模块
python中的异常与模块
8 1
|
11天前
|
JSON 数据格式 Python
Python标准库中包含了json模块,可以帮助你轻松处理JSON数据
【4月更文挑战第30天】Python的json模块简化了JSON数据与Python对象之间的转换。使用`json.dumps()`可将字典转为JSON字符串,如`{&quot;name&quot;: &quot;John&quot;, &quot;age&quot;: 30, &quot;city&quot;: &quot;New York&quot;}`,而`json.loads()`则能将JSON字符串转回字典。通过`json.load()`从文件读取JSON数据,`json.dump()`则用于将数据写入文件。
16 1
|
12天前
|
Python
Python实现压缩解压---tarfile模块详解
Python实现压缩解压---tarfile模块详解
|
12天前
|
Linux Python Windows
Python中time和datetime模块详解
Python中time和datetime模块详解
|
12天前
|
存储 Linux 数据安全/隐私保护
python的压缩模块zipfile详解
python的压缩模块zipfile详解
|
12天前
|
Linux Python Windows
python的os模块详细解读(二)
python的os模块详细解读(二)
|
12天前
|
移动开发 Linux Shell
python的os模块详细解读(一)
python的os模块详细解读(一)
python的os模块详细解读(一)
|
12天前
|
Python 容器
python内置函数、数学模块、随机模块(二)
python内置函数、数学模块、随机模块(二)
|
12天前
|
索引 Python
python内置函数、数学模块、随机模块(一)
python内置函数、数学模块、随机模块(一)