自動發郵件做成視覺化可以連線資料庫取資料可設定定時傳送等

珊瑚恋鱼發表於2024-03-27

因工作需要做一個自動傳送郵件的功能,要求是週末定時傳送。
原因是這樣,公司的行政辦公人員週末和節假日不上班,但總有一些人加班,而公司是採用報餐的形式去報中午的餐數量,
平時都是行政人員發資料給中央廚房,而週末節日行政人員不上班,廚房又沒有配置電腦這些,而且廚房不一定在公司附近,
可能距離比較遠。所以有了這樣的需求,總結就是:
1:週末,節日自動定時傳送郵件給中央廚房。郵件內容含當天的用餐早報人數
2:廚房沒有辦法連線到公司的網路,也沒有配備電腦。
那我們開始設計思路:
做一個自動傳送郵件,郵件正文含當天的報餐人數給廚房就行了。那麼我們要解決的有以下兩點
一:從公司的報餐資料庫中取出當日的報餐數量,彙總後以正文的形式發一封郵件給廚房
二:定時傳送給指定郵箱的人。
考慮到以上可能資料庫會變,郵件接收人會更換等。應該做成可配置靈活的,而不是寫死。
基於保密,資料庫連線密碼,郵件授權碼這些就做成加密的形式儲存。
先看一下UI佈局的整體效果。

我用的是PySimpleGUI這個庫。
先匯入要用到的庫,如果沒有的自己去:pip install XXXXXX
一:程式中用到的庫如下:
import time as t
import PySimpleGUI as sg
import smtplib
import os
import pyodbc
import _thread
from configparser import ConfigParser
from datetime import datetime,time
import GetDinData
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
import base64
from Crypto.Cipher import AES
二:
介面UI佈局及主題
sg.theme('GreenMono') # 設定當前主題

佈局設定

layout = [
#收件資訊控制元件佈置
[sg.Text('收件人: ',font=('微軟雅黑', 12)), sg.InputText('', key='_To',size=(70, 1), font=('微軟雅黑', 12))],
[sg.Text('抄送:\t',font=('微軟雅黑', 12)), sg.InputText('', key='_To_copy',size=(70, 1), font=('微軟雅黑', 12))],
[sg.Text('主題:\t',font=('微軟雅黑', 12)), sg.InputText('理研-報/用餐資料彙總及明細表', key='_Subject',size=(70, 1), font=('微軟雅黑', 12))],
[sg.Text('附件:\t',font=('微軟雅黑', 12)),
sg.FileBrowse('新增附件', file_types=(('Text Files', '.'),), size=(10, 1), font=('微軟雅黑', 11),key='_OpenFile'),
sg.Button('刪除附件', font=('微軟雅黑', 12),key='_Delete')
],
#正文
[sg.Frame(layout=[
[sg.Multiline(default_text='您好:'+'\n'+' 這是您申請傳送的(報/用餐資料彙總)情況,請您檢視! 注:此郵件為自動傳送郵件!' + '\n',
size=(63, 10),font=('微軟雅黑', 14), text_color='Blue', key='_Content',auto_size_text=True)],
],
title='郵件正文', title_color='red', relief=sg.RELIEF_SUNKEN, tooltip='郵件正文')
],
# 伺服器及發件人控制元件佈置
[sg.Frame(layout=[
[sg.Text('伺服器: ', font=('微軟雅黑', 12), text_color='red'),
sg.InputText('smtp.qq.com', key='_Server', size=(25, 1), font=('微軟雅黑', 12)),
sg.Text('埠號: ', font=('微軟雅黑', 12), text_color='red'),
sg.InputText('465', key='_Port', size=(5, 1), font=('微軟雅黑', 12)),
sg.Text('授權碼: ',font=('微軟雅黑', 12), text_color='red'),
sg.InputText('',key='_AutoCode', size=(18, 1), font=('微軟雅黑', 12)), ],
[sg.Text('發件人: ', font=('微軟雅黑', 12), text_color='red'),
sg.InputText('', key='_From', size=(69, 1), font=('微軟雅黑', 12))],

        [sg.Text('定時1 :   ', font=('微軟雅黑', 12),text_color='blue'),sg.InputText('10:00', key='_AutoTime1',size=(9, 1)),
         sg.Text('定時2 :   ', font=('微軟雅黑', 12),text_color='blue'),sg.InputText('15:00', key='_AutoTime2',size=(9, 1)),
         sg.Button('郵件伺服器連線測試', font=('微軟雅黑', 12),button_color='blue', key='_ConnectEmail'),
         sg.Button('顯示配置資訊', font=('微軟雅黑', 12),key='_ShowAutoCode'),
         sg.Button('儲存配置', font=('微軟雅黑', 12),key='_SaveConfigEmail')],
         ],
         title='(1): 郵件伺服器及發件人配置', title_color='red', relief=sg.RELIEF_SUNKEN, tooltip='郵件伺服器及發件人設定')
     ],
    # 伺服器資料庫控制元件佈置
    [sg.Frame(layout=[
        [sg.Text('伺服器地址:', font=('微軟雅黑', 12), text_color='red'),
         sg.InputText('', key='_ServerName', size=(30, 1), font=('微軟雅黑', 12), tooltip='服務名或IP地址'),
         sg.Text('資料庫名稱:', font=('微軟雅黑', 12), text_color='red'),
         sg.InputText('', key='_Database', size=(25, 1), font=('微軟雅黑', 12), tooltip='資料庫名稱')],
        [sg.Text('登入使用者名稱:', font=('微軟雅黑', 12), text_color='red'),
         sg.InputText('sa', key='_LogId', size=(30, 1), font=('微軟雅黑', 12), tooltip='正常是sa'),
         sg.Text('使用者名稱密碼:', font=('微軟雅黑', 12), text_color='red'),
         sg.InputText('',key='_LogPassword', size=(25, 1), font=('微軟雅黑', 12), tooltip='sa對應的密碼')],

        [sg.Text('操作按鈕 >>>>>>>>>>>>>>>', text_color='blue', font=('微軟雅黑', 12)),
         sg.Button('資料庫連線測試', font=('微軟雅黑', 12), button_color='blue', key='_ConnectDB'),
         sg.Button('顯示配置資訊', font=('微軟雅黑', 12), key='_ShowConfig'),
         sg.Button('儲存配置', font=('微軟雅黑', 12), key='_SaveConfigDB'),
         sg.Button('測試獲取資料', font=('微軟雅黑', 12), key='_Get'),
         ],
    ],
        title='(2): 伺服器資料庫配置', title_color='red', relief=sg.RELIEF_SUNKEN, tooltip='伺服器資料庫設定')
    ],
     [sg.Text('說明: (1) 多個收件人地址用分號";"隔開 (2) 定時週末及節假日才會傳送',text_color='red',font=('微軟雅黑', 12)),
      sg.Button('傳送郵件', font=('微軟雅黑', 12),key='_Send'),
      sg.Button('開啟自動傳送', font=('微軟雅黑', 12),key='_AutoSend')],
     [sg.Text('執行狀態:  還未開啟自動傳送郵件',text_color='yellow', font=('微軟雅黑', 12),key='_State')],
     # [sg.StatusBar('執行狀態:  還未開啟自動傳送郵件',text_color='yellow', font=('微軟雅黑', 12),key='_State')]
     ]

建立視窗

window = sg.Window('定時自動傳送郵件小程式,Author:Running Ver:1.0 ; 程式執行時間: ' + t.strftime('%Y-%m-%d %H:%M:%S'), layout,font=('微軟雅黑', 12), default_element_size=(50, 1))
三:配置檔案及相關

配置檔案

app_path = 'setting.ini'
log_path = 'log.txt'
key = 'lsqily82lsqily82' #自己金鑰一定要16位元組不然會報錯

控制是否點了“顯示授權碼”預設為True

AutoFlag = False
四:AES加密及解密
def AES_Encrypt(key, data):

金鑰(key), 密斯偏移量(iv) CBC模式加密

vi = '0102030405060708'
pad = lambda s: s + (16 - len(s) % 16) * chr(16 - len(s) % 16)
data = pad(data)

字串補位

cipher = AES.new(key.encode('utf8'), AES.MODE_CBC, vi.encode('utf8'))
encryptedbytes = cipher.encrypt(data.encode('utf8'))

加密後得到的是bytes型別的資料

encodestrs = base64.b64encode(encryptedbytes)

使用Base64進行編碼,返回byte字串

enctext = encodestrs.decode('utf8')

對byte字串按utf-8進行解碼

return enctext
def AES_Decrypt(key, data):
vi = '0102030405060708'
data = data.encode('utf8')
encodebytes = base64.decodebytes(data)

將加密資料轉換位bytes型別資料

cipher = AES.new(key.encode('utf8'), AES.MODE_CBC, vi.encode('utf8'))
text_decrypted = cipher.decrypt(encodebytes)
unpad = lambda s: s[0:-s[-1]]
text_decrypted = unpad(text_decrypted)

去補位

text_decrypted = text_decrypted.decode('utf8')
return text_decrypted

五:郵件伺服器配置相關函式-

----------------郵件伺服器配置相關函式--------------------

定義全域性變數

Server=''
def ini():
"初始化建立自動發郵件配置檔案"
# 建立一個ConfigParser物件
config = ConfigParser()
if not os.path.exists(app_path):
sg.popup('沒有'+app_path+'配置檔案,請先在當前介面配置郵件伺服器並儲存配置檔案', title='提示', )
return 'N'
else:
return 'Y'
def Data_Effect():
"資料有效性驗證"
info='OK'
#獲取UI介面上的各項值
ToMail = values['_To'] # 收件人暱稱和地址
Subject = values['_Subject'] # 郵件主題
Smtp = values['_Server']
Port = values['_Port']
AutoCode = values['_AutoCode']
SendAddress = values['_From']
AutoTime1 = values['_AutoTime1']
AutoTime2 = values['_AutoTime2']
Server = values['_ServerName']
DataBase = values['_Database']
LogId = values['_LogId']
LogPassword = values['_LogPassword']
#判斷是否為空
if len(ToMail)0:
info="收件人郵件地址不能為空"
sg.popup('收件人郵件地址不能為空', title='提示', )
elif len(Subject)
0:
sg.popup('郵件主題不能為空', title='提示', )
elif len(Smtp)0:
sg.popup('郵件伺服器不能為空', title='提示', )
elif len(Port)
0:
sg.popup('埠號不能為空', title='提示', )
elif len(AutoCode)0:
sg.popup('授權碼不能為空', title='提示', )
elif len(AutoTime1)
0:
sg.popup('定時1不能為空', title='提示', )
elif len(AutoTime2)0:
sg.popup('定時2不能為空', title='提示', )
elif len(Server)
0:
sg.popup('伺服器地址不能為空', title='提示', )
elif len(DataBase)0:
sg.popup('資料庫名稱不能為空', title='提示', )
elif len(LogId)
0:
sg.popup('登入使用者名稱不能為空', title='提示', )
elif len(LogPassword)0:
sg.popup('使用者名稱密碼不能為空', title='提示', )
window['_State'].update('當前狀態: '+ info)
return info
def show_ini():
#顯示配置檔案前,先判斷是否有生成配置檔案
if ini()
'N':
return
# 建立一個ConfigParser物件
config = ConfigParser()
try:
# 從 INI檔案中讀取配置資訊
config.read(app_path, encoding="utf-8")
# 獲取指定節點下的鍵值對
Smtp = config['SMTP']['Smtp']
Port = config['SMTP']['Port']
AutoCode = config['SMTP']['AutoCode']
# 顯示出解密的明文 ,授權碼jyfgyfmienircage
SendAddress = config['SMTP']['SendAddress']
AutoTime1 = config['SMTP']['AutoTime1']
AutoTime2 = config['SMTP']['AutoTime2']
#顯示在UI介面
window['_Server'].update(Smtp)
window['_Port'].update(Port)
window['_AutoCode'].update(AutoCode)
window['_From'].update(SendAddress)
window['_AutoTime1'].update(AutoTime1)
window['_AutoTime2'].update(AutoTime2)
window['_State'].update('當前狀態: 郵件伺服器配置檔案顯示成功!')
except:
window['_State'].update('當前狀態: 郵件伺服器配置檔案顯示失敗,請確認是否有配置檔案!')
sg.popup('配置檔案顯示失敗,請確認是否有配置檔案', title='提示', )
def Save_ServerEmail():
"新增郵件伺服器的節和配置的項的值"
# 建立一個ConfigParser物件
config = ConfigParser()
config.add_section('SMTP')
config.set('SMTP', 'Smtp', values['_Server']) # 郵件伺服器地址smtp及
config.set('SMTP', 'Port', values['_Port']) # 埠號port
config.set('SMTP', 'SendAddress', values['_From']) # 發件人郵箱地址
config.set('SMTP', 'AutoTime1', values['_AutoTime1']) #定時1
config.set('SMTP', 'AutoTime2', values['_AutoTime2']) #定時1
#儲存前先判斷是不是新建的配置檔案,如果是新建的加密,否則取出配置解密後判斷是不是和當前顯示的一樣
if not os.path.exists(app_path):
config.set('SMTP', 'AutoCode', AES_Encrypt(key, values['_AutoCode'])) # 發件人授權碼加密後再儲存
# 新增資料庫的節和配置項的值供儲存使用
config.add_section('database')
config.set('database', 'ServerName', values['_ServerName'])
config.set('database', 'Database', values['_Database'])
config.set('database', 'LogId', values['_LogId'])
config.set('database', 'LogPassword', AES_Encrypt(key, values['_LogPassword']))
# config.set('database', 'LogPassword', values['_LogPassword'])
else:
config.read(app_path, encoding="utf-8") #讀取ini配置檔案
AES_AutoCode = config['SMTP']['AutoCode']
if AES_AutoCode != values['_AutoCode']:
config.set('SMTP', 'AutoCode', AES_Encrypt(key, values['_AutoCode'])) # 發件人授權碼加密後再儲存
else:
config.set('SMTP', 'AutoCode', values['_AutoCode']) # 發件人授權碼

   AES_LogPassword = config['database']['LogPassword']
   if AES_LogPassword != values['_LogPassword']:
      config.set('database', 'LogPassword', AES_Encrypt(key, values['_LogPassword']))  # 使用者名稱密碼加密後再儲存
   else:
      config.set('database', 'LogPassword', values['_LogPassword'])  # 使用者名稱密碼

# 寫入配置檔案
with open(app_path, 'w', encoding="utf-8") as configfile:
    config.write(configfile)
print('郵件伺服器配置檔案儲存成功')
window['_State'].update('當前狀態: 郵件伺服器配置檔案儲存成功!')
sg.popup('郵件伺服器配置儲存成功', title='提示', )

def Connect_email_server():
"連線郵件伺服器前先顯示配置資訊(不知道為什麼要等此函式連線成功才會顯示,先顯示在介面再取值取不到?)"
#顯示在UI介面
show_ini()
global Server
if Server!='':
window['_State'].update('當前狀態: 郵件伺服器已經連線中,無需重複測試!')
# Server.quit()
return Server
# 建立一個ConfigParser物件
config = ConfigParser()
# 從 INI檔案中讀取配置資訊
config.read(app_path, encoding="utf-8")
#授權碼要解密一下再去連線,不直接明文顯示在介面上
AutoCode = AES_Decrypt(key,config['SMTP']['AutoCode'])
#print(AutoCode)
try:
# 連線伺服器
Server = smtplib.SMTP_SSL(config['SMTP']['Smtp'], config['SMTP']['Port'])
# 登入郵箱
loginResult = Server.login(config['SMTP']['SendAddress'], AutoCode)
# print(loginResult)
if loginResult[0]==235:
print('恭喜,郵件伺服器連線成功')
window['_State'].update('當前狀態: 郵件伺服器連線成功')
return(Server)
else:
print('郵件伺服器連線失敗,請確認配置是否正確後重試')
window['_State'].update('當前狀態: 郵件伺服器連線失敗,請確認配置是否正確後重試')
return
except:
window['_State'].update('當前狀態: 郵件伺服器連線失敗,請確認配置是否正確後重試')
sg.popup('郵件伺服器連線失敗,請確認配置是否正確後重試', title='提示', )
Server.quit()
return
def Send_file_email(content_data):
"此函式為,執行傳送郵件的函式,可帶附件"
#先進行資料有效性驗證
info = Data_Effect()
if info != 'OK':
return
try:
# 收發相關資訊
SendAddress = values['_From'] # 發件人暱稱和地址
ToMail = values['_To'] # 收件人暱稱和地址
ToCopy = values['_To_copy'] # 抄送人暱稱和地址
Subject = values['_Subject'] # 郵件主題
print(ToMail)
# 定義一個可以新增正文和附件的郵件訊息物件
msg = MIMEMultipart()
# 收件人相關資訊
msg['From'] = SendAddress
msg['To'] = ToMail
msg['Cc'] = ToCopy
msg['Subject'] = Subject
# 郵件正文,從指令碼GetDinData.getdata()中獲取
content = content_data
# 先透過MIMEText將正文規範化,構造成郵件的一部分,再新增到郵件訊息物件中
msg.attach(MIMEText(content, 'plain', 'utf-8'))
# 附件(新增多個附件同理),暫時關閉,有需要再開啟
# 以二進位制形式將檔案的資料讀出,再使用MIMEText進行規範化
# attachment = MIMEText(open(f'image/logo.gif', 'rb').read(), 'base64', 'utf-8')
# # 告知瀏覽器或郵件伺服器這是位元組流,瀏覽器處理位元組流的預設方式為下載
# attachment['Content-Type'] = 'application/octet-stream'
# # 此部分主要是告知瀏覽器或郵件伺服器這是一個附件,名字叫做xxxxx,這個檔名不要用中文,不同郵箱對中文的對待形式不同
# attachment['Content-Disposition'] = 'attachment;filename="logo.gif"'
#
# msg.attach(attachment)
# 呼叫函式後返回的伺服器物件
Server = Connect_email_server()
# 向伺服器提交郵件傳送 ,ToMail 收件人
Server.sendmail(SendAddress, [ToMail], msg.as_string())
print('郵件傳送成功')
return 'Success'
except:
return 'Faile'
# sg.popup('郵件傳送成功', title='提示', )
#傳送成功後關閉Server
Server.close()
def Auto_Send(window,AutoFlag):
"資料有效性驗證"
info = Data_Effect()
if info !='OK':
return
if AutoFlag:
# 定時1
Auto_H1 = int(values['_AutoTime1'][:2])
Auto_M1 = int(values['_AutoTime1'][-2:])
target_time1 = time(Auto_H1, Auto_M1,10)
# 定時2
Auto_H2 = int(values['_AutoTime2'][:2])
Auto_M2 = int(values['_AutoTime2'][-2:])
target_time2 = time(Auto_H2, Auto_M2, 10)

    # 無限迴圈,每次檢查當前時間是否達到設定時間
    while True:
        now = t.localtime()
        now = t.strftime("%H:%M:%S",now)
        print('等待執行中'+str(now))
        if now == str(target_time1) or now == str(target_time2):
            # # 如果當前時間達到或超過設定時間,執行以下操作
            print("1:預設時間到,開始執行操作")
            # 你的程式碼放這裡,連線資料庫取值
            data = GetDinData.GetData()
            # print(data)
            window['_Content'].Update(data)
            #判斷是不是週末或節日
            if GetDinData.Getworktype() == "週末" or GetDinData.Getworktype() == "節日":
               #自動執行傳送郵件結果,返回Success表示成功
               if Send_file_email(data) == 'Success':
                  log_txt ='系統時間:' + datetime.now().strftime("%Y-%m-%d %H:%M:%S") + ' 執行自動發郵件成功!'
               else:
                  log_txt ='系統時間:' + datetime.now().strftime("%Y-%m-%d %H:%M:%S") + ' 執行自動發郵件失敗!'
               #執行函式寫入日誌檔案:log.txt
               Write_Log(log_txt)
         # break
        #等待1秒
        t.sleep(1)
        window['_State'].update('當前狀態: 自動傳送郵件執行中....')
else:
    window['_State'].update('當前狀態: 系統己就緒等待執行指令')
    # print('關閉自動傳送郵件')

def Write_Log(log_text):
# 寫入日誌,檢查檔案是否存在不存在先建立log.txt
if not os.path.exists(log_path):
# 檔案不存在,則建立檔案
with open(log_path, 'w') as file:
# 將字串寫入檔案
file.write(log_text)
file.close()
else:
with open(log_path, 'w') as file:
file.write(log_text)
file.close()
六:# -----------伺服器資料庫配置相關函式----------------------
def Show_Config():
# 建立一個ConfigParser物件
config = ConfigParser()
if not os.path.exists(app_path):
sg.popup('沒有'+app_path+'配置檔案,請先在當前介面配置郵件伺服器並儲存配置檔案', title='提示', )
return 'N'
else:
# 從 INI 檔案中讀取配置資訊
config.read(app_path, encoding="utf-8")
# 獲取指定節點下的鍵值對
Server = config['database']['ServerName']
DataBase = config['database']['Database']
LogId = config['database']['LogId']
LogPassword = config['database']['LogPassword']
#把配置資訊顯示在介面上
window['_ServerName'].update(Server)
window['_Database'].update(DataBase)
window['_LogId'].update(LogId)
window['_LogPassword'].update(LogPassword)
window['_State'].update('當前狀態: 伺服器資料庫配置檔案顯示成功!')
return 'Y'
def Save_ServerDB():
Save_ServerEmail()
# 建立一個ConfigParser物件
# config = ConfigParser()
# if ini()'N':
# return
# else:
# # 設定鍵值對
# config.add_section('database')
# config.set('database', 'ServerName', values['_ServerName'])
# config.set('database', 'Database', values['_Database'])
# config.set('database', 'LogId', values['_LogId'])
# config.set('database', 'LogPassword', values['_LogPassword'])
# # 寫入配置檔案
# with open(app_path, 'w',encoding="utf-8") as configfile:
# config.write(configfile)
# window['_State'].update('當前狀態: 伺服器資料庫配置檔案儲存成功!')
# sg.popup('伺服器資料庫配置檔案儲存成功!', title='提示', )
def connect_db():
"連線前先顯示出配置資訊在介面方便核對"
if Show_Config()
'N':
return
# 建立一個ConfigParser物件
config = ConfigParser()
# 從 INI 檔案中讀取配置資訊
config.read(app_path,encoding="utf-8")
# 獲取指定節點下的鍵值對
Server = config['database']['ServerName']
DataBase = config['database']['Database']
LogId = config['database']['LogId']
LogPassword = config['database']['LogPassword']
LogPassword = AES_Decrypt(key,LogPassword) #顯示出解密後的密碼
print(LogPassword)
try:
conn = pyodbc.connect('DRIVER={SQL Server};SERVER=' + Server + ';DATABASE=' + DataBase + ';UID=' + LogId + ';PWD=' + LogPassword )
print('當前狀態: 伺服器資料庫連線成功!')
window['_State'].update('當前狀態: 伺服器資料庫連線成功!')
return conn
except Exception as e:
print('當前狀態: 資料庫連線失敗,請檢查資料庫配置檔案!'+str(e))
sg.popup('資料庫連線失敗,請檢查資料庫配置檔案!', title='提示', )
return 'conn_faild'
七:

事件迴圈並獲取輸入值

while True:
event, values = window.read()
# 開啟時自動點選顯示伺服器郵件配置資訊
if event in (None, '_Close'): # 如果使用者關閉視窗或點選Close
break
elif event'_SaveConfigEmail':
Save_ServerEmail() #儲存郵件伺服器配置
elif event == '_ConnectEmail':
Connect_email_server() #連線郵件伺服器
elif event
'_ShowAutoCode':
show_ini() #顯示配置檔案
elif event'_Send':
Send_file_email('你好,這是一封測試郵件不用理會!')
elif event
'_AutoSend': #開啟、關閉自動傳送
if not AutoFlag:
window.find_element('_AutoSend').update('關閉自動傳送')
window.find_element('_State').update('執行狀態: 開啟自動傳送郵件中......')
AutoFlag = True
#利用多執行緒,防止程式卡死無響應狀態
_thread.start_new_thread(Auto_Send, (window,AutoFlag))
# Auto_Send(window,AutoFlag)
else:
window.find_element('_AutoSend').update('開啟自動傳送')
window.find_element('_State').update('執行狀態: 還未開啟自動傳送郵件')
thread_id = _thread.get_ident()
t.sleep(2)
AutoFlag = False
Auto_Send(window,AutoFlag)
#-------------伺服器配置的事件放在下面---------------
elif event'_ShowConfig':
Show_Config()
elif event
'_SaveConfigDB':
Save_ServerDB() #儲存伺服器資料庫配置
elif event == '_ConnectDB':
connect_db() # 連線伺服器資料庫
elif event == '_Get':
data = GetDinData.GetData()
print(data)
window['_Content'].Update(data)

關閉郵件伺服器連線和視窗

window.close()

這樣配置好了,點開始自動傳送郵件如下圖:測試時間到自動傳送了:

郵箱中看到的郵件:

我用的是QQ郵箱,授權碼要自己去申請一下。

相關文章