python3 收发邮件,解析邮件内容,附带使用说明,GUI,以及一些遇到的坑

环境

python3.8.3

代码

#!/usr/bin/python3
# -*- coding: UTF-8 -*-
import tkinter as tk
from tkinter import *
import tkinter.messagebox
import smtplib
import poplib
from email.mime.text import MIMEText
from email.header import Header
from email.parser import Parser
from email.header import decode_header
from email.utils import parseaddr

#使用腾讯QQ邮箱发送邮件
def send_email_by_qq():
    def send_email():
        message = MIMEText(entry_message_context.get(), 'plain', 'utf-8')
        message["From"] = Header(entry_sender_email_address.get())
        message["To"] = Header(entry_receiver_email.get())
        message["Subject"] = Header(entry_message_subject.get(), 'utf-8')
        email_client = smtplib.SMTP_SSL(smtp_server_host, smtp_server_port)
        try:
            # 验证邮箱及密码是否正确
            email_client.login(entry_sender_email_address.get(), entry_sender_email_password.get())
            tk.messagebox.showinfo('恭喜','发送成功,请查收')
        except:
            tk.messagebox.showerror('错误','账户OR密码错误')
        else:
            email_client.sendmail(entry_sender_email_address.get(), entry_receiver_email.get(), message.as_string())
        finally:
            email_client.close()

    global qq_send_window
    qq_send_window = tk.Tk()
    qq_send_window.title('使用QQ邮箱发送邮件')
    qq_send_window.geometry('500x350')

    #获取邮件信息
    tk.Label(qq_send_window, text='发件人邮箱:', font=('微软雅黑', 14)).place(x=50, y=10)
    tk.Label(qq_send_window, text='授权密码:', font=('微软雅黑', 14)).place(x=50, y=40)
    tk.Label(qq_send_window, text='收件人邮箱:', font=('微软雅黑', 14)).place(x=50, y=70)
    tk.Label(qq_send_window, text='服务器:smtp.qq.com', font=('微软雅黑', 14)).place(x=50, y=100)
    tk.Label(qq_send_window, text='服务器端口:465', font=('微软雅黑', 14)).place(x=50, y=130)
    tk.Label(qq_send_window, text='邮件主题:', font=('微软雅黑', 14)).place(x=50, y=160)
    tk.Label(qq_send_window, text='邮件内容:', font=('微软雅黑', 14)).place(x=50, y=190)

    #使用QQ邮箱时
    global smtp_server_host
    smtp_server_host = "smtp.qq.com"
    global smtp_server_port
    smtp_server_port = 465


    # 获取发件人邮箱
    global sender_email_address
    global entry_sender_email_address
    sender_email_address = tk.StringVar()
    entry_sender_email_address = tk.Entry(qq_send_window, textvariable=sender_email_address, font=('微软雅黑', 14))
    entry_sender_email_address.place(x=175, y=10)

    # 获取授权密码
    global sender_email_password
    global entry_sender_email_password
    sender_email_password = tk.StringVar()
    entry_sender_email_password = tk.Entry(qq_send_window, textvariable=sender_email_password, font=('微软雅黑', 14))
    entry_sender_email_password.place(x=175, y=40)

    # 获取收件人邮箱
    global receiver_email
    global entry_receiver_email
    receiver_email = tk.StringVar()
    entry_receiver_email = tk.Entry(qq_send_window, textvariable=receiver_email, font=('微软雅黑', 14))
    entry_receiver_email.place(x=175, y=70)

    # 获取邮件主题
    global message_subject
    global entry_message_subject
    message_subject = tk.StringVar()
    entry_message_subject = tk.Entry(qq_send_window, textvariable=message_subject, font=('微软雅黑', 14))
    entry_message_subject.place(x=175, y=160)

    # 获取邮件内容
    global message_context
    global entry_message_context
    message_context = tk.StringVar()
    entry_message_context = tk.Entry(qq_send_window, textvariable=message_context, font=('微软雅黑', 14))
    entry_message_context.place(x=175, y=190)

    #设置发送按钮
    send_button = tk.Button(qq_send_window, text='发送邮件', font=('微软雅黑', 12)
                                 , width=18, height=1, command=send_email)
    send_button.place(x=150, y=250)

#使用网易163邮箱发送邮件
def send_email_by_wy():
    def send_email():
        message = MIMEText(entry_message_context.get(), 'plain', 'utf-8')
        message["From"] = Header(entry_sender_email_address.get())
        message["To"] = Header(entry_receiver_email.get())
        message["Subject"] = Header(entry_message_subject.get(), 'utf-8')
        email_client = smtplib.SMTP_SSL(smtp_server_host, smtp_server_port)
        try:
            # 验证邮箱及密码是否正确
            email_client.login(entry_sender_email_address.get(), entry_sender_email_password.get())
            tk.messagebox.showinfo('恭喜','发送成功,请查收')
        except:
            tk.messagebox.showerror('错误','账户OR密码错误')
        else:
            email_client.sendmail(entry_sender_email_address.get(), entry_receiver_email.get(), message.as_string())
        finally:
            email_client.close()

    global wy_send_window
    wy_send_window = tk.Tk()
    wy_send_window.title('使用网易163邮箱发送邮件')
    wy_send_window.geometry('500x350')

    #获取邮件信息
    tk.Label(wy_send_window, text='发件人邮箱:', font=('微软雅黑', 14)).place(x=50, y=10)
    tk.Label(wy_send_window, text='授权密码:', font=('微软雅黑', 14)).place(x=50, y=40)
    tk.Label(wy_send_window, text='收件人邮箱:', font=('微软雅黑', 14)).place(x=50, y=70)
    tk.Label(wy_send_window, text='服务器:smtp.163.com', font=('微软雅黑', 14)).place(x=50, y=100)
    tk.Label(wy_send_window, text='服务器端口:465', font=('微软雅黑', 14)).place(x=50, y=130)
    tk.Label(wy_send_window, text='邮件主题:', font=('微软雅黑', 14)).place(x=50, y=160)
    tk.Label(wy_send_window, text='邮件内容:', font=('微软雅黑', 14)).place(x=50, y=190)

    #使用网易邮箱时
    global smtp_server_host
    smtp_server_host = "smtp.163.com"
    global smtp_server_port
    smtp_server_port = 465

    # 获取发件人邮箱
    global sender_email_address
    global entry_sender_email_address
    sender_email_address = tk.StringVar()
    entry_sender_email_address = tk.Entry(wy_send_window, textvariable=sender_email_address, font=('微软雅黑', 14))
    entry_sender_email_address.place(x=175, y=10)

    # 获取授权密码
    global sender_email_password
    global entry_sender_email_password
    sender_email_password = tk.StringVar()
    entry_sender_email_password = tk.Entry(wy_send_window, textvariable=sender_email_password, font=('微软雅黑', 14))
    entry_sender_email_password.place(x=175, y=40)

    # 获取收件人邮箱
    global receiver_email
    global entry_receiver_email
    receiver_email = tk.StringVar()
    entry_receiver_email = tk.Entry(wy_send_window, textvariable=receiver_email, font=('微软雅黑', 14))
    entry_receiver_email.place(x=175, y=70)

    # 获取邮件主题
    global message_subject
    global entry_message_subject
    message_subject = tk.StringVar()
    entry_message_subject = tk.Entry(wy_send_window, textvariable=message_subject, font=('微软雅黑', 14))
    entry_message_subject.place(x=175, y=160)

    # 获取邮件内容
    global message_context
    global entry_message_context
    message_context = tk.StringVar()
    entry_message_context = tk.Entry(wy_send_window, textvariable=message_context, font=('微软雅黑', 14))
    entry_message_context.place(x=175, y=190)

    #设置发送按钮
    send_button = tk.Button(wy_send_window, text='发送邮件', font=('微软雅黑', 12)
                                 , width=18, height=1, command=send_email)
    send_button.place(x=150, y=250)

def recv_email_by_pop3_qq():
    def recv_email():
        try:
            email_server = poplib.POP3_SSL(host=pop_server_host, port=pop_server_port, timeout=10)
        except:
            tk.messagebox.showerror('错误', '连接超时')
            exit(1)
        try:
            email_server.user(entry_email_address.get())
        except:
            tk.messagebox.showerror('错误', '邮箱不存在')
            exit(1)
        try:
            # 验证邮箱密码是否正确
            email_server.pass_(entry_email_password.get())
        except:
            tk.messagebox.showerror('错误', '密码错误')
            exit(1)

        email_count = len(email_server.list()[1])
        resp, lines, octets = email_server.retr(email_count)
        email_content = b'\r\n'.join(lines).decode('utf-8')
        msg = Parser().parsestr(email_content)
        text = Text(qq_recv_window, width=68, height=28)
        text.place(x=10, y=80)
        def decode_str(s):
            value, charset = decode_header(s)[0]
            if charset:
                value = value.decode(charset)
            return value

        def guess_charset(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 print_info(msg, indent=0):
            if indent == 0:
                for header in ['From', 'To', 'Subject']:
                    value = msg.get(header, '')
                    if value:
                        if header == 'Subject':
                            value = decode_str(value)
                        else:
                            hdr, addr = parseaddr(value)
                            name = decode_str(hdr)
                            value = u'%s <%s>' % (name, addr)
                    text.insert(INSERT, '%s%s: %s\n' % ('  ' * indent, header, value))
            if (msg.is_multipart()):
                parts = msg.get_payload()
                for n, part in enumerate(parts):
                    text.insert(INSERT,'%spart %s\n' % ('  ' * indent, n))
                    text.insert(INSERT,'%s--------------------' % ('  ' * indent))
                    print_info(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 = guess_charset(msg)
                    if charset:
                        content = content.decode(charset)
                    text.insert(INSERT, '%sText: %s\n' % ('  ' * indent, content))
                else:
                    text.insert(INSERT, '%sAttachment: %s\n' % ('  ' * indent, content_type))

        print_info(msg)
        email_server.close()

    global qq_recv_window
    qq_recv_window = tk.Tk()
    qq_recv_window.title('使用腾讯QQ邮箱接收邮件')
    qq_recv_window.geometry('500x500')

    tk.Label(qq_recv_window, text='收件人邮箱:', font=('微软雅黑', 14)).place(x=50, y=10)
    tk.Label(qq_recv_window, text='授权密码:', font=('微软雅黑', 14)).place(x=50, y=40)

    # 获取收件人邮箱
    global email_address
    global entry_email_address
    email_address = tk.StringVar()
    entry_email_address = tk.Entry(qq_recv_window, textvariable=email_address, font=('微软雅黑', 14))
    entry_email_address.place(x=175, y=10)

    # 获取授权密码
    global email_password
    global entry_email_password
    email_password = tk.StringVar()
    entry_email_password = tk.Entry(qq_recv_window, textvariable=email_password, font=('微软雅黑', 14))
    entry_email_password.place(x=175, y=40)

    email_address = entry_email_address.get()
    email_password = entry_email_password.get()
    pop_server_host = "pop.qq.com"
    pop_server_port = 995

    send_button = tk.Button(qq_recv_window, text='接收邮件', font=('微软雅黑', 12)
                            , width=18, height=1, command=recv_email)
    send_button.place(x=150, y=450)

def recv_email_by_pop3_wy():
    def recv_email_wy():
        try:
            email_server = poplib.POP3_SSL(host=pop_server_host, port=pop_server_port, timeout=10)
        except:
            tk.messagebox.showerror('错误', '连接超时')
            exit(1)
        try:
            email_server.user(entry_email_address.get())
        except:
            tk.messagebox.showerror('错误', '邮箱不存在')
            exit(1)
        try:
            email_server.pass_(entry_email_password.get())
        except:
            tk.messagebox.showerror('错误', '密码错误')
            exit(1)

        email_count = len(email_server.list()[1])
        resp, lines, octets = email_server.retr(email_count)
        email_content = b'\r\n'.join(lines).decode('utf-8')
        msg = Parser().parsestr(email_content)
        text = Text(wy_recv_window, width=68, height=28)
        text.place(x=10, y=80)
        def decode_str(s):
            value, charset = decode_header(s)[0]
            if charset:
                value = value.decode(charset)
            return value

        def guess_charset(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

        def print_info(msg, indent=0):
            if indent == 0:
                for header in ['From', 'To', 'Subject']:
                    value = msg.get(header, '')
                    if value:
                        if header == 'Subject':
                            value = decode_str(value)
                        else:
                            hdr, addr = parseaddr(value)
                            name = decode_str(hdr)
                            value = u'%s <%s>' % (name, addr)
                    text.insert(INSERT, '%s%s: %s\n' % ('  ' * indent, header, value))
            if (msg.is_multipart()):
                parts = msg.get_payload()
                for n, part in enumerate(parts):
                    text.insert(INSERT,'%spart %s\n' % ('  ' * indent, n))
                    text.insert(INSERT,'%s--------------------' % ('  ' * indent))
                    print_info(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 = guess_charset(msg)
                    if charset:
                        content = content.decode(charset)
                    text.insert(INSERT, '%sText: %s\n' % ('  ' * indent, content))
                else:
                    text.insert(INSERT, '%sAttachment: %s\n' % ('  ' * indent, content_type))

        print_info(msg)
        email_server.close()

    global wy_recv_window
    wy_recv_window = tk.Tk()
    wy_recv_window.title('使用网易163邮箱接收邮件')
    wy_recv_window.geometry('500x500')

    tk.Label(wy_recv_window, text='收件人邮箱:', font=('微软雅黑', 14)).place(x=50, y=10)
    tk.Label(wy_recv_window, text='授权密码:', font=('微软雅黑', 14)).place(x=50, y=40)

    # 获取收件人邮箱
    global email_address
    global entry_email_address
    email_address = tk.StringVar()
    entry_email_address = tk.Entry(wy_recv_window, textvariable=email_address, font=('微软雅黑', 14))
    entry_email_address.place(x=175, y=10)

    # 获取授权密码
    global email_password
    global entry_email_password
    email_password = tk.StringVar()
    entry_email_password = tk.Entry(wy_recv_window, textvariable=email_password, font=('微软雅黑', 14))
    entry_email_password.place(x=175, y=40)

    email_address = entry_email_address.get()
    email_password = entry_email_password.get()
    pop_server_host = "pop.163.com"
    pop_server_port = 995

    send_button = tk.Button(wy_recv_window, text='接收邮件', font=('微软雅黑', 12)
                            , width=18, height=1, command=recv_email_wy)
    send_button.place(x=150, y=450)

def main():
    mainwindow=tk.Tk()
    mainwindow.title('邮件收发器')
    mainwindow.geometry('600x480')
    HelloMessage=tk.Label(mainwindow,text='欢迎使用本邮件收发器!',
                      font=('微软雅黑',12),
                      width=20,height=2)
    HelloMessage.pack()
    #提示选择
    InfoMessage1=tk.Label(mainwindow,text='本软件目前仅添加了对腾讯QQ邮箱'
                                 '\n和网易163邮箱的支持',
                     font=('微软雅黑',12)
                     ,width=25,height=2)
    InfoMessage1.pack()

    InfoMessage2=tk.Label(mainwindow,text='请选择使用哪种操作',
                     font=('微软雅黑',20)
                     ,width=25,height=4)
    InfoMessage2.pack()

    choose_qq_email1 = tk.Button(mainwindow, text='使用腾讯QQ邮箱发邮件', font=('微软雅黑', 12)
                                , width=18, height=1,command=send_email_by_qq)
    choose_qq_email1.place(x=100, y=250)

    choose_qq_email2 = tk.Button(mainwindow, text='使用腾讯QQ邮箱收邮件', font=('微软雅黑', 12)
                                , width=18, height=1,command=recv_email_by_pop3_qq)
    choose_qq_email2.place(x=100, y=300)

    choose_wy_email1 = tk.Button(mainwindow, text='使用网易163邮箱发邮件', font=('微软雅黑', 12)
                                , width=18, height=1,command=send_email_by_wy)
    choose_wy_email1.place(x=350, y=250)

    choose_wy_email2 = tk.Button(mainwindow, text='使用网易163邮箱收邮件', font=('微软雅黑', 12)
                                , width=18, height=1,command=recv_email_by_pop3_wy)
    choose_wy_email2.place(x=350, y=300)

    mainwindow.mainloop()

main()

碰到的坑

在中间的from和to之间不要加utf8,不然可能会乱码导致邮件发送失败

        message = MIMEText(entry_message_context.get(), 'plain', 'utf-8')
        message["From"] = Header(entry_sender_email_address.get())
        message["To"] = Header(entry_receiver_email.get())
        message["Subject"] = Header(entry_message_subject.get(), 'utf-8')

使用手册

使用QQ邮箱时,需要更改一下设置

第一步打开邮箱首页,点击设置
在这里插入图片描述
第二步切换到账户
在这里插入图片描述
第三步,往下拉找到服务栏,点击开启pop3和imap服务,发送短信进行验证
在这里插入图片描述
需要发送短信,按照要求发送之后点击我已发送

在这里插入图片描述
得到授权码,将其复制保存,之后有用

在这里插入图片描述

使用网易163邮箱,基本同上,别忘了保存授权密码

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
参考文章
1.Python3+smtplib+poplib+imaplib实现发送和收取邮件(以qq邮箱为例)
2.POP3收取邮件

猜你喜欢

转载自blog.csdn.net/weixin_45067603/article/details/106857198