How Imap Idle Works

IMAP Idle Timeout

As you know, the purpose of IMAP IDLE command (RFC 2177) is to make it possible to have the server transmit status updates to the client in real time. In this context, status updates means untagged IMAP server responses such as EXISTS, RECENT, FETCH or EXPUNGE that are sent when new messages arrive, message status is updated or a message is removed.

However, these IMAP status updates can be returned by any IMAP command, not just the IDLE command - for example, the NOOP command (see RFC 3501 section 6.1.2) can be used to poll for server updates as well (it predates the IDLE command). IDLE only makes it possible to get these updates more efficiently - if you don't use IDLE command, server updates will simply be sent by the server when the client executes another command (or even when no command is in progress in some cases) - see RFC 3501 section 5.2 and 5.3 for details.

This means that if a message is changed between the IDLE canceling and the new IDLE command, the status updates should not be lost, just as they are not lost if you never used IDLE in the first place (and use NOOP every few seconds instead, for example) - they should simply be sent after the new IDLE command is started.

How to check whether IMAP-IDLE works?

Inspired by http://pymotw.com/2/imaplib/, you can use following Python scripts to check if and how fast push notification via IDLE work:

imaplib_connect.py

import imaplib
import ConfigParser
import os

def open_connection(verbose=False):
# Read the config file
config = ConfigParser.ConfigParser()
config.read([os.path.abspath('settings.ini')])

# Connect to the server
hostname = config.get('server', 'hostname')
if verbose: print 'Connecting to', hostname
connection = imaplib.IMAP4_SSL(hostname)

# Login to our account
username = config.get('account', 'username')
password = config.get('account', 'password')
if verbose: print 'Logging in as', username
connection.login(username, password)
return connection

if __name__ == '__main__':
c = open_connection(verbose=True)
try:
print c
finally:
c.logout()
print "logged out"

imaplib_idlewait.py

import imaplib
import pprint
import imaplib_connect

imaplib.Debug = 4
c = imaplib_connect.open_connection()
try:
c.select('INBOX', readonly=True)
c.send("%s IDLE\r\n"%(c._new_tag()))
print ">>> waiting for new mail..."
while True:
line = c.readline().strip();
if line.startswith('* BYE ') or (len(line) == 0):
print ">>> leaving..."
break
if line.endswith('EXISTS'):
print ">>> NEW MAIL ARRIVED!"
finally:
try:
print ">>> closing..."
c.close()
except:
pass
c.logout()

settings.ini

[server]
hostname: yourserver.com

[account]
username: yourmail@yourserver.com
password: yoursecretpassword

After creating those files, just call

python imaplib_idlewait.py

Please note, that this scripts does not close gracefully if you press CTRL+C (readline() is blocking and is not terminated by close()), however, for testing it should be good enough.

Also note, that most mail server terminate the connection after 30 minutes. After that you have to re-open the connection, e.g. like demonstrated here: http://blog.mister-muffin.de/2013/06/05/reliable-imap-synchronization-with-idle-support

IMAP Idle, possibility to miss events?

How are you doing this? The below code works pretty well.

inbox.addMessageCountListener(new MessageCountAdapter() { ... })

Of course you need to have another infinite loop something like:

          while (true) {
IMAPFolder f = (IMAPFolder)inbox;
f.idle();
}

IMAP email IDLE stops waiting timeout duration, instead loops instantaneously in Python

I came up with a solution to this. I still don't know why this happened in the first place, but this solved it for me.

I put server.idle() just within the try: code. Then I put server.idle_done() in a finally code segment. That way, every time the program loops it starts the idle and every time it ends it stops the idling. It seems like doing that every time makes the program more stable.

Getting email message after IMAP IDLE command exists response

Uh... "safe"? If you're not controlling a nuclear power plant, then probably. Here's a rule of thumb: will someone be injured when your software fails? If not, whatever it does is safe.

How about "correct"? No, it is incorrect, because the EXISTS response tells you how many messages exist in the mailbox. It does not tell you the UID of any of them.

When to use Noop command to keep alive imap idle connection

Strictly, you do not need NOOP when using IDLE. When in IDLE, the only command you can execute is DONE. You can then immediately go back into a new IDLE.

According to the specification, you must reissue IDLE at least every 29 minutes, as the server is allowed to close connection after 30 minutes. However, if you are behind a NAT (especially on cellular networks), you may need to do it more often to keep the socket mapping alive.



Related Topics



Leave a reply



Submit