Skip to main content

檔案掃描比對加郵件寄送

  BUBU 因為公司要確認每天備份是否正常運行,做了一支小程可以每天針對某個目錄下備份檔做差異比對並且匯成網頁用郵件寄給 BUBU 做查看,那我是用 python 方式去編寫,剛好最近都在上有關於 python 課程來使用。因為是初學者所以沒有寫的很好但可用來參考用。

#!/usr/bin/python3
# -*- coding: UTF-8 -*-

# 要載入的模組
import os  # 系統
import re  # 正規
import fnmatch  # 檔名匹配
from pathlib import Path  # 路徑
import time  # 時間
import difflib  # 比對
import shutil  # 判斷目錄
import smtplib # 郵件 SMTP
import ssl # 憑證用
from email.mime.text import MIMEText # 郵件格式
from email.mime.multipart import MIMEMultipart # 郵件附加檔

# 產生出現當下日期及時間
timestr = time.strftime("%Y%m%d-%H%M")

# 該目錄清單
path1 = 'list'
# 要掃路徑
path2 = '路徑'
# 結出來結果記錄檔
path3 = 'log'

# 當 VMlog 目錄不存在自動建立
if not os.path.isdir(path3):
    os.makedirs(path3)

# 確認 list1 檔案在不在,不存在就會自動建立該檔案(上次的記錄)
destination = Path(path3, "list1.txt")
destination.touch(exist_ok=True)
# 確認 list2 檔案在不在,不存在就會自動建立該檔案(當下的記錄)
destination1 = Path(path3, "list2.txt")
destination1.touch(exist_ok=True)
# 確認 dir-list1 檔案在不在,不存在就會自動建立該檔案(上次的記錄)
destination3 = Path(path3, "dir-list1.txt")
destination3.touch(exist_ok=True)
# 確認 dir-list2 檔案在不在,不存在就會自動建立該檔案(當下的記錄)
destination4 = Path(path3, "dir-list2.txt")
destination4.touch(exist_ok=True)


# 要排除的檔案
includes = set([''])

# 要排除的目錄
exclude = set(['log'])

# 將 glob 模式轉換為正則表達式
includes = r'|'.join([fnmatch.translate(x) for x in includes])

# 讀取清單
txt1 = open(path1, 'r')
# 列表清單
txt2 = txt1.readlines()

# 執行迴圈方式去掃目錄
for d in txt2:
    # 移除字串尾巴的換行符號
    d = d.strip()
    # 路徑加要掃目錄
    path4 = path2 + d
    # 掃路踁回圈 dirPath 行啟始路徑 dirNames 資料夾名稱 fileNames 檔案名稱
    for dirPath, dirNames, fileNames in os.walk(path4):
        # 排除不掃檔案
        fileNames = [fi for fi in fileNames if not re.match(includes, fi)]
        # 排除不掃目錄
        dirNames[:] = [d1 for d1 in dirNames if d1 not in exclude]
        # 掃目錄迴圈
        for fdir in dirNames:
            fdir_path = Path(dirPath, fdir)
            # 寫入到指定記錄檔
            with open(path3 + 'dir-' + timestr + '.txt', 'a') as fdir1:
                fdir1.write(str(fdir_path) + '\n')
        # 掃檔案迴圈
        for ffile in fileNames:
            ffile_path = Path(dirPath, ffile)
            # 寫入到指定記錄檔
            with open(path3 + timestr + '.txt', 'a') as ffile1:
                ffile1.write(str(ffile_path) + '\n')
# 關閉讀取檔案
txt1.close()

# 檔案清單路徑
ffnew = Path(path3 + timestr + '.txt')
# list1.txt路徑
ffnew1 = Path(path3, destination)
# list2.txt路徑
ffnew2 = Path(path3, destination1)

# 目錄清單路徑
ffdir = Path(path3 + 'dir-' + timestr + '.txt')
# dir-list1.txt路徑
ffdir1 = Path(path3, destination3)
# dir-list2.txt路徑
ffdir2 = Path(path3, destination4)

# 將上次的記錄檔名修改為 list1.txt
dest1 = shutil.copyfile(ffnew2, ffnew1)
# 本次的記錄檔修改為 list2.txt
dest = shutil.copyfile(ffnew, ffnew2)

# 將上次的記錄檔名修改為 dir-list1.txt
dest4 = shutil.copyfile(ffdir2, ffdir1)
# 本次的記錄檔修改為 dir-list2.txt
dest3 = shutil.copyfile(ffdir, ffdir2)

# 讀取檔案清單上次記錄
xx1 = open(ffnew1, 'r')
# 讀取檔案清單這次記錄
xx2 = open(ffnew2, 'r')

# 讀取目錄清單上次記錄
xx3 = open(ffdir1, 'r')
# 讀取目錄清單這次記錄
xx4 = open(ffdir2, 'r')

# 比對清檔差異輸出成 html 檔
diff = difflib.HtmlDiff()
ffnew3 = diff.make_file(xx1, xx2)
with open(path3 + 'diff' + timestr + '.html', 'w') as diffnew:
    diffnew.write(ffnew3)

# 比對目錄差異輸出成 html 檔
diff1 = difflib.HtmlDiff()
ffdir3 = diff.make_file(xx3, xx4)
with open(path3 + 'dir-diff' + timestr + '.html', 'w') as diffdir:
    diffdir.write(ffdir3)
    
####  mail smtp 設定 ####

# smtp port 號
port = 587  # For starttls
# smtp mail 伺服器
smtp_server = ""
# 寄件者帳號
sender_email = ""
# 寄件者密碼
password = ''
# 收件者
receiver_email = ""

# 要傳送的文字
message = MIMEMultipart()
message["From"] = sender_email  # 撰寫你的暱稱或是信箱
message["To"] = receiver_email  # 撰寫你要寄的人
message["Subject"] = "每日備份比對結果"  # 撰寫郵件標題
# 撰寫內文內容,以及指定格式為plain,語言為中文
message.attach(MIMEText("比對結果請參考附件", "plain", "utf-8"))

# 建立附件
att1 = MIMEText(open('123.txt', 'rb').read(), 'base64', 'utf-8')
att1["Content-Type"] = 'application/octet-stream'
# 附件名稱
att1["Content-Disposition"] = 'attachment; filename=" {}.html"'.format('utf-8', '中文' + time.strftime("%Y%m%d"))
message.attach(att1)


context = ssl.create_default_context()
try:
    with smtplib.SMTP(smtp_server, port) as server:
        server.ehlo()  # Can be omitted
        server.starttls(context=context)
        server.ehlo()  # Can be omitted
        # 登入郵件伺服器
        server.login(sender_email, password)
        server.sendmail(sender_email, receiver_email, message.as_string())
        print("信件已成功傳送")
except smtplib.SMTPException:
    print("Error: 信件傳送失敗")