I'm trying to manipulate IMAP flags on a single message to mark it unread, after fetching all the "UNREAD" messages and then iterating through them and fetching them.
I'm not entirely sure how to mark the messages unread/unseen on a single-message basis. All I get is the message number, and I'm not sure how to store the UID properly to only affect the single message.
The answer in a similar question didn't appear to work, as it sets the wrong messages as 'unread'. How do I go about setting a single mail message that I've fetched as 'unread' again?
I was asked to give more information. While stripping out the specifics that are 'secret' here, this is the existing runtime that I've tried to implement, such that it attempts to process the message according to code rules, and stores the message numbers, etc., and attempts to set each message to "UNREAD" after storing the id and subject of the message in a pickle file, as anything that's been 'seen' during a run will be marked as 'read' on the server automatically, and not set to 'unread' status:
def main():
conn = imaplib.IMAP4('SERVER')
conn.login('username', 'passphrase')
conn.select('inbox')
(status, nums) = conn.search(None, '(UNSEEN)')
msgnums = map(int, nums[0].split())
for i in msgnums:
try:
raw_msg = conn.fetch(i, '(RFC822)')
raw_msg = conn.fetch(i, '(RFC822)')
msg = email.message_from_string(raw_msg[1][0][1])
body = "Date: %s\r\nSender: %s\r\nSubject: %s\r\n\r\n" % (msg['Date'], msg['From'], msg['Subject'])
msg_date = re.sub('/', '-', msg['Date']).replace(":", ".")
fdate = re.sub('\s+', '_', msg_date).replace(",", "")
print "Checking message: %s" % msg['Subject']
if not msg['Subject']:
continue # fname = "unknown_msg%d_%s" % (i,fdate)
elif msg['Subject'].lower().rfind('foobar') != -1:
print "Subject match 'foobar', processing: %s" % msg['Subject']
# We should have from the pickle an "observed" set of data, both subjects and message numbers.
if msg['Subject'] in PICKLED_MESSAGES['observed']['subjects']:
print "Already handled this message, moving on to next item."
# Since this was already observed we let it be removed so things don't rerun it later.
# noinspection PyBroadException
try:
PICKLED_MESSAGES['observed']['subjects'].remove(msg['Subject'])
PICKLED_MESSAGES['observed']['msgnums'].remove(i)
except:
pass
continue
else:
continue
# Do stuff with the message to store it in a special way on the filesystem
# Note that we've now looked at the message, so next-run we can see
# what was handled on the last run.
PICKLED_MESSAGES['observed']['msgnums'].append(i)
PICKLED_MESSAGES['observed']['subjects'].append(msg['Subject'])
print "PICKLED:\n%s" % PICKLED_MESSAGES['observed']
conn.uid('STORE', str(i), '-FLAGS', '(\Seen)')
except Exception:
conn.uid('STORE', str(i), '-FLAGS', '(\Seen)')
PICKLED_MESSAGES['observed']['msgnums'].remove(i)
PICKLED_MESSAGES['observed']['subjects'].remove(msg['Subject'])
print "PICKLED:\n%s\n" % PICKLED_MESSAGES
finally:
# Store the pickle file so we can use it next run.
cPickle.dump(PICKLED_MESSAGES, open('observed_msgs.pkl', 'wb'))
if __name__ == "__main__":
# pre-runtime checks - is IMAP up, etc. run first, then this:
# Initialize the PICKLED_MESSAGES data with pickle data or an empty
# structure for the pickle.
# noinspection PyBroadException
try:
PICKLED_MESSAGES = cPickle.load(open('observed_msgs.pkl', 'rb'))
except Exception as e:
PICKLED_MESSAGES = {
'observed': {
'msgnums': [],
'subjects': [],
},
}
# If all checks satisfied, continue and process the main() directives.
try:
main()
except Exception as e:
print("CRITICAL An unhandled error has occurred: %s" % str(e))
exit()
However, it's not setting the correct message as 'unread; when using the methods I've seen suggested on the system. So, I'm not entirely sure whether I'm not getting the UID of the message proper, or whether there's something else I'm missing doing here.