All,

[ Apologies if this was fixed or otherwise addressed already. ]


I'm using dbmail 2.2.10, and it looks like the EXAMINE command is
marking messages as read when I FETCH them. This looks like a bug that
was fixed ages ago:

http://osdir.com/ml/mail.imap.dbmail.devel/2004-10/msg00124.html

However I have tested the behavior and it is still working this way.


If you run the attached Python script, you will see that the status of
the e-mail is changed, even though the IMAP library is using "EXAMINE"
to connect to the mailbox. To do this, run:

$ python ExamineFail.py imap-host imap-user
Flags for added message: 
Flags for added message: \Seen

As you can see, the first time the message has no flags, and the second
time the message has the \Seen flag set. As I understand the RFC, this
should not be allowed.

It uses SSL. If you don't have this enabled then you can change the call
from IMAP4_SSL to IMAP4.


Note that you can use BODY.PEEK[] rather than RFC822 when getting the
e-mails and then the flags are not updated. The problem is not all
programs do this, but rather expect that read-only access is in fact
read-only.

--
Shane
import imaplib
import sys
import getpass
import random
import email.parser
import time

# log in using host/user/password specified on command line
if (len(sys.argv) < 3) or (len(sys.argv) > 4):
    sys.stderr.write('Syntax: %s host user [password]\n' % sys.argv[0])
    sys.exit(1)

host = sys.argv[1]
imap = imaplib.IMAP4_SSL(host)

user = sys.argv[2]
if len(sys.argv) == 4:
    password = sys.argv[3]
else:
    password = getpass.getpass("IMAP password for %s at %s:" % (user, host))
imap.login(user, password)

# create an e-mail message to put in the mailbox
message_text = """
From: [email protected]
To: [email protected]
Subject: ExamineFail.py message
Date: %s

This message is to show IMAP EXAMINE failing in dbmail.
""" % time.strftime("%a, %d %b %Y %H:%M:%S +0000", time.gmtime())
parser = email.parser.Parser()
email_message = parser.parsestr(message_text.lstrip())
email_flags = ('\\Recent',)
email_time = imaplib.Time2Internaldate(time.time())

# create a new mailbox
created = False
while not created:
    mailbox_name = 'ExamineFail%05d' % random.randint(0, 99999)
    typ, replies = imap.create(mailbox_name)
    if typ == 'OK':
        created = True


# from this point on, execute in a try/except block so we can 
# cleanup the mailbox on any errors
try:

    # put a message in the mailbox
    typ, replies = imap.append(mailbox_name, 
                               email_flags, email_time, str(email_message))
    if typ != 'OK': raise RuntimeError('Unable to append to mailbox')

    # now select the mailbox for read-only access
    # this uses the EXAMINE command of IMAP
    typ, replies = imap.select(mailbox_name, True)
    if typ != 'OK': raise RuntimeError('Unable to select mailbox')

    # get our message
    typ, msgnum_info = imap.search(None, 'ALL')
    if typ != 'OK': raise RuntimeError('Unable to search')
    msgnums = msgnum_info[0].split()
    if len(msgnums) != 1:
       raise RuntimeError('%d messages in mailbox, should be 1' % len(msgnums))

    typ, data = imap.fetch(msgnums[0], '(RFC822 FLAGS)')
    if typ != 'OK': raise RuntimeError('Unable to fetch message')
    info = data[0]
    flags = imaplib.ParseFlags(info[0])
    msg = info[1]
    sys.stdout.write('Flags for added message: ' + ', '.join(flags) + '\n')

    # now open the mailbox again (still read-only), and check the flags
    typ, replies = imap.select(mailbox_name, True)
    if typ != 'OK': raise RuntimeError('Unable to select mailbox')
    typ, msgnum_info = imap.search(None, 'ALL')
    if typ != 'OK': raise RuntimeError('Unable to search')
    msgnums = msgnum_info[0].split()
    if len(msgnums) != 1:
       raise RuntimeError('%d messages in mailbox, should be 1' % len(msgnums))

    typ, data = imap.fetch(msgnums[0], '(RFC822 FLAGS)')
    if typ != 'OK': raise RuntimeError('Unable to fetch message')
    info = data[0]
    flags = imaplib.ParseFlags(info[0])
    msg = info[1]
    sys.stdout.write('Flags for added message: ' + ', '.join(flags) + '\n')

finally:
   typ, replies = imap.delete(mailbox_name)
   if typ != 'OK':
       sys.stderr.write('Error deleting mailbox "%s"\n' % mailbox_name)

_______________________________________________
DBmail mailing list
[email protected]
http://mailman.fastxs.nl/cgi-bin/mailman/listinfo/dbmail

Reply via email to