Python 壓縮資料夾併傳送郵件功能
1. 功能概述
本筆記介紹如何使用 Python 進行以下操作:
- 將指定資料夾中的檔案壓縮為
.zip
檔案,不包含子資料夾及其內容。 - 將壓縮後的檔案透過電子郵件傳送給指定收件人,使用 QQ 郵箱作為傳送郵件的 SMTP 伺服器。
2. 將資料夾壓縮為 ZIP 檔案(不含子資料夾)
程式碼:
import os
import zipfile
def zip_folder(folder_path: str, output_path: str) -> None:
"""
將指定資料夾中的檔案壓縮為 zip 檔案,不包含子資料夾及其內容
:param folder_path: 要壓縮的資料夾路徑 (str)
:param output_path: 壓縮檔案儲存路徑 (str)
:return: None
"""
# 使用 'w' 模式開啟 zip 檔案,表示建立一個新的 zip 檔案並寫入內容
with zipfile.ZipFile(output_path, 'w', zipfile.ZIP_DEFLATED) as zipf:
# 遍歷指定資料夾中的所有檔案,不包括子資料夾
for file in os.listdir(folder_path):
file_path = os.path.join(folder_path, file)
# 僅處理檔案(忽略子資料夾)
if os.path.isfile(file_path):
# 將檔案新增到 zip 檔案中
zipf.write(file_path, arcname=file) # arcname=file 使壓縮包內檔案保持原檔名
# 輸出壓縮成功資訊
print(f"資料夾中的檔案已壓縮為:{output_path}")
程式碼解釋:
os.listdir(folder_path)
:列出資料夾中的所有檔案和子資料夾。os.path.isfile(file_path)
:檢查檔案路徑是否為檔案,忽略子資料夾。zipfile.ZipFile
:建立並寫入 zip 檔案,arcname=file
確保壓縮包中的檔案沒有包含資料夾路徑。
3. 透過郵件傳送壓縮檔案
程式碼:
import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.mime.base import MIMEBase
from email import encoders
class FolderZipperAndEmailSender:
def __init__(self, smtp_server: str, smtp_port: int, sender_email: str, sender_password: str):
"""
初始化郵件傳送器
:param smtp_server: SMTP 伺服器地址
:param smtp_port: SMTP 埠號
:param sender_email: 傳送方郵箱
:param sender_password: 授權碼(非郵箱密碼)
"""
self.smtp_server = smtp_server
self.smtp_port = smtp_port
self.sender_email = sender_email
self.sender_password = sender_password
def send_email(self, recipient_email: str, subject: str, body: str, attachment_path: str) -> None:
"""
傳送帶附件的郵件
:param recipient_email: 接收方郵箱
:param subject: 郵件主題
:param body: 郵件正文
:param attachment_path: 附件路徑
:return: None
"""
# 建立郵件物件
msg = MIMEMultipart()
msg['From'] = self.sender_email
msg['To'] = recipient_email
msg['Subject'] = subject
# 新增郵件正文
msg.attach(MIMEText(body, 'plain'))
# 新增附件
with open(attachment_path, 'rb') as attachment:
part = MIMEBase('application', 'octet-stream')
part.set_payload(attachment.read())
encoders.encode_base64(part)
part.add_header(
'Content-Disposition',
f'attachment; filename={os.path.basename(attachment_path)}'
)
msg.attach(part)
# 傳送郵件 (好像用with郵件傳送成功但會報錯)
with smtplib.SMTP_SSL(self.smtp_server, self.smtp_port) as server: # 使用 SSL
server.login(self.sender_email, self.sender_password)
server.send_message(msg)
print("郵件已傳送")
程式碼解釋:
- 郵件傳送類
FolderZipperAndEmailSender
:該類負責傳送郵件。需要提供 SMTP 配置、傳送者郵箱和授權碼。 send_email
方法:負責構建併傳送郵件,支援正文和附件。使用MIMEText
和MIMEBase
構建郵件內容。- SMTP 配置:
- 使用 QQ 郵箱的 SMTP 伺服器 (
smtp.qq.com
)。 - 使用 SSL 連線(埠 465)確保安全通訊。
- 登入時使用授權碼而不是郵箱密碼。
- 使用 QQ 郵箱的 SMTP 伺服器 (
4. 整合成完整的工作流程
整合程式碼:
import os
import zipfile
import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.mime.base import MIMEBase
from email import encoders
class FolderZipperAndEmailSender:
def __init__(self, smtp_server: str, smtp_port: int, sender_email: str, sender_password: str):
"""
初始化郵件傳送器
:param smtp_server: SMTP 伺服器地址
:param smtp_port: SMTP 埠號
:param sender_email: 傳送方郵箱
:param sender_password: 授權碼(非郵箱密碼)
"""
self.smtp_server = smtp_server
self.smtp_port = smtp_port
self.sender_email = sender_email
self.sender_password = sender_password
def zip_folder(self, folder_path: str, output_path: str) -> None:
"""
將指定資料夾中的檔案壓縮為 zip 檔案,不包含子資料夾及其內容
:param folder_path: 要壓縮的資料夾路徑 (str)
:param output_path: 壓縮檔案儲存路徑 (str)
:return: None
"""
with zipfile.ZipFile(output_path, 'w', zipfile.ZIP_DEFLATED) as zipf:
for file in os.listdir(folder_path):
file_path = os.path.join(folder_path, file)
if os.path.isfile(file_path):
zipf.write(file_path, arcname=file)
print(f"資料夾中的檔案已壓縮為:{output_path}")
def send_email(self, recipient_email: str, subject: str, body: str, attachment_path: str) -> None:
"""
傳送帶附件的郵件
:param recipient_email: 接收方郵箱
:param subject: 郵件主題
:param body: 郵件正文
:param attachment_path: 附件路徑
:return: None
"""
msg = MIMEMultipart()
msg['From'] = self.sender_email
msg['To'] = recipient_email
msg['Subject'] = subject
msg.attach(MIMEText(body, 'plain'))
with open(attachment_path, 'rb') as attachment:
part = MIMEBase('application', 'octet-stream')
part.set_payload(attachment.read())
encoders.encode_base64(part)
part.add_header('Content-Disposition', f'attachment; filename={os.path.basename(attachment_path)}')
msg.attach(part)
with smtplib.SMTP_SSL(self.smtp_server, self.smtp_port) as server:
server.login(self.sender_email, self.sender_password)
server.send_message(msg)
print("郵件已傳送")
# 使用示例
if __name__ == "__main__":
sender = FolderZipperAndEmailSender(
smtp_server="smtp.qq.com",
smtp_port=465,
sender_email="your_email@qq.com",
sender_password="your_authorization_code"
)
folder_to_zip = "./example_folder"
zip_file_path = "./example_folder.zip"
# 壓縮資料夾
sender.zip_folder(folder_to_zip, zip_file_path)
recipient_email = "recipient_email@example.com"
subject = "壓縮檔案傳送示例"
body = "請查收附件中的壓縮檔案。"
# 傳送郵件
sender.send_email(recipient_email, subject, body, zip_file_path)
5. 總結
透過以上的程式碼,我們實現了以下功能:
- 壓縮資料夾:只壓縮指定資料夾中的檔案,不包括子資料夾。
- 傳送郵件:透過 QQ 郵箱傳送帶附件的郵件。使用授權碼代替密碼,並使用 SSL 連線保證安全性。
這個工作流程可以幫助我們方便地將資料夾中的內容壓縮並透過郵件傳送,適用於批次檔案傳輸和自動化任務。