def test_recompute_thread_labels(db):
    # This is smoke test that checks that a lone label gets
    # added to a thread's labels.
    thread = db.session.query(Thread).get(THREAD_ID)
    g_labels = thread.messages[-1].imapuids[-1].g_labels

    g_labels.append('Random-label-1')
    recompute_thread_labels(thread, db.session)
    folders = {folder.name: folder for folder in thread.folders}
    assert 'Random-label-1' in folders
def test_recompute_thread_labels(db):
    # This is smoke test that checks that a lone label gets
    # added to a thread's labels.
    thread = db.session.query(Thread).get(THREAD_ID)
    g_labels = thread.messages[-1].imapuids[-1].g_labels

    g_labels.append('Random-label-1')
    recompute_thread_labels(thread, db.session)
    folders = {folder.name: folder for folder in thread.folders}
    assert 'random-label-1' in folders
def test_recompute_thread_labels(db, thread, default_namespace):
    # This is smoke test that checks that a lone label gets
    # added to a thread's labels.
    account = default_namespace.account
    message = add_fake_message(db.session, default_namespace.id, thread)
    add_fake_imapuid(db.session, account.id, message, account.inbox_folder, 22)
    g_labels = thread.messages[-1].imapuids[-1].g_labels

    g_labels.append('Random-label-1')
    recompute_thread_labels(thread, db.session)
    folders = {folder.name: folder for folder in thread.folders}
    assert 'Random-label-1' in folders
def test_recompute_thread_labels(db, thread, default_namespace):
    # This is smoke test that checks that a lone label gets
    # added to a thread's labels.
    account = default_namespace.account
    message = add_fake_message(db.session, default_namespace.id, thread)
    add_fake_imapuid(db.session, account.id, message,
                     account.inbox_folder, 22)
    g_labels = thread.messages[-1].imapuids[-1].g_labels

    g_labels.append('Random-label-1')
    recompute_thread_labels(thread, db.session)
    folders = {folder.name: folder for folder in thread.folders}
    assert 'Random-label-1' in folders
def test_adding_message_to_thread(db):
    """recompute_thread_labels is not invoked when a new message is added
     (only when UID metadata changes, or when a UID is deleted). Test that
     tag changes work when adding messages to a thread."""
    account = db.session.query(Account).get(ACCOUNT_ID)
    account.namespace.create_canonical_tags()
    thread = db.session.query(Thread).get(THREAD_ID)
    account.trash_folder = Folder(name='Trash', account=account)
    fld_item = FolderItem(thread=thread, folder=account.trash_folder)

    folder_names = [folder.name for folder in thread.folders]
    m = Message(namespace_id=account.namespace.id,
                subject='test message',
                thread_id=thread.id,
                received_date=datetime.datetime.now(),
                size=64,
                sanitized_body="body",
                snippet="snippet")

    uid = ImapUid(account=account,
                  message=m,
                  g_labels=['\\Inbox', 'test-label'],
                  msg_uid=22L,
                  folder_id=account.inbox_folder.id)
    uid.folder = account.inbox_folder
    uid2 = ImapUid(account=account,
                   message=m,
                   g_labels=['test-2'],
                   msg_uid=24L,
                   folder_id=account.trash_folder.id)
    uid2.folder = account.trash_folder

    thread.messages.append(m)
    add_any_new_thread_labels(thread, uid, db.session)
    add_any_new_thread_labels(thread, uid2, db.session)

    folder_names = [folder.name for folder in thread.folders]
    for folder in folder_names:
        assert folder in ['Inbox', 'Trash', 'test-label', 'test-2', '[Gmail]/All Mail', '[Gmail]/Important'],\
            "all folders should be present"

    # Now, remove the message
    m.imapuids.remove(uid2)
    db.session.delete(uid2)
    db.session.flush()

    recompute_thread_labels(thread, db.session)
    folder_names = [folder.name for folder in thread.folders]
    assert 'test-2' not in folder_names,\
        "test-2 label should have been removed from thread"
def test_recompute_thread_labels_removes_trash(db):
    account = db.session.query(Account).get(ACCOUNT_ID)
    thread = db.session.query(Thread).get(THREAD_ID)
    account.trash_folder = Folder(name='Trash', account_id=account.id)
    db.session.flush()

    # Check that the we remove the trash folder from a thread
    # if the latest message has the inbox flag.
    # To do this, we manufacture this situation.
    g_labels = thread.messages[-1].imapuids[-1].g_labels
    if '\\Inbox' not in g_labels:
        g_labels.append('\\Inbox')

    thread.folders.add(account.trash_folder)
    recompute_thread_labels(thread, db.session)
    assert account.trash_folder not in thread.folders,\
        "should have removed trash folder from thread"
def test_recompute_thread_labels_removes_trash(db):
    account = db.session.query(Account).get(ACCOUNT_ID)
    thread = db.session.query(Thread).get(THREAD_ID)
    account.trash_folder = Folder(name='Trash', account_id=account.id)
    db.session.flush()

    # Check that the we remove the trash folder from a thread
    # if the latest message has the inbox flag.
    # To do this, we manufacture this situation.
    g_labels = thread.messages[-1].imapuids[-1].g_labels
    if '\\Inbox' not in g_labels:
        g_labels.append('\\Inbox')

    thread.folders.add(account.trash_folder)
    recompute_thread_labels(thread, db.session)
    assert account.trash_folder not in thread.folders,\
        "should have removed trash folder from thread"
def test_recompute_thread_labels_removes_trash(db, default_account, thread):
    default_account.trash_folder = Folder(name='Trash',
                                          account_id=default_account.id)
    message = add_fake_message(db.session, default_account.namespace.id,
                               thread)
    add_fake_imapuid(db.session, default_account.id, message,
                     default_account.inbox_folder, 22)
    db.session.commit()

    # Check that the we remove the trash folder from a thread
    # if the latest message has the inbox flag.
    # To do this, we manufacture this situation.
    g_labels = thread.messages[-1].imapuids[-1].g_labels
    if '\\Inbox' not in g_labels:
        g_labels.append('\\Inbox')

    thread.folders.add(default_account.trash_folder)
    recompute_thread_labels(thread, db.session)
    assert default_account.trash_folder not in thread.folders,\
        "should have removed trash folder from thread"
def test_recompute_thread_labels_removes_trash(db, default_account, thread):
    default_account.trash_folder = Folder(name='Trash',
                                          account_id=default_account.id)
    message = add_fake_message(db.session, default_account.namespace.id,
                               thread)
    add_fake_imapuid(db.session, default_account.id, message,
                     default_account.inbox_folder, 22)
    db.session.commit()

    # Check that the we remove the trash folder from a thread
    # if the latest message has the inbox flag.
    # To do this, we manufacture this situation.
    g_labels = thread.messages[-1].imapuids[-1].g_labels
    if '\\Inbox' not in g_labels:
        g_labels.append('\\Inbox')

    thread.folders.add(default_account.trash_folder)
    recompute_thread_labels(thread, db.session)
    assert default_account.trash_folder not in thread.folders,\
        "should have removed trash folder from thread"
def test_adding_message_to_thread(db):
    """recompute_thread_labels is not invoked when a new message is added
     (only when UID metadata changes, or when a UID is deleted). Test that
     tag changes work when adding messages to a thread."""
    account = db.session.query(Account).get(ACCOUNT_ID)
    account.namespace.create_canonical_tags()
    thread = db.session.query(Thread).get(THREAD_ID)
    account.trash_folder = Folder(name='Trash', account=account)
    FolderItem(thread=thread, folder=account.trash_folder)

    folder_names = [folder.name for folder in thread.folders]
    m = Message(namespace_id=account.namespace.id, subject='test message',
                thread_id=thread.id, received_date=datetime.datetime.now(),
                size=64, body="body", snippet="snippet")

    uid = ImapUid(account=account, message=m,
                  g_labels=['\\Inbox', 'test-label'],
                  msg_uid=22L, folder_id=account.inbox_folder.id)
    uid.folder = account.inbox_folder
    uid2 = ImapUid(account=account, message=m, g_labels=['test-2'],
                   msg_uid=24L, folder_id=account.trash_folder.id)
    uid2.folder = account.trash_folder

    thread.messages.append(m)
    add_any_new_thread_labels(thread, uid, db.session)
    add_any_new_thread_labels(thread, uid2, db.session)

    folder_names = [folder.name for folder in thread.folders]
    for folder in folder_names:
        assert folder in ['Inbox', 'Trash', 'test-label', 'test-2', '[Gmail]/All Mail', '[Gmail]/Important'],\
            "all folders should be present"

    # Now, remove the message
    m.imapuids.remove(uid2)
    db.session.delete(uid2)
    db.session.flush()

    recompute_thread_labels(thread, db.session)
    folder_names = [folder.name for folder in thread.folders]
    assert 'test-2' not in folder_names,\
        "test-2 label should have been removed from thread"
예제 #11
0
def add_new_imapuids(crispin_client, remote_g_metadata, syncmanager_lock,
                     uids):
    """
    Add ImapUid entries only for (already-downloaded) messages.

    If a message has already been downloaded via another folder, we only need
    to add `ImapUid` accounting for the current folder. `Message` objects
    etc. have already been created.

    """
    flags = crispin_client.flags(uids)

    with syncmanager_lock:
        with mailsync_session_scope() as db_session:
            # Since we prioritize download for messages in certain threads, we
            # may already have ImapUid entries despite calling this method.
            local_folder_uids = {uid for uid, in
                                 db_session.query(ImapUid.msg_uid).join(Folder)
                                 .filter(
                                     ImapUid.account_id ==
                                     crispin_client.account_id,
                                     Folder.name ==
                                     crispin_client.selected_folder_name,
                                     ImapUid.msg_uid.in_(uids))}
            uids = [uid for uid in uids if uid not in local_folder_uids]

            if uids:
                acc = db_session.query(GmailAccount).get(
                    crispin_client.account_id)

                # collate message objects to relate the new imapuids to
                imapuid_for = dict([(metadata.msgid, uid) for (uid, metadata)
                                    in remote_g_metadata.items()
                                    if uid in uids])
                imapuid_g_msgids = [remote_g_metadata[uid].msgid for uid in
                                    uids]
                message_for = dict([(imapuid_for[m.g_msgid], m) for m in
                                    db_session.query(Message).join(ImapThread)
                                    .filter(
                                        Message.g_msgid.in_(imapuid_g_msgids),
                                        ImapThread.namespace_id ==
                                        acc.namespace.id)])

                # Stop Folder.find_or_create()'s query from triggering a flush.
                with db_session.no_autoflush:
                    new_imapuids = [ImapUid(
                        account=acc,
                        folder=Folder.find_or_create(
                            db_session, acc,
                            crispin_client.selected_folder_name),
                        msg_uid=uid, message=message_for[uid]) for uid in uids
                        if uid in message_for]
                    for item in new_imapuids:
                        # skip uids which have disappeared in the meantime
                        if item.msg_uid in flags:
                            item.update_flags_and_labels(
                                flags[item.msg_uid].flags,
                                flags[item.msg_uid].labels)

                            item.message.is_draft = item.is_draft
                            common.update_unread_status(item)
                db_session.add_all(new_imapuids)
                db_session.flush()

                # Don't forget to update thread labels.
                messages = set(message_for.values())
                unique_threads = set([message.thread for message in messages])

                for thread in unique_threads:
                    common.recompute_thread_labels(thread, db_session)
                db_session.commit()
예제 #12
0
def add_new_imapuids(crispin_client, remote_g_metadata, syncmanager_lock,
                     uids):
    """
    Add ImapUid entries only for (already-downloaded) messages.

    If a message has already been downloaded via another folder, we only need
    to add `ImapUid` accounting for the current folder. `Message` objects
    etc. have already been created.

    """
    flags = crispin_client.flags(uids)

    with syncmanager_lock:
        with mailsync_session_scope() as db_session:
            # Since we prioritize download for messages in certain threads, we
            # may already have ImapUid entries despite calling this method.
            local_folder_uids = {
                uid
                for uid, in db_session.query(ImapUid.msg_uid).join(Folder).
                filter(ImapUid.account_id == crispin_client.account_id,
                       Folder.name == crispin_client.selected_folder_name,
                       ImapUid.msg_uid.in_(uids))
            }
            uids = [uid for uid in uids if uid not in local_folder_uids]

            if uids:
                acc = db_session.query(GmailAccount).get(
                    crispin_client.account_id)

                # collate message objects to relate the new imapuids to
                imapuid_for = dict([
                    (metadata.msgid, uid)
                    for (uid, metadata) in remote_g_metadata.items()
                    if uid in uids
                ])
                imapuid_g_msgids = [
                    remote_g_metadata[uid].msgid for uid in uids
                ]
                message_for = dict([
                    (imapuid_for[m.g_msgid], m)
                    for m in db_session.query(Message).join(ImapThread).filter(
                        Message.g_msgid.in_(imapuid_g_msgids),
                        ImapThread.namespace_id == acc.namespace.id)
                ])

                # Stop Folder.find_or_create()'s query from triggering a flush.
                with db_session.no_autoflush:
                    new_imapuids = [
                        ImapUid(account=acc,
                                folder=Folder.find_or_create(
                                    db_session, acc,
                                    crispin_client.selected_folder_name),
                                msg_uid=uid,
                                message=message_for[uid]) for uid in uids
                        if uid in message_for
                    ]
                    for item in new_imapuids:
                        # skip uids which have disappeared in the meantime
                        if item.msg_uid in flags:
                            item.update_flags_and_labels(
                                flags[item.msg_uid].flags,
                                flags[item.msg_uid].labels)

                            item.message.is_draft = item.is_draft
                            common.update_unread_status(item)
                db_session.add_all(new_imapuids)
                db_session.flush()

                # Don't forget to update thread labels.
                messages = set(message_for.values())
                unique_threads = set([message.thread for message in messages])

                for thread in unique_threads:
                    common.recompute_thread_labels(thread, db_session)
                db_session.commit()