PyQT 跟我学做密码管理器(5) —— 备份数据到邮箱

声明:本文借鉴https://blog.csdn.net/bigbennyguo/article/details/50755207 修改而来

前言

借鉴的文章是基于python2+pyqt4,本文是基于python3+pyqt5

环境

编辑器:Sublime Text3

操作系统:win10

Python3

所需要的库:主要是PyQT5,因为加了一点拓展功能,所以还有sqlite3,Image,pyinstaller

pip3 install pyqt5
pip3 install pyqt5-tools
pip3 install sqilte3
pip3 install Image
pip3 install pyinstaller

首先是pyqt5, 这个是我们的主要工具,用来做界面的,pyqt5-tools这个库主要是是在用QT Creator设计好界面之后,将ui文件转化为py文件;

sqlite3这个库可以安也可以不安,因为pyqt5里面有一个模块QtSql,它支持sqlite的操作;
Image这个库主要是用来处理一下图片资源,以及最后程序的图标的
pyinstaller 最后将程序转化为可执行的exe文件

邮箱登陆

python自带的smtblib库可以登陆邮箱,本文主要介绍如何登陆邮箱

如果是公司自己的邮箱,可能直接使用smtplib.SMTP().login()也许就登陆上去了

每个公司的邮箱可能不一样,这里介绍qq/163的邮箱登陆

使用python来登陆qq/163邮箱,第一件事,得从邮箱里面获取授权码

授权码应该是一个16位字母组成的

拿到授权码之后,我们就可以进行邮箱登陆了

import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart   class SendEmail():global send_userglobal email_hostglobal passwordglobal user_listglobal subpassword = ""                   #授权码email_host = "smtp.qq.com"     #邮箱host,如果是163的,则是smtp.163.comsend_user = "123@qq.com"       #自己的qq邮箱账户或者163账户user_list = ['123@qq.com','123@163.com']        #收件人列表sub = "密码管理系统-密码备份"                    #邮件主题def __init__(self):self.server = smtplib.SMTP_SSL()self.server.connect(email_host,465)code,resp=self.server.login(send_user,password)    #登陆邮箱if code in (235, 503):                             #登陆成功的话,code应该为235,已经登陆过的话,code应该是503print('login success')else:print('没有登陆成功')return

如果登陆成功之后呢,就可以开始构造邮件了,构造邮件用到了python自带的email模块

如下:

        user = "shape" + "<" + send_user + ">"        #组装邮件消息头,包括收件人,发件人,邮件主题self.message = MIMEMultipart('mixed') self.message['Subject'] = subself.message['From'] = userself.message['To'] = ";".join(user_list)

邮件正文:

text_plain = MIMEText(content,'plain', 'utf-8') 

邮件附件:

#构造附件sendfile=open(filename,'rb').read()text_att = MIMEText(sendfile, 'base64', 'utf-8') text_att["Content-Type"] = 'application/octet-stream'  new_name=filename.split('\\')[-1]print(new_name)text_att.add_header('Content-Disposition', 'attachment', filename=new_name)

完整的邮件类如下:

import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart   class SendEmail():global send_userglobal email_hostglobal passwordglobal user_listglobal subpassword = ""                   #授权码email_host = "smtp.qq.com"     #邮箱host,如果是163的,则是smtp.163.comsend_user = "123@qq.com"       #自己的qq邮箱账户或者163账户user_list = ['123@qq.com','123@163.com']        #收件人列表sub = "密码管理系统-密码备份"                    #邮件主题def __init__(self):self.server = smtplib.SMTP_SSL()self.server.connect(email_host,465)code,resp=self.server.login(send_user,password)    #登陆邮箱if code in (235, 503):                             #登陆成功的话,code应该为235,已经登陆过的话,code应该是503print('login success')else:print('没有登陆成功')returnuser = "shape" + "<" + send_user + ">"        #组装邮件消息头,包括收件人,发件人,邮件主题self.message = MIMEMultipart('mixed') self.message['Subject'] = subself.message['From'] = userself.message['To'] = ";".join(user_list)def send_textmail(self,content):                        #发送文本邮件text_plain = MIMEText(content,'plain', 'utf-8')    self.message.attach(text_plain)def send_Enclosuremail(self,filename):                #发送附件#构造附件sendfile=open(filename,'rb').read()text_att = MIMEText(sendfile, 'base64', 'utf-8') text_att["Content-Type"] = 'application/octet-stream'  new_name=filename.split('\\')[-1]print(new_name)text_att.add_header('Content-Disposition', 'attachment', filename=new_name)self.message.attach(text_att) def sendmailforbackup(self,content,file):self.send_textmail(content)self.send_Enclosuremail(file)#self.server.sendmail(send_user,user_list,self.message.as_string())def close(self):                                    #关闭邮件severprint('mail class close')self.server.close()

为密码管理器添加备份功能

其实在上一篇文章中,备份功能的接口已经预留好了,仅仅是没有实现它
要做的就是,从数据库中读取所有的数据,然后处理一下数据内容,将其转化为字符串
将数据库文件作为附件同时通过邮件发送出去

    def backupAction_def(self):cur = self.conn.cursor()cur.execute('SELECT * FROM INFO')data = cur.fetchall()print(len(data))a=' '.join(['Website', 'Username', 'Password', 'Url'])+'\n'for items in data:for item in items:a=a+str(item)+' 'a =a+'\n'myEmail=SendEmail()myEmail.sendmailforbackup(a,self.dbpath)myEmail.close()

小结

至此,这个密码管理器的所有功能全部完成。

目前就剩临门一脚了,将代码整合,打包生成exe文件,这个我们下一篇文章再说

目前的代码如下:

# -*- coding: utf-8 -*-
# @Date     : 2018-12-17 16:50:23
# @Author   : Jimy_Fengqi (jmps515@163.com)
# @Link     : https://blog.csdn.net/qiqiyingse
# @Version  : V1.0
# @pyVersion: 3.6import sys,sqlite3,os
from PyQt5.QtWidgets import *
from PyQt5.QtGui import QIcon, QFont
from PyQt5.QtCore import *
import imagesimport smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart   class SendEmail():global send_userglobal email_hostglobal passwordglobal user_listglobal subpassword = ""                   #授权码email_host = "smtp.qq.com"     #邮箱host,如果是163的,则是smtp.163.comsend_user = "123@qq.com"       #自己的qq邮箱账户或者163账户user_list = ['123@qq.com','123@163.com']        #收件人列表sub = "密码管理系统-密码备份"                    #邮件主题def __init__(self):self.server = smtplib.SMTP_SSL()self.server.connect(email_host,465)code,resp=self.server.login(send_user,password)    #登陆邮箱if code in (235, 503):                             #登陆成功的话,code应该为235,已经登陆过的话,code应该是503print('login success')else:print('没有登陆成功')returnuser = "shape" + "<" + send_user + ">"        #组装邮件消息头,包括收件人,发件人,邮件主题self.message = MIMEMultipart('mixed') self.message['Subject'] = subself.message['From'] = userself.message['To'] = ";".join(user_list)def send_textmail(self,content):                        #发送文本邮件text_plain = MIMEText(content,'plain', 'utf-8')    self.message.attach(text_plain)def send_Enclosuremail(self,filename):                #发送附件#构造附件sendfile=open(filename,'rb').read()text_att = MIMEText(sendfile, 'base64', 'utf-8') text_att["Content-Type"] = 'application/octet-stream'  new_name=filename.split('\\')[-1]print(new_name)text_att.add_header('Content-Disposition', 'attachment', filename=new_name)self.message.attach(text_att) def sendmailforbackup(self,content,file):self.send_textmail(content)self.send_Enclosuremail(file)#self.server.sendmail(send_user,user_list,self.message.as_string())def close(self):                                    #关闭邮件severprint('mail class close')self.server.close()class PasswordManagerSystem(QMainWindow):def __init__(self):super(PasswordManagerSystem, self).__init__()self.initToolbar()self.initDB()self.initGrid()#self.current_row = 0self.setGeometry(300, 300, 650, 300)self.setWindowTitle('密码管理器')self.setWindowIcon(QIcon(':images/logo.jpg'))def initToolbar(self):newAction = QAction(QIcon(':images/new.png'), 'New Ctrl+N', self)editAction = QAction(QIcon(':images/edit.png'), 'Edit Ctrl+E', self)delAction = QAction(QIcon(':images/del.png'), 'Delete', self)backupAction = QAction(QIcon(':images/backup.png'), 'Backup Ctrl+B', self)newAction.setShortcut('Ctrl+N')editAction.setShortcut('Ctrl+E')delAction.setShortcut('Delete')backupAction.setShortcut('Ctrl+B')newAction.triggered.connect(self.newAction_def)editAction.triggered.connect(self.editAction_def)delAction.triggered.connect(self.delAction_def)backupAction.triggered.connect(self.backupAction_def)self.tb_new = self.addToolBar('New')self.tb_edit = self.addToolBar('Edit')self.tb_del = self.addToolBar('Del')self.tb_backup = self.addToolBar('Backup')self.tb_new.addAction(newAction)self.tb_edit.addAction(editAction)self.tb_del.addAction(delAction)self.tb_backup.addAction(backupAction)def backupAction_def(self):cur = self.conn.cursor()cur.execute('SELECT * FROM INFO')data = cur.fetchall()print(len(data))a=' '.join(['Website', 'Username', 'Password', 'Url'])+'\n'for items in data:for item in items:a=a+str(item)+' 'a =a+'\n'myEmail=SendEmail()myEmail.sendmailforbackup(a,self.dbpath)myEmail.close()def initDB(self):home = os.path.expanduser('~')if '.PasswordManageSystem' not in os.listdir(home):os.mkdir(os.path.join(home, '.PasswordManageSystem'))self.dbpath = os.path.join(home, '.PasswordManageSystem', 'PasswordManagement.db')if os.path.exists(self.dbpath):self.conn = sqlite3.connect(self.dbpath)self.conn.isolation_level = Noneelse:self.conn = sqlite3.connect(dbpath)self.conn.isolation_level = Noneself.conn.execute('''CREATE TABLE INFO(ID int PRIMARY KEY NOT NULL,WEBSITE char(255),USERNAME char(255),PASSWORD char(255),URL char(255))''')cur = self.conn.cursor()cur.execute('SELECT * FROM INFO')self.displayData = cur.fetchall()cur.close()self.current_row = len(self.displayData)def initGrid(self):self.grid = QTableWidget()self.setCentralWidget(self.grid)self.grid.setColumnCount(4)self.grid.setRowCount(0)column_width = [75, 150, 270, 150]for column in range(4):self.grid.setColumnWidth(column, column_width[column])headerlabels = ['Website', 'Username', 'Password', 'Url']self.grid.setHorizontalHeaderLabels(headerlabels)self.grid.setEditTriggers(QAbstractItemView.NoEditTriggers)self.grid.setSelectionBehavior(QAbstractItemView.SelectRows)for row in range(len(self.displayData)):#根据数据库数据的数目,决定循环次数self.grid.insertRow(row)            #插入一行data = self.displayData[row]        #获取一条数据for i in range(4):item=data[i+1]                #获取一条数据中的一个元素#print(row, i, item)new_item = QTableWidgetItem(item)    #将数据转化为QTableWidgetItemself.grid.setItem(row, i, new_item)    #插入数据def newAction_def(self):data = self.showDialog()if data[0]:self.current_row += 1self.conn.execute("INSERT INTO INFO VALUES(%d, '%s', '%s', '%s', '%s')"% (self.current_row, data[1], data[2], data[3], data[4]))self.grid.insertRow(self.current_row - 1)for i in range(4):new_item = QTableWidgetItem(data[i + 1])self.grid.setItem(self.current_row - 1, i, new_item)def editAction_def(self):selected_row = self.grid.selectedItems()if selected_row:edit_row = self.grid.row(selected_row[0])old_data = []for i in range(4):old_data.append(self.grid.item(edit_row, i).text())new_data = self.showDialog(*old_data)if new_data[0]:self.conn.execute('''UPDATE INFO SETWEBSITE = '%s', USERNAME = '%s',PASSWORD = '%s', URL = '%s'WHERE ID = '%d' '''% (new_data[1], new_data[2], new_data[3], new_data[4], edit_row + 1))for i in range(4):new_item = QTableWidgetItem(new_data[i + 1])self.grid.setItem(edit_row, i, new_item)else:self.showHint()def delAction_def(self):selected_row = self.grid.selectedItems()if selected_row:del_row = self.grid.row(selected_row[0])self.grid.removeRow(del_row)self.conn.execute("DELETE FROM INFO WHERE ID = %d" % (del_row + 1))for index in range(del_row + 2, self.current_row + 1):self.conn.execute("UPDATE INFO SET ID = %d WHERE ID = %d" % ((index - 1), index))self.current_row -= 1else:self.showHint()def showHint(self):hint_msg = QMessageBox()hint_msg.setText('No selected row!')hint_msg.addButton(QMessageBox.Ok)hint_msg.exec_()def showDialog(self, ws = '', un = '', pw = '', url = ''):edit_dialog = QDialog(self)group = QGroupBox('Edit Info', edit_dialog)lbl_website = QLabel('Website:', group)le_website = QLineEdit(group)le_website.setText(ws)lbl_username = QLabel('Username:', group)le_username = QLineEdit(group)le_username.setText(un)lbl_password = QLabel('Password:', group)le_password = QLineEdit(group)le_password.setText(pw)lbl_url = QLabel('Url:', group)le_url = QLineEdit(group)le_url.setText(url)ok_button = QPushButton('OK', edit_dialog)cancel_button = QPushButton('CANCEL', edit_dialog)ok_button.clicked.connect(edit_dialog.accept)ok_button.setDefault(True)cancel_button.clicked.connect(edit_dialog.reject)group_layout = QVBoxLayout()group_item = [lbl_website, le_website,lbl_username, le_username,lbl_password, le_password,lbl_url, le_url]for item in group_item:group_layout.addWidget(item)group.setLayout(group_layout)group.setFixedSize(group.sizeHint())button_layout = QHBoxLayout()button_layout.addWidget(ok_button)button_layout.addWidget(cancel_button)dialog_layout = QVBoxLayout()dialog_layout.addWidget(group)dialog_layout.addLayout(button_layout)edit_dialog.setLayout(dialog_layout)edit_dialog.setFixedSize(edit_dialog.sizeHint())if edit_dialog.exec_():website = le_website.text()username = le_username.text()password = le_password.text()url = le_url.text()return True, website, username, password, urlreturn False, None, None, None, Noneclass Login():passif __name__ == '__main__':app = QApplication(sys.argv)pwk = PasswordManagerSystem()pwk.show()app.exec_()pwk.conn.close()sys.exit(0)

PyQT 跟我学做密码管理器(5)相关推荐

  1. PyQT 跟我学做密码管理器(1)

    PyQT 跟我学做密码管理器(1)-- 初始化UI控件 声明:本文借鉴https://blog.csdn.net/bigbennyguo/article/details/50755207 修改而来 前 ...

  2. Firefox 密码管理器 Lockbox 推出 Android 版

    开发四年只会写业务代码,分布式高并发都不会还做程序员?   Mozilla 今日在 Android 上推出了一项新功能"Firefox Lockbox",该功能此前已经出现在桌面( ...

  3. 幕后产品_使用Bitwarden密码管理器在幕后

    幕后产品 我们是人类. 我们每天都被技术和帐户所淹没,大多数人会选择一个容易记住的密码. -乔纳森·勒布朗(Jonathan LeBlanc),前PayPal 必须记住Web应用程序,电子邮件,银行帐 ...

  4. 使用Python编写自己的个人密码管理器

    技术要点: 1)tkinter界面设计: 2)SQLite数据库操作: 3)字符串异或运算加密和解密. 使用方法: 只需要记住一个加解密密钥即可,对于各平台的密码,使用密钥加密后存储到数据库,查询时使 ...

  5. c语言实现一个密码管理器(更新中)

    作为电脑爱好者,会经常注册各种网站的账号,但是考虑到隐私的可能泄露,不喜欢把密码托管给浏览器,于是经常忘记各种密码.饱受折磨后,我决定用学的一点点c语言知识写一个密码管理器. 在写之前我希望它目前可以 ...

  6. 1Password 7.3.2 强大的密码管理器

    如今密码泄露事件层出不穷,为了账户密码不怕被一锅端,较为安全的办法是针对不同网站设置不同密码,但这样虽更安全,却也带来了记忆上的负担. 而即便你只打算用一个密码走天下,但日积月累下来千百个网站和 AP ...

  7. ac管理器管理员密码忘记了_人们为什么不使用密码管理器

    ac管理器管理员密码忘记了 Password managers generate secure, complex and unique passwords automatically for each ...

  8. 使用Docker搭建自己的在线密码管理器软件-Bitwarden

    前言 因为现在网络安全问题愈发严重,黑客经常通过互联网已泄露的用户和密码信息进行撞库攻击,而且很多用户在不同网站使用的是相同的帐号密码,所以为不同的网站设置不同的密码就非常重要. 但密码不同尤其是使用 ...

  9. 8种最好的Linux密码管理器

    推荐8种最好的Linux密码管理器,可以安全地存储你的登录信息. ·Fiagaro's Password Manager ·Gpass ·Gpassword Manager ·Gringotts ·K ...

最新文章

  1. python 2.* 升级到python3.*的过程
  2. mysql命令行执行时不输出列名(字段名)
  3. 160个Crackme040
  4. python对文件的_python 对文件操作
  5. spark学习-33-Spark安全机制SecurityManager
  6. CentOS 搭建简单svn服务器【转】
  7. win7无法访问局域网内电脑_win7系统局域网无法访问原因 win7局域网无法访问解决方法【图文】...
  8. Git之Reset的三种模式
  9. 报错A Database Error Occurred,linux系统被cc***
  10. window安装python3后怎么用pyspark_pyspark:连接spark集群Windows环境搭建
  11. 注册、注销与结束session变量
  12. Atiitt attilax掌握的前后技术放在简历里面.docx
  13. linux文件的上传和下载(终端工具SCRT和XShell)
  14. Linux嵌入式和单片机嵌入式到底什么区别?
  15. Bridging the Gap Between Anchor-based and Anchor-free Detection 阅读
  16. 糖尿病性视网膜病变分级诊断
  17. mac 安装java8
  18. 【Halcon 字符串与HTuple互转,double与HTuple互转,Mat与HObject互转】
  19. “元宇宙”,究竟离我们有多远?(中)
  20. C++实验 | 定义流对象,实现用write函数将学生信息以二进制方式写到磁盘文件stu.dat中

热门文章

  1. 乔哈里资讯窗(转载)
  2. 动态星空科技感粒子登录页 附代码复制即可用
  3. 联想扬天V15锐龙版2023 参数 联想扬天V15锐龙版2023 怎么样
  4. mysql注入到命令执行 | 提权
  5. MYSQL注入(Welcome Dhakkan)
  6. 英语中“万”的奇特表示法
  7. Unity3D 关于模型变形技术代码实现
  8. 鲁大师9月新机流畅榜:OPPO ColorOS 12跑分亮相!
  9. SfM三维点云重建:BA优化--【VS2015+OpenCV3.4+PCL1.8】
  10. C语言程序设计 重点内容(一)