Search code examples
pythonpython-asynciopywin32python-datetime

Python Async Function not updating timestamp


I have a machine running some scripts that I need to keep an eye on.

I have set up a script in python to send me emails using every hour.

I would like to add timestamp to it so that I can see at a glance when was the last message send from the machine to know it's running. When testing this to send email after every 120 seconds, I found that the email sending part works perfectly but the timestamp does not update. Can't figure out what I am doing wrong.

The print statement returns the same timestamp after each loop and so does the email.

Email Sent at 18 December 2024 13:16:50
Email Sent at 18 December 2024 13:16:50
Email Sent at 18 December 2024 13:16:50

My code:

import asyncio

#Main Event loop to send emails
async def send_email(timestamp):

    import datetime as dt
    timestamp = dt.datetime.now()

    import socket
    hostname = socket.gethostname()

    import getpass
    user = getpass.getuser()

    timestamp_string = timestamp.strftime("%d %B %Y %H:%M:%S")
    subject = f"Machine Status Check - {timestamp_string}"

    html_body =     f"""
                        Machine Name: {hostname}\n
                        User ID: {user}
                    """
    to = "[email protected]"
   
    while True:

        import win32com.client
        outlook = win32com.client.gencache.EnsureDispatch('Outlook.Application')

        new_email = outlook.CreateItem(0)
        new_email.To = to
        new_email.Subject = subject
        new_email.HTMLBody = html_body

        new_email.Send()

        print(f"Email Sent at {timestamp_string}")
        await asyncio.sleep(120)

#Run the asyncio event loop
async def main():

    await send_email()

#Start the event loop
asyncio.run(main=main())

Solution

  • You are not updating your values in your while loop so it keeps reusing the same value.

    Quick explanation.

    • you make a variable timestamp and init it with the date now which is 2024-12-18 05:55:11 or whatever

    this variable is now made with the value 2024-12-18 05:55:11. When sending out the mail it will not rerun the datetime.now() function but it will just look at the value saved in the initialization of that object which is 2024-12-18 05:55:11. So in the loop you need to keep updating the values otherwise it will keep using the values stored at the memory address.

    Hope this helps!

    async def send_email():
        hostname = socket.gethostname()
        user = getpass.getuser()
        to = "[email protected]"
    
        while True:
            timestamp = dt.datetime.now()
            timestamp_string = timestamp.strftime("%d %B %Y %H:%M:%S")
            subject = f"Machine Status Check - {timestamp_string}"
    
            html_body = f"""
                Machine Name: {hostname}<br>
                User ID: {user}
            """
    
            outlook = win32com.client.gencache.EnsureDispatch('Outlook.Application')
            new_email = outlook.CreateItem(0)
            new_email.To = to
            new_email.Subject = subject
            new_email.HTMLBody = html_body
            new_email.Send()
    
            print(f"Email Sent at {timestamp_string}")
            await asyncio.sleep(120)