How to check all emails that came in within a time

2020-03-05 03:29发布

I have the following method get_email() that basically every 20 seconds, gets the latest email and performs a series of other methods on it.

def get_email():
    import win32com.client
    import os
    import time
    import datetime as dt

    date_time = time.strftime('%m-%d-%Y')

    outlook = win32com.client.Dispatch("Outlook.Application").GetNameSpace("MAPI")
    inbox = outlook.GetDefaultFolder(6)

    messages = inbox.Items
    message = messages.GetFirst()  # any time calling GetFirst(), you can get GetNext()....
    email_subject = message.subject
    email_sender = message.SenderEmailAddress
    attachments = message.Attachments
    body_content = message.body

    print ('From: ' + email_sender)
    print ('Subject: ' + email_subject)

    if attachments.Count > 0:
        print (str(attachments.Count) + ' attachments found.')
        for i in range(attachments.Count):
                email_attachment = attachments.Item(i+1)
                report_name = date_time + '_' + email_attachment.FileName
                print('Pushing attachment - ' + report_name + ' - to check_correct_email() function.')

                if check_correct_email(email_attachment, email_subject, report_name) == True:
                    save_incoming_report(email_attachment, report_name, get_report_directory(email_subject))
                else:
                    print('Not the attachment we are looking for.')
                    # add error logging here
                    break

    else: #***********add error logging here**************
        print('No attachment found.')

My main question is:

  • Is there a way I can iterate over every email using the GetNext() function per se every hour instead of getting the latest one every 20 seconds (which is definitely not as efficient as searching through all emails)?

Given that there are two functions: GetFirst() and GetNext() how would I properly have it save the latest checked, and then go through all the ones that have yet to be checked?


Do you think it would be easier to potentially set up a different folder in Outlook where I can push all of these reports to, and then iterate through them on a time basis? The only problem here is, if an incoming report is auto-generated and the time interval between the email is less than 20 seconds, or even 1 second.


Any help at all is appreciated!

4条回答
冷血范
2楼-- · 2020-03-05 03:45

I had a similar question and worked through the above solution. Including another general use example in case other folks find it easier:

import win32com.client
import os
import datetime as dt

outlook = win32com.client.Dispatch("Outlook.Application").GetNamespace("MAPI")

# setup range for outlook to search emails (so we don't go through the entire inbox)
lastWeekDateTime = dt.datetime.now() - dt.timedelta(days = 7)
lastWeekDateTime = lastWeekDateTime.strftime('%m/%d/%Y %H:%M %p')  #<-- This format compatible with "Restrict"

# Select main Inbox
inbox = outlook.GetDefaultFolder(6)
messages = inbox.Items

# Only search emails in the last week:
messages = messages.Restrict("[ReceivedTime] >= '" + lastWeekDateTime +"'")

print(message.subject)
# Rest of code...
查看更多
Juvenile、少年°
3楼-- · 2020-03-05 03:58

Using import datetime, this is what I came up with:

count = 0    
msg = messages[len(messages) - count - 1]
while msg.SentOn.strftime("%d-%m-%y") == datetime.datetime.today().strftime("%d-%m-%y"):
        msg = messages[len(messages) - count - 1]
        count += 1
        # Rest of the code
查看更多
家丑人穷心不美
4楼-- · 2020-03-05 04:09

You can use the Restrict function to restrict your messages variable to emails sent within the past hour, and iterate over each of those. Restrict takes the full list of items from your inbox and gives you a list of the ones that meet specific criteria, such as having been received in a specified time range. (The MSDN documentation linked above lists some other potential properties you could Restrict by.)

If you run this every hour, you can Restrict your inbox to the messages you received in the past hour (which, presumably, are the ones that still need to be searched) and iterate over those.

Here's an example of restricting to emails received in the past hour (or minute):

import win32com.client
import os
import time
import datetime as dt

# this is set to the current time
date_time = dt.datetime.now()
# this is set to one hour ago
lastHourDateTime = dt.datetime.now() - dt.timedelta(hours = 1)
#This is set to one minute ago; you can change timedelta's argument to whatever you want it to be
lastMinuteDateTime = dt.datetime.now() - dt.timedelta(minutes = 1)

outlook = win32com.client.Dispatch("Outlook.Application").GetNameSpace("MAPI")
inbox = outlook.GetDefaultFolder(6)

# retrieve all emails in the inbox, then sort them from most recently received to oldest (False will give you the reverse). Not strictly necessary, but good to know if order matters for your search
messages = inbox.Items
messages.Sort("[ReceivedTime]", True)

# restrict to messages from the past hour based on ReceivedTime using the dates defined above.
# lastHourMessages will contain only emails with a ReceivedTime later than an hour ago
# The way the datetime is formatted DOES matter; You can't add seconds here.
lastHourMessages = messages.Restrict("[ReceivedTime] >= '" +lastHourDateTime.strftime('%m/%d/%Y %H:%M %p')+"'")

lastMinuteMessages = messages.Restrict("[ReceivedTime] >= '" +lastMinuteDateTime.strftime('%m/%d/%Y %H:%M %p')+"'")

print "Current time: "+date_time.strftime('%m/%d/%Y %H:%M %p')
print "Messages from the past hour:"

for message in lastHourMessages:
    print message.subject
    print message.ReceivedTime

print "Messages from the past minute:"

for message in lastMinuteMessages:
    print message.subject
    print message.ReceivedTime

# GetFirst/GetNext will also work, since the restricted message list is just a shortened version of your full inbox.
print "Using GetFirst/GetNext"
message = lastHourMessages.GetFirst()
while message:
    print message.subject
    print message.ReceivedTime
    message = lastHourMessages.GetNext()

You seem to have it running every 20 seconds, so presumably you could run it at a different interval. If you can't run it reliably at a regular interval (which would then be specified in the timedelta, e.g. hours=1), you could save the ReceivedTime of the most recent email checked, and use it to Restrict your search. (In that case, the saved ReceivedTime would replace lastHourDateTime, and the Restrict would retrieve every email sent after the last one checked.)

I hope this helps!

查看更多
我欲成王,谁敢阻挡
5楼-- · 2020-03-05 04:12

The below solution gives past 30 minutes unread folder mails from outlook and the count of the mails within the past 30 minutes

import win32com.client
import os
import time
import datetime as dt
# this is set to the current time
date_time = dt.datetime.now()

#This is set to one minute ago; you can change timedelta's argument to whatever you want it to be
last30MinuteDateTime = dt.datetime.now() - dt.timedelta(minutes = 30 )

outlook = win32com.client.Dispatch("Outlook.Application").GetNameSpace("MAPI")
inbox = outlook.GetDefaultFolder(6)

# retrieve all emails in the inbox, then sort them from most recently received to oldest (False will give you the reverse). Not strictly necessary, but good to know if order matters for your search
messages = inbox.Items.Restrict("[Unread]=true")
messages.Sort("[ReceivedTime]", True)




last30MinuteMessages = messages.Restrict("[ReceivedTime] >= '" +last30MinuteDateTime.strftime('%m/%d/%Y %H:%M %p')+"'")

print "Current time: "+date_time.strftime('%m/%d/%Y %H:%M %p')

print "Messages from the past 30 minute:"
c=0
for message in last30MinuteMessages:
    print message.subject
    print message.ReceivedTime
    c=c+1;

print "The count of meesgaes unread from past 30 minutes ==",c
查看更多
登录 后发表回答