0

I am trying to read some info from a bunch of emails quickly without pulling the whole object and set the mail item as read. Especially so, since most of the emails have large attachments I do not want to pull them. For this I try something as follows:

mail_filter = acct.inbox.filter(message_id__in=email_id_list).values_list("subject", "body", "datetime_received", "sender")

mail_filter.page_size = 2
for item in mail_filter.iterator():
    do_something_with_the_tuple_in_item()

# Now I want to set is_read = True. Something like below:
acct.inbox.filter(message_id__in=email_id_list).update(is_read=True)

While with values_list I could avoid getting the whole mail item (which otherwise seems to consume lots of memory especially for emails with attachments), I find there is no update() support on the filter. So in order for me to set an email to be is_read, I meed to pull the object (at the cost of memory) and set is_read = True, then save() back. Basically, it fails the purpose to save memory usage by using values_list. Any other idea exists? Anything I am missing?

Erik Cederstrand
  • 9,643
  • 8
  • 39
  • 63
RajSoundar
  • 341
  • 1
  • 2
  • 8

1 Answers1

1

You can tell exchangelib to only fetch some field values, and to only update the is_read field. Also, if you only want to process unread emails, you can add a filter on the is_read value:

for item in f.filter(is_read=False).only('is_read', 'subject', 'body', ...):
    item.is_read = True
    item.save(update_fields=['is_read'])

To put even less load on the server, you can batch update your items:

update_tuples = []
for item in f.filter(is_read=False).only('is_read', 'subject', 'body', ...):
    item.is_read = True
    # bulk_update() expects a list of (Item, fieldnames) tuples
    items_to_update.append((item, ['is_read']))

account.bulk_update(update_tuples)
Erik Cederstrand
  • 9,643
  • 8
  • 39
  • 63