PyQt5 郵件客戶端
下面是一個簡潔高效的郵件客戶端實現,支持編寫郵件、添加附件和發送郵件功能:
編寫 eMailClient_qt.py 如下
# -*- coding: utf-8 -*-
""" 用 PyQt5 開發一個郵件客戶端,能編寫郵件,發送郵件及附件 """
import os
import sys
import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.base import MIMEBase
from email import encoders
from PyQt5.QtWidgets import (QApplication, QMainWindow, QWidget, QVBoxLayout, QHBoxLayout, QFileDialog,QLineEdit, QTextEdit, QPushButton, QLabel,QListWidget, QMessageBox, QStatusBar, QGridLayout)
from PyQt5.QtGui import QFont, QPalette, QColor
from PyQt5.QtCore import Qt, QSizeclass EmailClient(QMainWindow):def __init__(self):super().__init__()self.setWindowTitle("郵件客戶端")# 設置窗口大小為1000x600self.setGeometry(100, 100, 1000, 600)# 設置現代化UI樣式self.setStyleSheet("""QMainWindow {background-color: #f0f2f5;}QLabel {color: #333;font-size: 12px;font-weight: bold;padding: 2px 0;}QLineEdit, QTextEdit {background-color: white;border: 1px solid #dcdfe6;border-radius: 4px;padding: 8px;font-size: 13px;}QLineEdit:focus, QTextEdit:focus {border: 1px solid #4a90e2;}QPushButton {background-color: #4a90e2;color: white;border: none;border-radius: 4px;padding: 8px 15px;font-size: 13px;min-height: 30px;}QPushButton:hover {background-color: #3a7bc8;}QPushButton:pressed {background-color: #2a65a8;}QPushButton#attachButton {background-color: #f5f7fa;color: #4a90e2;border: 1px solid #4a90e2;}QPushButton#sendButton {background-color: #27ae60;padding: 10px 25px;font-size: 14px;font-weight: bold;}QPushButton#sendButton:hover {background-color: #219653;}QListWidget {background-color: white;border: 1px solid #dcdfe6;border-radius: 4px;padding: 5px;font-size: 12px;alternate-background-color: #f8f9fa;}QStatusBar {background-color: #e0e6ed;color: #666;font-size: 11px;padding: 5px;}QFrame#headerFrame {background-color: #4a90e2;border-radius: 5px;padding: 10px;}""")# 創建中央部件central_widget = QWidget()self.setCentralWidget(central_widget)# 主布局 - 使用網格布局更靈活main_layout = QGridLayout(central_widget)main_layout.setSpacing(15)main_layout.setContentsMargins(15, 15, 15, 15)# 標題區域title_label = QLabel("郵件客戶端")title_label.setFont(QFont("Arial", 18, QFont.Bold))title_label.setStyleSheet("color: #2c3e50;")main_layout.addWidget(title_label, 0, 0, 1, 3, alignment=Qt.AlignLeft)# 發件人信息main_layout.addWidget(QLabel("發件人:"), 1, 0, alignment=Qt.AlignRight)self.sender_email = QLineEdit()self.sender_email.setPlaceholderText("your_email@qq.com")main_layout.addWidget(self.sender_email, 1, 1, 1, 2)main_layout.addWidget(QLabel("密碼:"), 1, 3, alignment=Qt.AlignRight)self.password = QLineEdit()self.password.setEchoMode(QLineEdit.Password)self.password.setPlaceholderText("郵箱密碼或應用密碼")main_layout.addWidget(self.password, 1, 4)# 收件人 - 標簽和輸入框在同一行main_layout.addWidget(QLabel("收件人:"), 2, 0, alignment=Qt.AlignRight)self.recipient_email = QLineEdit()self.recipient_email.setPlaceholderText("recipient@qq.com")main_layout.addWidget(self.recipient_email, 2, 1, 1, 4)# 主題 - 標簽和輸入框在同一行main_layout.addWidget(QLabel("主題:"), 3, 0, alignment=Qt.AlignRight)self.subject = QLineEdit()self.subject.setPlaceholderText("郵件主題")main_layout.addWidget(self.subject, 3, 1, 1, 4)# 附件main_layout.addWidget(QLabel("附件:"), 4, 0, alignment=Qt.AlignRight | Qt.AlignTop)# 附件列表和按鈕attachment_widget = QWidget()attachment_layout = QVBoxLayout(attachment_widget)self.attachment_list = QListWidget()self.attachment_list.setMinimumHeight(80)attachment_layout.addWidget(self.attachment_list)# 按鈕布局btn_layout = QHBoxLayout()attach_button = QPushButton("添加附件")attach_button.setObjectName("attachButton")attach_button.clicked.connect(self.add_attachment)btn_layout.addWidget(attach_button)remove_button = QPushButton("移除附件")remove_button.setObjectName("attachButton")remove_button.clicked.connect(self.remove_attachment)btn_layout.addWidget(remove_button)attachment_layout.addLayout(btn_layout)main_layout.addWidget(attachment_widget, 4, 1, 1, 4)# 郵件正文 - 擴大區域main_layout.addWidget(QLabel("正文:"), 5, 0, alignment=Qt.AlignRight | Qt.AlignTop)self.body = QTextEdit()self.body.setPlaceholderText("在此輸入郵件內容...")# 設置正文區域的行數(相對擴大)main_layout.addWidget(self.body, 5, 1, 1, 4)# 發送按鈕send_button = QPushButton("發送郵件")send_button.setObjectName("sendButton")send_button.clicked.connect(self.send_email)main_layout.addWidget(send_button, 6, 4, alignment=Qt.AlignRight)# 設置行和列的比例,使正文區域擴大main_layout.setRowStretch(5, 3) # 正文區域行權重設為3main_layout.setColumnStretch(1, 1)main_layout.setColumnStretch(2, 1)main_layout.setColumnStretch(3, 1)main_layout.setColumnStretch(4, 2) # 右側列權重更大# 狀態欄self.status_bar = QStatusBar()self.setStatusBar(self.status_bar)self.status_bar.showMessage(f"就緒 - 窗口大小: {self.width()}x{self.height()}")# 存儲附件路徑self.attachments = []# 設置示例數據self.sender_email.setText("your_email@qq.com")self.recipient_email.setText("recipient@qq.com")self.subject.setText("PyQt5 郵件客戶端測試")self.body.setPlainText("這是一封測試郵件,使用 PyQt5 郵件客戶端發送。\n\n""此郵件支持添加多個附件,并采用現代化的界面設計。\n\n""功能包括:\n""? 郵件編寫\n""? 附件添加/移除\n""? 郵件發送\n""? 狀態反饋\n\n""祝您使用愉快!")def add_attachment(self):files, _ = QFileDialog.getOpenFileNames(self, "選擇附件", "", "所有文件 (*.*)")if files:self.attachments.extend(files)self.attachment_list.addItems(files)self.status_bar.showMessage(f"已添加 {len(files)} 個附件")def remove_attachment(self):current_row = self.attachment_list.currentRow()if current_row >= 0:item = self.attachment_list.takeItem(current_row)del self.attachments[current_row]self.status_bar.showMessage(f"已移除附件: {item.text()}")else:self.status_bar.showMessage("請選擇要移除的附件")def send_email(self):sender = self.sender_email.text()password = self.password.text()recipient = self.recipient_email.text()subject = self.subject.text()body = self.body.toPlainText() # 使用純文本格式if not sender or not password or not recipient:QMessageBox.warning(self, "輸入錯誤", "請填寫完整的發件人、密碼和收件人信息")returntry:# 創建郵件對象msg = MIMEMultipart()msg['From'] = sendermsg['To'] = recipientmsg['Subject'] = subject# 添加郵件正文msg.attach(MIMEText(body, 'plain'))# 添加附件for file_path in self.attachments:try:with open(file_path, "rb") as attachment:part = MIMEBase("application", "octet-stream")part.set_payload(attachment.read())encoders.encode_base64(part)# 獲取文件名filename = file_path.split('/')[-1] if '/' in file_path else file_pathfilename = filename.split('\\')[-1] # 處理Windows路徑part.add_header("Content-Disposition",f"attachment; filename={filename}",)msg.attach(part)except Exception as e:self.status_bar.showMessage(f"添加附件失敗: {str(e)}")return# 連接SMTP服務器并發送郵件self.status_bar.showMessage("正在連接服務器...")server = smtplib.SMTP_SSL('smtp.gmail.com', 465) # 使用Gmail SMTP服務器self.status_bar.showMessage("正在登錄...")server.login(sender, password)self.status_bar.showMessage("正在發送郵件...")server.sendmail(sender, recipient, msg.as_string())server.quit()# 發送成功后的操作self.status_bar.showMessage("郵件發送成功!")QMessageBox.information(self, "發送成功", "郵件已成功發送!")# 清空附件列表self.attachment_list.clear()self.attachments = []except smtplib.SMTPAuthenticationError:QMessageBox.critical(self, "認證失敗", "郵箱或密碼錯誤,請檢查您的登錄信息")self.status_bar.showMessage("認證失敗")except Exception as e:QMessageBox.critical(self, "發送失敗", f"郵件發送失敗: {str(e)}")self.status_bar.showMessage(f"發送失敗: {str(e)}")def resizeEvent(self, event):"""窗口大小改變時更新狀態欄信息"""self.status_bar.showMessage(f"就緒 - 窗口大小: {self.width()}x{self.height()}")super().resizeEvent(event)if __name__ == "__main__":app = QApplication(sys.argv)# 設置應用樣式palette = QPalette()palette.setColor(QPalette.Window, QColor(240, 242, 245))palette.setColor(QPalette.WindowText, QColor(51, 51, 51))palette.setColor(QPalette.Base, QColor(255, 255, 255))palette.setColor(QPalette.AlternateBase, QColor(248, 249, 250))palette.setColor(QPalette.Button, QColor(74, 144, 226))palette.setColor(QPalette.ButtonText, QColor(255, 255, 255))palette.setColor(QPalette.Highlight, QColor(74, 144, 226))palette.setColor(QPalette.HighlightedText, QColor(255, 255, 255))app.setPalette(palette)client = EmailClient()client.show()sys.exit(app.exec_())
功能說明
這個郵件客戶端實現了以下核心功能:
-
郵件編寫:
- 發件人郵箱和密碼輸入
- 收件人地址輸入
- 郵件主題輸入
- 郵件正文編輯區域
-
附件管理:
- 添加多個附件
- 查看附件列表
- 移除選中的附件
-
郵件發送:
- 使用SMTP協議發送郵件
- 支持純文本格式的郵件內容
- 支持發送多個附件
- 錯誤處理和狀態反饋
使用說明
- 在"發件人"字段輸入您的郵箱地址
- 在"密碼"字段輸入您的郵箱密碼(或應用專用密碼)
- 在"收件人"字段輸入收件人郵箱地址
- 填寫郵件主題和正文內容
- 點擊"添加附件"按鈕選擇要發送的文件
- 點擊"發送郵件"按鈕發送郵件
注意事項
-
該程序默認使用Gmail的SMTP服務器(smtp.gmail.com:465),如果您使用其他郵箱服務:
- QQ郵箱:smtp.qq.com:465
- 163郵箱:smtp.163.com:465
- Outlook:smtp.office365.com:587(需要使用TLS)
-
部分郵箱服務需要開啟SMTP服務并獲取授權碼:
- Gmail:需要在賬戶設置中開啟"安全性較低的應用的訪問權限"
- QQ/163:需要在郵箱設置中開啟SMTP服務并獲取授權碼
-
出于安全考慮,程序不會保存您的密碼,每次發送郵件都需要輸入
這個程序提供了一個簡潔高效的郵件發送解決方案,代碼結構清晰,去除了不必要的裝飾元素,專注于核心功能的實現。
PyQt5 郵件客戶端 - 優化布局
下面是一個優化布局的郵件客戶端實現,窗口大小調整為1000x600,提供更舒適的編輯體驗:
編寫 eMailClient_qt5.py 如下
import sys
import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.base import MIMEBase
from email import encoders
from PyQt5.QtWidgets import (QApplication, QMainWindow, QWidget, QVBoxLayout, QHBoxLayout,QLineEdit, QTextEdit, QPushButton, QLabel, QFileDialog,QListWidget, QMessageBox, QStatusBar, QSplitter, QFrame)
from PyQt5.QtGui import QFont, QPalette, QColor
from PyQt5.QtCore import Qtclass EmailClient(QMainWindow):def __init__(self):super().__init__()self.setWindowTitle("郵件客戶端")# 設置窗口大小為1000x600self.setGeometry(100, 100, 1000, 600)# 設置現代化UI樣式self.setStyleSheet("""QMainWindow {background-color: #f0f2f5;}QLabel {color: #333;font-size: 12px;font-weight: bold;padding: 2px 0;}QLineEdit, QTextEdit {background-color: white;border: 1px solid #dcdfe6;border-radius: 4px;padding: 8px;font-size: 13px;}QLineEdit:focus, QTextEdit:focus {border: 1px solid #4a90e2;}QPushButton {background-color: #4a90e2;color: white;border: none;border-radius: 4px;padding: 8px 15px;font-size: 13px;min-height: 30px;}QPushButton:hover {background-color: #3a7bc8;}QPushButton:pressed {background-color: #2a65a8;}QPushButton#attachButton {background-color: #f5f7fa;color: #4a90e2;border: 1px solid #4a90e2;}QPushButton#sendButton {background-color: #27ae60;padding: 10px 25px;font-size: 14px;font-weight: bold;}QPushButton#sendButton:hover {background-color: #219653;}QListWidget {background-color: white;border: 1px solid #dcdfe6;border-radius: 4px;padding: 5px;font-size: 12px;alternate-background-color: #f8f9fa;}QStatusBar {background-color: #e0e6ed;color: #666;font-size: 11px;padding: 5px;}QFrame#headerFrame {background-color: #4a90e2;border-radius: 5px;padding: 10px;}""")# 創建中央部件central_widget = QWidget()self.setCentralWidget(central_widget)# 主布局main_layout = QVBoxLayout(central_widget)main_layout.setSpacing(15)main_layout.setContentsMargins(15, 15, 15, 15)# 標題區域header_frame = QFrame()header_frame.setObjectName("headerFrame")header_layout = QHBoxLayout(header_frame)header_layout.setContentsMargins(10, 5, 10, 5)title_label = QLabel("郵件客戶端")title_label.setFont(QFont("Arial", 18, QFont.Bold))title_label.setStyleSheet("color: white;")header_layout.addWidget(title_label)header_layout.addStretch()main_layout.addWidget(header_frame)# 創建分割器,左側為設置區域,右側為編輯區域splitter = QSplitter(Qt.Horizontal)main_layout.addWidget(splitter, 1)# 左側設置面板settings_panel = QWidget()settings_layout = QVBoxLayout(settings_panel)settings_layout.setContentsMargins(0, 0, 10, 0)# 發件人信息sender_group = QWidget()sender_layout = QVBoxLayout(sender_group)sender_layout.addWidget(QLabel("發件人設置"))sender_form = QHBoxLayout()sender_form.addWidget(QLabel("郵箱:"))self.sender_email = QLineEdit()self.sender_email.setPlaceholderText("your_email@example.com")sender_form.addWidget(self.sender_email)sender_layout.addLayout(sender_form)sender_form2 = QHBoxLayout()sender_form2.addWidget(QLabel("密碼:"))self.password = QLineEdit()self.password.setEchoMode(QLineEdit.Password)self.password.setPlaceholderText("郵箱密碼或應用密碼")sender_form2.addWidget(self.password)sender_layout.addLayout(sender_form2)settings_layout.addWidget(sender_group)# 收件人recipient_group = QWidget()recipient_layout = QVBoxLayout(recipient_group)recipient_layout.addWidget(QLabel("收件人"))self.recipient_email = QLineEdit()self.recipient_email.setPlaceholderText("recipient@example.com")recipient_layout.addWidget(self.recipient_email)settings_layout.addWidget(recipient_group)# 主題subject_group = QWidget()subject_layout = QVBoxLayout(subject_group)subject_layout.addWidget(QLabel("主題"))self.subject = QLineEdit()self.subject.setPlaceholderText("郵件主題")subject_layout.addWidget(self.subject)settings_layout.addWidget(subject_group)# 附件attachment_group = QWidget()attachment_layout = QVBoxLayout(attachment_group)attachment_layout.addWidget(QLabel("附件"))# 附件列表self.attachment_list = QListWidget()self.attachment_list.setMinimumHeight(100)attachment_layout.addWidget(self.attachment_list)# 附件按鈕btn_layout = QHBoxLayout()attach_button = QPushButton("添加附件")attach_button.setObjectName("attachButton")attach_button.clicked.connect(self.add_attachment)btn_layout.addWidget(attach_button)remove_button = QPushButton("移除附件")remove_button.setObjectName("attachButton")remove_button.clicked.connect(self.remove_attachment)btn_layout.addWidget(remove_button)attachment_layout.addLayout(btn_layout)settings_layout.addWidget(attachment_group)settings_layout.addStretch()# 右側編輯區域editor_panel = QWidget()editor_layout = QVBoxLayout(editor_panel)editor_layout.setContentsMargins(0, 0, 0, 0)# 郵件正文editor_layout.addWidget(QLabel("郵件正文"))self.body = QTextEdit()self.body.setPlaceholderText("在此輸入郵件內容...")editor_layout.addWidget(self.body, 1)# 發送按鈕send_button = QPushButton("發送郵件")send_button.setObjectName("sendButton")send_button.clicked.connect(self.send_email)editor_layout.addWidget(send_button, 0, Qt.AlignRight)# 添加左右面板到分割器splitter.addWidget(settings_panel)splitter.addWidget(editor_panel)splitter.setSizes([300, 700])# 狀態欄self.status_bar = QStatusBar()self.setStatusBar(self.status_bar)self.status_bar.showMessage("就緒 - 窗口大小: 1000x600")# 存儲附件路徑self.attachments = []# 設置示例數據self.sender_email.setText("your_email@example.com")self.recipient_email.setText("recipient@example.com")self.subject.setText("PyQt5 郵件客戶端測試")self.body.setPlainText("這是一封測試郵件,使用 PyQt5 郵件客戶端發送。\n\n""此郵件支持添加多個附件,并采用現代化的界面設計。\n\n""功能包括:\n""? 郵件編寫\n""? 附件添加/移除\n""? 郵件發送\n""? 狀態反饋\n\n""祝您使用愉快!")def add_attachment(self):files, _ = QFileDialog.getOpenFileNames(self, "選擇附件", "", "所有文件 (*.*)")if files:self.attachments.extend(files)self.attachment_list.addItems(files)self.status_bar.showMessage(f"已添加 {len(files)} 個附件")def remove_attachment(self):current_row = self.attachment_list.currentRow()if current_row >= 0:item = self.attachment_list.takeItem(current_row)del self.attachments[current_row]self.status_bar.showMessage(f"已移除附件: {item.text()}")else:self.status_bar.showMessage("請選擇要移除的附件")def send_email(self):sender = self.sender_email.text()password = self.password.text()recipient = self.recipient_email.text()subject = self.subject.text()body = self.body.toPlainText() # 使用純文本格式if not sender or not password or not recipient:QMessageBox.warning(self, "輸入錯誤", "請填寫完整的發件人、密碼和收件人信息")returntry:# 創建郵件對象msg = MIMEMultipart()msg['From'] = sendermsg['To'] = recipientmsg['Subject'] = subject# 添加郵件正文msg.attach(MIMEText(body, 'plain'))# 添加附件for file_path in self.attachments:try:with open(file_path, "rb") as attachment:part = MIMEBase("application", "octet-stream")part.set_payload(attachment.read())encoders.encode_base64(part)# 獲取文件名filename = file_path.split('/')[-1] if '/' in file_path else file_pathfilename = filename.split('\\')[-1] # 處理Windows路徑part.add_header("Content-Disposition",f"attachment; filename={filename}",)msg.attach(part)except Exception as e:self.status_bar.showMessage(f"添加附件失敗: {str(e)}")return# 連接SMTP服務器并發送郵件self.status_bar.showMessage("正在連接服務器...")server = smtplib.SMTP_SSL('smtp.gmail.com', 465) # 使用Gmail SMTP服務器self.status_bar.showMessage("正在登錄...")server.login(sender, password)self.status_bar.showMessage("正在發送郵件...")server.sendmail(sender, recipient, msg.as_string())server.quit()# 發送成功后的操作self.status_bar.showMessage("郵件發送成功!")QMessageBox.information(self, "發送成功", "郵件已成功發送!")# 清空附件列表self.attachment_list.clear()self.attachments = []except smtplib.SMTPAuthenticationError:QMessageBox.critical(self, "認證失敗", "郵箱或密碼錯誤,請檢查您的登錄信息")self.status_bar.showMessage("認證失敗")except Exception as e:QMessageBox.critical(self, "發送失敗", f"郵件發送失敗: {str(e)}")self.status_bar.showMessage(f"發送失敗: {str(e)}")if __name__ == "__main__":app = QApplication(sys.argv)# 設置應用樣式palette = QPalette()palette.setColor(QPalette.Window, QColor(240, 242, 245))palette.setColor(QPalette.WindowText, QColor(51, 51, 51))palette.setColor(QPalette.Base, QColor(255, 255, 255))palette.setColor(QPalette.AlternateBase, QColor(248, 249, 250))palette.setColor(QPalette.Button, QColor(74, 144, 226))palette.setColor(QPalette.ButtonText, QColor(255, 255, 255))palette.setColor(QPalette.Highlight, QColor(74, 144, 226))palette.setColor(QPalette.HighlightedText, QColor(255, 255, 255))app.setPalette(palette)client = EmailClient()client.show()sys.exit(app.exec_())
功能說明
這個郵件客戶端具有以下特點:
-
現代化UI設計:
- 藍色主題與現代化界面元素
- 分割布局(左側設置區,右側編輯區)
- 響應式設計,適應1000x600窗口尺寸
-
郵件功能:
- 完整的郵件編寫功能
- 多附件支持(添加/移除)
- SMTP郵件發送
-
用戶體驗優化:
- 狀態提示(連接、登錄、發送狀態)
- 詳細的錯誤反饋
- 清晰的視覺層次結構
-
布局優化:
- 左側設置面板:發件人信息、收件人、主題、附件管理
- 右側編輯面板:郵件正文編輯區域
- 底部狀態欄:顯示操作狀態和反饋
使用說明
-
左側設置面板:
- 輸入發件人郵箱和密碼
- 輸入收件人郵箱地址
- 填寫郵件主題
- 管理附件(添加/移除)
-
右側編輯面板:
- 在正文區域編寫郵件內容
- 點擊"發送郵件"按鈕發送
-
狀態反饋:
- 狀態欄顯示當前操作狀態
- 發送成功/失敗會有彈窗提示
技術特點
-
窗口尺寸:
- 主窗口設置為1000x600像素,提供寬敞的編輯空間
- 使用QSplitter實現可調整大小的面板
-
郵件發送:
- 支持Gmail SMTP服務器(可修改為其他服務商)
- 支持純文本郵件內容
- 支持多個附件發送
-
錯誤處理:
- 詳細的錯誤捕獲和反饋
- 認證失敗、發送失敗等情況的專門處理
這個郵件客戶端在保持功能完整性的同時,提供了更加現代化和專業的用戶界面,充分利用了1000x600的窗口空間,為用戶帶來更舒適的郵件編輯體驗。