def get_g_metadata(crispin_client, db_session, log, folder_name, uids, syncmanager_lock): assert folder_name == crispin_client.selected_folder_name, \ "crispin selected folder isn't as expected" account_id = crispin_client.account_id remote_g_metadata = None saved_validity = account.get_uidvalidity(account_id, db_session, folder_name) if saved_validity is not None: # If there's no cached validity we probably haven't run before. remote_g_metadata = retrieve_saved_g_metadata(crispin_client, db_session, log, folder_name, uids, saved_validity, syncmanager_lock) if remote_g_metadata is None: remote_g_metadata = crispin_client.g_metadata( crispin_client.all_uids()) set_cache(remote_g_metadata_cache_file(account_id, folder_name), remote_g_metadata) # Save highestmodseq that corresponds to the saved g_metadata. account.update_uidvalidity(account_id, db_session, folder_name, crispin_client.selected_uidvalidity, crispin_client.selected_highestmodseq) db_session.commit() return remote_g_metadata
def base_poll(crispin_client, db_session, log, folder_name, shared_state, highestmodseq_fn): """ It checks for changed message metadata and new messages using CONDSTORE / HIGHESTMODSEQ and also checks for deleted messages. We may wish to frob update frequencies based on which folder a user has visible in the UI as well, and whether or not a user is actually logged in on any devices. """ with crispin_client.pool.get() as c: saved_validity = account.get_uidvalidity(crispin_client.account_id, db_session, folder_name) # Start a session since we're going to IDLE below anyway... status = crispin_client.select_folder(folder_name, uidvalidity_cb(db_session, crispin_client.account_id), c) if status["HIGHESTMODSEQ"] > saved_validity.highestmodseq: highestmodseq_update( crispin_client, db_session, log, folder_name, saved_validity.highestmodseq, shared_state["status_cb"], highestmodseq_fn, shared_state["syncmanager_lock"], c, ) # We really only want to idle on a folder for new messages. Idling on # `All Mail` won't tell us when messages are archived from the Inbox # TODO make sure the server supports the IDLE command (Yahoo does not) if folder_name.lower() in IDLE_FOLDERS: shared_state["status_cb"](crispin_client.account_id, "idle", (folder_name, datetime.utcnow().isoformat())) status = crispin_client.select_folder(folder_name, uidvalidity_cb(db_session, crispin_client.account_id), c) idle_frequency = 1800 # 30min log.info("Idling on {0} with {1} timeout".format(folder_name, idle_frequency)) c.idle() c.idle_check(timeout=idle_frequency) # If we want to do soemthing with the response, but lousy # because it uses sequence IDs instead of UIDs # resp = c.idle_check(timeout=shared_state['poll_frequency']) # r = dict( EXISTS=[], EXPUNGE=[]) # for msg_uid, cmd in resp: # r[cmd].append(msg_uid) # print r c.idle_done() log.info("IDLE triggered poll or timeout reached on {0}".format(folder_name)) else: shared_state["status_cb"](crispin_client.account_id, "poll", (folder_name, datetime.utcnow().isoformat())) log.info("Sleeping on {0} for {1} seconds".format(folder_name, shared_state["poll_frequency"])) sleep(shared_state["poll_frequency"]) return "poll"
def check_flags(crispin_client, db_session, log, folder_name, local_uids, syncmanager_lock, c): """ Update message flags if folder has changed on the remote. If we have a saved uidvalidity for this folder, make sure the folder hasn't changed since we saved it. Otherwise we need to query for flag changes too. """ saved_validity = account.get_uidvalidity(crispin_client.account_id, db_session, folder_name) if saved_validity is not None: last_highestmodseq = saved_validity.highestmodseq if last_highestmodseq > crispin_client.selected_highestmodseq: uids = crispin_client.new_and_updated_uids(last_highestmodseq, c) if uids: _, updated = new_or_updated(uids, local_uids) update_metadata(crispin_client, db_session, log, folder_name, updated, syncmanager_lock, c)
def fn(folder, select_info): assert folder is not None and select_info is not None, "must start IMAP session before verifying UID validity" saved_validity = account.get_uidvalidity(account_id, db_session, folder) selected_uidvalidity = select_info["UIDVALIDITY"] if saved_validity: is_valid = account.uidvalidity_valid( account_id, db_session, selected_uidvalidity, folder, saved_validity.uid_validity ) if not is_valid: raise UIDInvalid( "folder: {}, remote uidvalidity: {}, cached uidvalidity: {}".format( folder, selected_uidvalidity, saved_validity.uid_validity ) ) return select_info