基于SMTP协议服务器和python语言开发的GUI界面邮件发送程序V0.0

一,开发需求和思路

1.开发需求:

你是不是有这么一种需求:在使用邮箱(qq邮箱或163邮箱)时,许多时候都需要我们重新登录(或者隔一段时间),那么如果忘记密码,重新设置将是一件很痛苦的事,加之,我们对邮箱使用很频繁,能不能有种产品能使我们不用登入账户,同时桌面应用程序那样而不用去登入网页版邮箱网站,从而满足我们的发送邮件的基本功能实现呢?答案是有的!
在开源IT时代,我们有很多方法和工具来实现我们的需求,作为极客,我们可以发现SMTP协议背后的一种特殊的发送邮件过程:基于邮箱服务商服务器(IMAP,SMTP,POS3等)来绑定对应程序,从而达到免登录,二次程序开发实现邮件发送功能(简单的理解下就可以了,可以自行百度)。
在这里插入图片描述

2.开发思路:

python是具有强大第三方库的一门超级语言,我们可以可控的选择简单且易上手的第三方库,经过笔者比对发现python的yagmail库是个不错的选择,另外,我们的需求开发出的是产品级(简陋的,嘻嘻),那么就不能再运行时再打开代码,那样会很麻烦,我们要设计出有UI交互界面的程序,由于python自带tkinter库,我们可以用来GUI开发比较方便简单。
在这里插入图片描述

3.前期准备

概括下前面的,我们需要准备并熟悉好如下东西:
(1)设置好所用邮箱服务商的服务器设置,备好对应的服务密码(不是账户登入密码);
(2)python的yagmail库,了解下使用方法;
(3)确保自带的tkinter包存在(一般没问题),了解下使用方法;
由于笔者前面做过这方面的介绍,在此不一一赘述了,下面给出链接:
python-基于yagmail库开发自动邮件发送程序

4.功能叙述

在这里插入图片描述

二,编写代码

1.处理程序模块

注意:代码中涉及隐私的,均已屏蔽,对应内容要根据自己实际引入

from tkinter import *  #tk图形库,标准库之一
from PIL import Image,ImageTk#由于我们设置窗口图片背景,所以要引入
import tkinter.filedialog#tk库里的文件选择框模块
import yagmail#邮箱发送的第三方库
import time#用来显示时间的
import datetime#用来在日历上获取并显示日历功能的
import calendar
root = Tk()#程序主窗体

#设置好全局变量,以防程序识别错误
global to, title, content,user, password, port, host

#yagmail库基本参数设置
user = ''  # 对应自己的主人邮箱
password = ''   # 对应自己邮箱申请的服务密码,上面的步骤有介绍
port = '465'  # 端口
host = 'smtp.163.com'  # 对应自己邮箱服务的服务器地址
mail = yagmail.SMTP(user, password, host, port)#yagmail库的基本配置

#控件实例
photo1=Image.open('background1.png')#同代码文件目录下的图片文件,用于背景,
background_image1 = ImageTk.PhotoImage(photo1.resize((500, 400)))
to_text = Text(root,width=26,height=1.55,font=('黑体',13))#收件人输入框
title_text = Text(root,width=26,height=1.55,font=('黑体',13))#邮件主题输入框
content_text = Text(root,width=75,height=12,font=('黑体',13))#邮件内容输入框
tipout_label = Label(root,text='暂无操作!',font=('黑体',13),bg='green',fg='white')#其文本内容对应着实际操作程序的操作提示
time_label=Label(root,text='',font=('黑体',16),fg='green')#用于时间显示
menubar=Menu(root)#主菜单
menuout=Menu(root,tearoff=0)#弹出菜单,清楚功能实现的汇集
root['menu']=menubar#设置主菜单

def gettime():#利用time库获取当前时间的函数
    timestr = time.strftime("%Y年%m月%d日 %H时:%M分:%S秒,%A")#获取并格式化输出时间
    time_label.configure(text=timestr)
    root.after(1000,gettime)#每一秒内(对应1000)刷新时间
gettime()#调用时间显示函数

def show_datetime():#利用calendar库显示日历的函数
    winnew=Toplevel(root)#顶层窗体
    winnew.title('日历窗口')
    winnew.geometry('500x400+700+50')
    winnew.iconbitmap('mail.ico')#设置窗口图标,统一使用同一张
    tipout_label['text'] = '你点开了日历窗口!'#操作变化提示,基本每个模块被使用时都会含有
    date_time=datetime.datetime.today()
    year=date_time.year#获取当前年份
    month=date_time.month#获取当前月份
    calendar.setfirstweekday(firstweekday=6)#设置日历的初始天(第一天)
    dates=calendar.month(year,month)#获得日历的字符串类型
    alldate=Label(winnew,text='',bg='green',fg='white',width=1000,height=600,font=('黑体',20),image=background_image1,compound = CENTER)
    alldate.configure(text=dates)
    alldate.pack()

global lists,textbooks#标注全局变量,在主窗体框架逻辑下,可以在关闭窗口仍有记忆功能,从而实现保存功能
textbooks=Label(root,text='无')
lists=['']#由于后面以第一个列表元素作为显示,所以初始元素先设置为空字符串
def textbook():
    text_win=Toplevel(root)
    text_win.title('草稿窗口')
    text_win.geometry('740x520+500+50')
    text_win.iconbitmap('mail.ico')
    tipout_label['text'] = '你点开了草稿窗口!'
    draft_paper=Text(text_win,width=100,height=30)#该实例为草稿箱输入和文本显示框功能
    draft_paper.insert('1.0', lists[0])#插入所保存的内容,相当记忆重现,实现了保存功能逻辑
    def saves():
        textbooks .configure(text=draft_paper.get(1.0, 'end'))
        lists[0]=textbooks['text']#点击保存按钮,触发获取文本框的内容,可在编写过程任一时刻保存,避免丢失
        tipout_label['text'] = "你保存了草稿箱里的内容!"
    def clears():
        draft_paper.delete('1.0', 'end')
        tipout_label['text'] = "你清空了草稿箱里的内容!"
    save_button = Button(text_win, text='保存', command=saves,relief=RAISED,fg='white',bg='green',font=('黑体',14),width=10,height=2).place(x=19,y=430)
    clear_button=Button(text_win, text='清空所有内容', command=clears,relief=RAISED,fg='white',bg='green',font=('黑体',14),width=16,height=2).place(x=150,y=430)
    draft_paper.place(x=19,y=18)

#菜单项加入:
menubar.add_command(label = "  草稿   ", command=textbook)
menubar.add_command(label = "     日历  ", command=show_datetime)

def pops(event):#右键响应函数,弹出菜单
    menuout.post(event.x_root, event.y_root)#这两个变量可让在在窗口任一触发部位弹出

def Clear_to():#清空收件人输入框函数
    to_text.delete('1.0', 'end')
    tipout_label['text']='你清空了收件人窗口!'

def Clear_title():#清空邮件主题输入框函数
    title_text.delete('1.0', 'end')
    tipout_label['text'] ='你清空了主题窗口!'

def Clear_content():#清空邮件内容输入框函数
    content_text.delete('1.0', 'end')
    tipout_label['text'] ='你清空了内容窗口!'

#用于其他模块下错误信息提示的使用,使用时调用即可
def message():
    tipout_label['text'] = "输入有误或已全清空!请重新输入所有内容!"
    to_text.delete('1.0', 'end')#文本框控件中第一个字符的位置是 1.0,可以用数字 1.0 或字符串"1.0"来表示
    title_text.delete('1.0', 'end')
    content_text.delete('1.0', 'end')

filename=''#文件地址变量,先初始化
#附件控件控制函数
def Attachments():
    global filename#在函数内,需声明全局变量,可供Sendto使用
    filename = tkinter.filedialog.askopenfilename()#在弹出框内选择文件,并获得字符串型的文件地址
    if filename != '':#用filename是否为空字符串来判断,是否文件附件功能和辨别相关
        tipout_label['text']='您选择的文件是' + filename
    else:
        tipout_label['text']='您没有选择任何文件'

#主函数:处理邮件发送
def Sendto():
    to = to_text.get('1.0', 'end')#获取相关内容
    title = title_text.get('1.0', 'end')
    content = content_text.get('1.0', 'end')
    if filename =='':#根据filename值来选择发送时是否包含附件
        try:  # 检查邮件发送是否成功很重要;
            mail.send(to, title, content)
            tipout_label['text'] = "发送成功!"
        except:
            message()
    elif filename !='':
        try:
            mail.send(to, title, content,filename)
            tipout_label['text'] = "发送成功!"
        except:
            message()

root.bind("<Button-3>",pops)#<Button-3>为右键点击事件,用于触发弹出菜单
menuout.add_command(label='清空收件人窗口',command=Clear_to)
menuout.add_command(label='清空主题窗口',command=Clear_title)
menuout.add_command(label='清空内容窗口',command=Clear_content)
menuout.add_command(label='清空所有输入窗口',command=message)

#控件属性设置
to_label=Label(root,text='收件人:',font=('黑体',13)).place(x=10,y=20)#收件人提示标签
title_label=Label(root,text='主题:',font=('黑体',13)).place(x=10,y=80)#主题标签
contents_label=Label(root,text='内容:',font=('黑体',13)).place(x=10,y=140)#内容标签
to_text.place(x=90,y=20)
title_text.place(x=90,y=80)
content_text.place(x=90,y=140)
attachments_button=Button(root,text='附件地址',font=('黑体',13),fg='white',bg='green',command=Attachments,width=10,height=2,relief=RAISED)
attachments_button.place(x=30,y=370)
check_button=Button(root,text='确认发送',font=('黑体',13),fg='white',bg='green',command=Sendto,width=10,height=2,relief=RAISED).place(x=30,y=450)
tip_label=Label(root,text='程序状态:',font=('黑体',13)).place(x=10,y=530)
tipout_label.place(x=120,y=530)
time_label.place(x=340,y=85)

#主窗口设置
root.title('基于SMTP协议自动发送的邮箱程序')#设置窗口标题
root.geometry('800x600+300+100')#设置窗口大小和在系统显示下的位置
root.iconbitmap('mail.ico')#设置窗体图标
root.mainloop()

2.运行效果展示:

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

三,程序打包

本次开发时,所使用的到的第三方库均已本地安装,pycharm虚拟环境也已继承),所以pycharm和本地PythonIDLE均可以运行执行代码。

1.程序打包步骤演示:

(1)先下载安装好pyinstaller安装如下:
pyinstaller安装
(2)Windows下打开命令行:
在这里插入图片描述
(3)进入自己所在的py文件目录下:
在这里插入图片描述(4)进入目录后,输入 :pyinstaller -F -w -i <包含文件类型名的文件全名>
在这里插入图片描述

(5)在py文件同目录下回生成以下目录和其他文件:
在这里插入图片描述

(6)进入dist文件,我们发现打包完成的exe程序,由于我们的程序exe还不包含里面所用到的图片,会出现以下错误:
在这里插入图片描述

(7)我们有解决方法,一是你要先前去掉代码对应的图片插入,二是像下面一样,把对应的图片文件复制或转移到同exe文件目录下,再重新打开,程序运行成功:
在这里插入图片描述
在这里插入图片描述

2.开发问题中遇到的问题及解决方法汇总:

报错:ModuleNotFoundError: No module named 'PIL’解决方法
python 获取当前年份和月份
Python中tkinter.filedialog
Python-Tkinter图形化界面设计(详细教程 )
用tkinter.pack设计复杂界面布局
python-基于yagmail库开发自动邮件发送程序
最后,由于开发经验尚浅和程序其中的一些瑕疵,希望大家理解!
对于文本内容有何问题,欢迎批评指正!!!

  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值