BIM World
A Professional BIM Learning Platform


Automating Scheduled Email Sending with Python

While most mainstream email services support sending emails on a scheduled basis, I decided to write a Python script to automate scheduled email sending myself. By setting a specific send time, you can follow the steps below to send files via QQ Mail.

The script performs the following actions:

  • The file’s last modified and access times are randomly adjusted to between 20 and 25 minutes before the scheduled sending time.
  • If the file exceeds 10MB or is a folder, it is automatically compressed into a zip file.
  • The file is then sent via email automatically.

Here are some important points to note:

  • Modifying a file’s timestamp requires the SetFileTime function from the Windows API, so the pywin32 module must be installed first.
  • Since the email is sent through SMTP, you must enable the SMTP service on your email account beforehand.
  • Sending emails via SMTP requires both the email address and an authorization code, which can be obtained from your email settings.

Below is the Python code implementing this functionality:

from win32file import CreateFile, SetFileTime, GetFileTime, CloseHandle
from win32file import GENERIC_READ, GENERIC_WRITE, OPEN_EXISTING
from pywintypes import Time
from threading import Timer
from email.header import Header
from email.mime.text import MIMEText
from email.mime.application import MIMEApplication
from email.mime.multipart import MIMEMultipart
import time, os, random, zipfile, smtplib

def ModifyFileTime(filePath, lastTime):
    # Construct file handle with read/write access
    fh = CreateFile(filePath, GENERIC_READ | GENERIC_WRITE, 0, None, OPEN_EXISTING, 0, 0)
    offsetSec = random.randint(1200, 1500)  # Random offset between 20-25 minutes
    cTime, aTime, wTime = GetFileTime(fh)
    aTime = Time(time.mktime(lastTime) - offsetSec)
    wTime = Time(time.mktime(lastTime) - offsetSec)
    # Modify the file's access and write times
    SetFileTime(fh, cTime, aTime, wTime)
    CloseHandle(fh)

def GetFilePathList(filePath, result):
    if os.path.isdir(filePath):
        files = os.listdir(filePath)
        for file in files:
            fullPath = os.path.join(filePath, file)
            if os.path.isdir(fullPath):
                GetFilePathList(fullPath, result)
            else:
                result.append(fullPath)
    else:
        result.append(filePath)

def RunZipFile(filePath):
    # Construct zip file name
    zipFilePath = os.path.basename(filePath)
    if os.path.isdir(filePath):
        zipFilePath += '.zip'
    else:
        zipFilePath = os.path.splitext(zipFilePath)[0] + '.zip'
    # Delete existing zip file if it exists
    if os.path.exists(zipFilePath):
        os.remove(zipFilePath)
    # Create zip archive
    zipFileList = []
    GetFilePathList(filePath, zipFileList)
    with zipfile.ZipFile(zipFilePath, 'w', zipfile.ZIP_DEFLATED) as f:
        for fileP in zipFileList:
            arcName = os.path.basename(fileP)
            if os.path.isdir(filePath):
                dirName = os.path.dirname(fileP)
                arcName = dirName.replace(os.path.dirname(dirName), '') + '/' + arcName
            f.write(fileP, arcName)
    return zipFilePath

def SendEmail(filePath):
    # Email configuration
    fromAddr = 'XXXXXXXXX@qq.com'  # Sender's email address
    autho = 'XXXXXXXXXXXXXXXX'     # Authorization code
    smtpServer = 'smtp.qq.com'     # SMTP server address

    # Email details
    toAddr = 'XXXXXXXX@163.com'    # Recipient's email address
    title = 'YourTitle'            # Email subject
    text = 'YourText'              # Email body text
    annexPath = filePath           # Attachment path

    # Compose email
    message = MIMEMultipart()
    message['From'] = fromAddr
    message['To'] = toAddr
    message['Subject'] = Header(title, 'utf-8')
    message.attach(MIMEText(text, 'plain', 'utf-8'))

    # Attach file
    with open(annexPath, 'rb') as f:
        annex = MIMEApplication(f.read())
    annex.add_header('Content-Disposition', 'attachment', filename=os.path.basename(annexPath))
    message.attach(annex)

    # Send email via SMTP SSL
    server = smtplib.SMTP_SSL(smtpServer, 465)
    server.login(fromAddr, autho)
    server.sendmail(fromAddr, [toAddr], message.as_string())
    server.quit()

def PreparingFilesAndSend(filePath, runTime):
    annexPath = filePath
    if os.path.isdir(filePath):
        # Modify timestamps for all files in directory
        modFileList = []
        GetFilePathList(filePath, modFileList)
        for fileP in modFileList:
            ModifyFileTime(fileP, runTime)
        # Compress directory into zip file
        annexPath = RunZipFile(filePath)
    else:
        # Modify timestamp for single file
        ModifyFileTime(filePath, runTime)
        # Compress if file size exceeds 10MB
        if os.path.getsize(filePath) / float(1024 * 1024) > 10:
            annexPath = RunZipFile(filePath)
    # Send the prepared file via email
    SendEmail(annexPath)

def TimedTask(filePath, runTime):
    interval = time.mktime(runTime) - time.mktime(time.localtime())
    Timer(interval, PreparingFilesAndSend, args=(filePath, runTime)).start()

fp = r"C:/Users/imfour/Documents/pythonTest/testtxt.txt"
rt = "2019-6-17 02:08:00"
# Convert string time to structured time
timeFormat = "%Y-%m-%d %H:%M:%S"
s_time = time.strptime(rt, timeFormat)

if __name__ == "__main__":
    TimedTask(fp, s_time)
xuebim
Follow the latest BIM developments in the architecture industry, explore innovative building technologies, and discover cutting-edge industry insights.
← Scan with WeChat
Like(0) 打赏
BIM WORLD » Automating Scheduled Email Sending with Python

Comment Get first!

Must log in before commenting!

 

BIM World, A Professional BIM Learning Platform

Stay updated on the latest architecture trends and share new building technologies.

Contact UsAbout Us

觉得文章有用就打赏一下小编吧

非常感谢你的打赏,我们将继续提供更多优质内容,让我们一起创建更加美好的网络世界!

支付宝扫一扫

微信扫一扫

Account Login

By signing in, you agree toUser Agreement

Sign Up