3

I am working on a function that collects data from email and has a switch to mark messages as unseen. During development it started to fail I don't know why. I've looked it up in documentation, I've searched stackoverflow (got to this thread, but it didn't help). Anyway. This is the code:

    mail = imaplib.IMAP4_SSL('imap.gmail.com', '993')
    mail.login(settings.INVOICES_LOGIN, settings.INVOICES_PASSWORD)
    mail.select('inbox')

    result, data = mail.uid('search', '(UNSEEN)', 'X-GM-RAW',
                            'SUBJECT: "{0}" FROM: "{1}"'.format(attachment_subject, attachment_from))
    uids = data[0].split()
    for uid in uids:
        result, data = mail.uid('fetch', uid, '(RFC822)')
        m = email.message_from_string(data[0][1])

        if m.get_content_maintype() == 'multipart':
            for part in m.walk():
                if part.get_content_maintype() == 'multipart':
                    continue
                if part.get('Content-Disposition') is None:
                    continue
                if re.match(attachment_filename_re, part.get_filename()):
                    attachments.append({'uid': uid, 'data': part.get_payload(decode=True)})

        if set_not_read:
            mail.store(uid, '-FLAGS', '(\Seen)')

I've debugged it, I am sure that with this flag the mail.store(uid, '-FLAGS', '(\Seen)') part is entered, I've also tried switching to \SEEN and \Seen instead of (\Seen).

EDIT:

What I'm trying to do is to make a script that allows user to mark email as unseen (not read), this is reset the Seen flag, and not to allow it to mark an email as seen (read).

Community
  • 1
  • 1
gonczor
  • 3,994
  • 1
  • 21
  • 46
  • 1
    Working with `imaplib` myself just recently, I can confirm the state of SO questions is pretty pitiful. – Wayne Werner Aug 03 '16 at 13:33
  • What's the output of `mail.store(uid, '-FLAGS', '(\\SEEN)')`? – Wayne Werner Aug 03 '16 at 13:57
  • No, it just won't work. – gonczor Aug 03 '16 at 14:11
  • "won't work" - does that mean that it produces an error? Produces nothing? Because `mail.store` *should* be producing a result. You can do `print(mail.store(uid, '-FLAGS', '(\\SEEN)')` and it should produce *something*, even if that something is a traceback. If nothing at all happens then something very strange is happening. – Wayne Werner Aug 03 '16 at 14:17
  • I mean the result is a tuple ('OK', [None]) and the mail in the mailbox remains marked as read. – gonczor Aug 03 '16 at 14:21
  • When you get the flags - `print(mail.fetch(uid, '(FLAGS)'))` right after you call store, what is the result? – Wayne Werner Aug 03 '16 at 14:26
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/119022/discussion-between-wayne-werner-and-wiktor-gonczaronek). – Wayne Werner Aug 03 '16 at 15:02
  • You are only searching for UNSEEN messages, so they are already unseen. Use FETCH BODY.PEEK[] so they don't get marked seen. – Max Aug 03 '16 at 18:38
  • @WayneWener That may have more to do with the fact that imaplib is a very thin protocol library, and does not do any parsing work. It assumes you already know RFC 3501 and email standards. – Max Aug 03 '16 at 18:41

1 Answers1

3

I believe you want

mail.store(uid, '+FLAGS', '(\\Seen)')

I think what you're doing right now is removing the seen flag. But I'll look in the RFC to be sure.

Edit: Yup. That's what the RFC says

-FLAGS <flag list>
         Remove the argument from the flags for the message.  The new
         value of the flags is returned as if a FETCH of those flags was
         done.

Other bits that you may find relevant:

The currently defined data items that can be stored are:

      FLAGS <flag list>
         Replace the flags for the message (other than \Recent) with the
         argument.  The new value of the flags is returned as if a FETCH
         of those flags was done.

      FLAGS.SILENT <flag list>
         Equivalent to FLAGS, but without returning a new value.

      +FLAGS <flag list>
         Add the argument to the flags for the message.  The new value
         of the flags is returned as if a FETCH of those flags was done.

      +FLAGS.SILENT <flag list>
         Equivalent to +FLAGS, but without returning a new value.

      -FLAGS <flag list>
         Remove the argument from the flags for the message.  The new
         value of the flags is returned as if a FETCH of those flags was
         done.

      -FLAGS.SILENT <flag list>
         Equivalent to -FLAGS, but without returning a new value.
Community
  • 1
  • 1
Wayne Werner
  • 49,299
  • 29
  • 200
  • 290
  • Yes, that's exactly what I'm trying to do. Mark an email as `UNSEEN`. I thought the title was clear, I'll correct it just now. – gonczor Aug 03 '16 at 13:40
  • So, did you try -FLAGS (\\Seen) ? You're not using raw strings, so you need to escape the backslash. – Max Aug 03 '16 at 18:40