Python 3 email

RobLegge
RobLegge used Ask the Experts™
on
Trying to display just the "From" and "Subject" items from all unread emails. What I've got in the code reads
<code>
          def getmail(server):
               select_info = server.select_folder(MAILBOX)
               messages  = server.search(['UNSEEN'])
               print("getting mail")
               for uid, message_data in server.fetch(messages, 'RFC822').items():
                    print("number of messages %d" % len(messages))
                    email_message = email.message_from_bytes(message_data[b'RFC822'])
                    print(email_message.get('From'), email_message.get('Subject'))
          return messages
</code>

However, what's happening is an error is occurring. Output listing is

getting mail
number of messages 1
"Rob PL" <rob@xxxxxxxxx.com> test
number of messages 1
Exception triggered: b'RFC822'

Just can't find a way of getting rid of the error.

Can anyone help here?
Comment
Watch Question

Do more with

Expert Office
EXPERT OFFICE® is a registered trademark of EXPERTS EXCHANGE®
David FavorFractional CTO
Distinguished Expert 2018

Commented:
Far more information is required.

It appears you're attempting to access an IMAP mail store.

1) Mention the exact IMAP4 library you're using.

2) Also provide one of the messages in question. The entire message, as a text attachment, with all headers included, no redactions.

Note: Your code, as written, will likely fail miserably for mailboxes with many unread (UNSEEN) messages.
David FavorFractional CTO
Distinguished Expert 2018

Commented:
Aside: Your code, as written, will also never consider any messages already read/accessed/seen, so your code is going to produce very flakey results. In other words, you'll have a completely different result if messages have been accessed or not.

For your code to work, you must be sure to never leave a mail client running, like Thunderbird or Outlook, as these clients periodically poll the IMAP server to scan newly arrived messages, pulling the date/from/to/subject, to display.

This polling action changes all message states from UNSEEN to SEEN, the instant polling occurs.

This suggests your code will likely require rethinking if you every use a mail client with the mailbox in question.

Fix: One work around here is to filter your mail, sending all mail matching some specific pattern to another mailbox, which is never accessed by any client. In this case, once you've processed all UNSEEN messages, your code should change each message to SEEN or each message will be reprocessed each time your code runs.

Author

Commented:
Ok, I should have been clear about the purposes of the app. It's not intended to act as an email client, just to show me who has sent me an email and the subject line. It's sitting on a Raspberry Pi Zero running beside me (or will - currently there's an earlier version that doesn't show the message details, just the count, on 3 mail boxes that's been working fine for around 9 months) so I can glance at it when something comes in and decide whether or not to interrupt what I'm doing and respond to it. If it doesn't require a response I really don't care that it doesn't get shown on the next run through the loop. In fact I'm very glad that it doesn't because my display is only 1.44 inches square. My main Outlook client is Outlook pulling the mail down as POP3.

The imported items are
import email
from imapclient import IMAPClient
import time
import sys
import os
import logging

Debug file attached
imapdebug.txt
Introduction to R

R is considered the predominant language for data scientist and statisticians. Learn how to use R for your own data science projects.

nociSoftware Engineer
Distinguished Expert 2018

Commented:
fetch does expect an array.., not a single value.  ( https://imapclient.readthedocs.io/en/2.1.0/api.html )
(and indenting does seem to leave something desired from your code.)
(try to use code in square brackets to tag code like below).:
def getmail(server):
      select_info = server.select_folder(MAILBOX)
      messages  = server.search(['UNSEEN'])
      print("getting mail")
      for uid, message_data in server.fetch(messages, ['RFC822']).items():
           print("number of messages %d" % len(messages))
           email_message = email.message_from_bytes(message_data[b'RFC822'])
           print(email_message.get('From'), email_message.get('Subject'))
      return messages

Open in new window

Commented:
Odd, I found my own solution to this some time ago and submitted it. It appears not to have updated.
nociSoftware Engineer
Distinguished Expert 2018

Commented:
Then please upload that solution again and mark that as the solution...
It can be pasted in a code block in a comment.

Do more with

Expert Office
Submit tech questions to Ask the Experts™ at any time to receive solutions, advice, and new ideas from leading industry professionals.

Start 7-Day Free Trial