Beispiel #1
0
def test_unread_and_draft_tags_applied(db, thread, message, folder, imapuid):
    """Test that the unread and draft tags are added/removed from a thread
    after UID flag changes."""
    msg_uid = imapuid.msg_uid
    update_metadata(ACCOUNT_ID, db.session, folder.name, folder.id, [msg_uid],
                    {msg_uid: GmailFlags((u'\\Seen', ), (u'\\Draft', ))})
    assert 'unread' not in [t.name for t in thread.tags]
    assert 'drafts' in [t.name for t in thread.tags]
    assert message.is_read

    update_metadata(ACCOUNT_ID, db.session, folder.name, folder.id, [msg_uid],
                    {msg_uid: GmailFlags((), ())})
    assert 'unread' in [t.name for t in thread.tags]
    assert 'drafts' not in [t.name for t in thread.tags]
    assert not message.is_read
Beispiel #2
0
def test_update_metadata(db, folder):
    """Check that threads are updated correctly when a label that we haven't
    seen before is added to multiple threads -- previously, this would fail
    with an IntegrityError because autoflush was disabled."""
    first_thread = add_fake_thread(db.session, NAMESPACE_ID)
    second_thread = add_fake_thread(db.session, NAMESPACE_ID)
    uids = []

    first_thread_uids = (22222, 22223)
    for msg_uid in first_thread_uids:
        message = add_fake_message(db.session, NAMESPACE_ID, first_thread)
        uids.append(
            add_fake_imapuid(db.session, ACCOUNT_ID, message, folder, msg_uid))

    second_thread_uids = (22224, 22226)
    for msg_uid in second_thread_uids:
        message = add_fake_message(db.session, NAMESPACE_ID, second_thread)
        uids.append(
            add_fake_imapuid(db.session, ACCOUNT_ID, message, folder, msg_uid))
    db.session.add_all(uids)
    db.session.commit()

    msg_uids = first_thread_uids + second_thread_uids

    new_flags = {
        msg_uid: GmailFlags((), (u'\\some_new_label', ))
        for msg_uid in msg_uids
    }
    update_metadata(ACCOUNT_ID, db.session, folder.name, folder.id, msg_uids,
                    new_flags)
    db.session.commit()
    assert 'some_new_label' in [tag.name for tag in first_thread.tags]
    assert 'some_new_label' in [tag.name for tag in second_thread.tags]
def test_gmail_drafts_flag_constrained_by_folder(
    db, default_account, message, imapuid, folder
):
    new_flags = {imapuid.msg_uid: GmailFlags((), (u"\\Draft",), None)}
    update_metadata(default_account.id, folder.id, "all", new_flags, db.session)
    assert message.is_draft
    update_metadata(default_account.id, folder.id, "trash", new_flags, db.session)
    assert not message.is_draft
def test_gmail_flags(gmail_client, constants):
    expected_resp = '{seq} (FLAGS {flags} X-GM-LABELS {g_labels} ' \
                    'UID {uid} MODSEQ ({modseq}))'.format(**constants)
    unsolicited_resp = '1198 (UID 1731 MODSEQ (95244) FLAGS (\\Seen))'
    patch_imap4(gmail_client, [expected_resp, unsolicited_resp])
    uid = constants['uid']
    flags = constants['flags']
    g_labels = constants['g_labels']
    assert gmail_client.flags([uid]) == {uid: GmailFlags(flags, g_labels)}
def test_messages_deleted_asynchronously(db, default_account, thread, message,
                                         imapuid, folder):
    msg_uid = imapuid.msg_uid
    update_metadata(default_account.id, folder.id,
                    {msg_uid: GmailFlags((), ('label', ))}, db.session)
    assert 'label' in [cat.display_name for cat in message.categories]
    remove_deleted_uids(default_account.id, folder.id, [msg_uid], db.session)
    assert abs((message.deleted_at - datetime.utcnow()).total_seconds()) < 2
    # Check that message categories do get updated synchronously.
    assert 'label' not in [cat.display_name for cat in message.categories]
Beispiel #6
0
def test_only_uids_deleted_synchronously(db, default_account,
                                         default_namespace, thread, message,
                                         imapuid, folder):
    msg_uid = imapuid.msg_uid
    update_metadata(default_account.id, db.session, folder.name, folder.id,
                    [msg_uid], {msg_uid: GmailFlags((), ('label', ))})
    assert 'label' in [t.name for t in thread.tags]
    remove_deleted_uids(default_account.id, db.session, [msg_uid], folder.id)
    assert abs((message.deleted_at - datetime.utcnow()).total_seconds()) < 1
    # Check that thread tags do get updated synchronously.
    assert 'label' not in [t.name for t in thread.tags]
def test_gmail_flags(gmail_client, constants):
    expected_resp = (
        "{seq} (FLAGS {flags} X-GM-LABELS {raw_g_labels} "
        "UID {uid} MODSEQ ({modseq}))".format(**constants)
    )
    unsolicited_resp = "1198 (UID 1731 MODSEQ (95244) FLAGS (\\Seen))"
    patch_imap4(gmail_client, [expected_resp, unsolicited_resp])
    uid = constants["uid"]
    flags = constants["flags"]
    modseq = constants["modseq"]
    g_labels = constants["unicode_g_labels"]
    assert gmail_client.flags([uid]) == {uid: GmailFlags(flags, g_labels, modseq)}
Beispiel #8
0
def test_gmail_label_sync(db, default_account, message, folder, imapuid,
                          default_namespace):
    # Note that IMAPClient parses numeric labels into integer types. We have to
    # correctly handle those too.
    new_flags = {
        imapuid.msg_uid:
        GmailFlags((), (u'\\Important', u'\\Starred', u'foo', 42), None)
    }
    update_metadata(default_namespace.account.id, folder.id,
                    folder.canonical_name, new_flags, db.session)
    category_canonical_names = {c.name for c in message.categories}
    category_display_names = {c.display_name for c in message.categories}
    assert 'important' in category_canonical_names
    assert {'foo', '42'}.issubset(category_display_names)
def test_renamed_label_refresh(db, default_account, thread, message, imapuid,
                               folder, mock_imapclient, monkeypatch):
    # Check that imapuids see their labels refreshed after running
    # the LabelRenameHandler.
    msg_uid = imapuid.msg_uid
    uid_dict = {msg_uid: GmailFlags((), ('stale label', ), ('23', ))}

    update_metadata(default_account.id, folder.id, folder.canonical_name,
                    uid_dict, db.session)

    new_flags = {
        msg_uid: {
            'FLAGS': ('\\Seen', ),
            'X-GM-LABELS': ('new label', ),
            'MODSEQ': ('23', )
        }
    }
    mock_imapclient._data['[Gmail]/All mail'] = new_flags

    mock_imapclient.add_folder_data(folder.name, new_flags)

    monkeypatch.setattr(MockIMAPClient, 'search', lambda x, y: [msg_uid])

    semaphore = Semaphore(value=1)

    rename_handler = LabelRenameHandler(default_account.id,
                                        default_account.namespace.id,
                                        'new label', semaphore)

    # Acquire the semaphore to check that LabelRenameHandlers block if
    # the semaphore is in-use.
    semaphore.acquire()
    rename_handler.start()

    # Wait 10 secs and check that the data hasn't changed.
    gevent.sleep(10)

    labels = list(imapuid.labels)
    assert len(labels) == 1
    assert labels[0].name == 'stale label'
    semaphore.release()
    rename_handler.join()

    db.session.refresh(imapuid)
    # Now check that the label got updated.
    labels = list(imapuid.labels)
    assert len(labels) == 1
    assert labels[0].name == 'new label'
Beispiel #10
0
def test_gmail_label_sync(db, default_account, message, thread, folder,
                          imapuid):
    if default_account.important_folder is not None:
        db.session.delete(default_account.important_folder)

    msg_uid = imapuid.msg_uid

    # Note that IMAPClient parses numeric labels into integer types. We have to
    # correctly handle those too.
    new_flags = {
        msg_uid: GmailFlags((), (u'\\Important', u'\\Starred', u'foo', 42))
    }
    update_metadata(ACCOUNT_ID, db.session, folder.name, folder.id, [msg_uid],
                    new_flags)
    thread_tag_names = {tag.name for tag in thread.tags}
    assert {'important', 'starred', 'foo'}.issubset(thread_tag_names)
def test_messages_deleted_asynchronously(db, default_account, thread, message,
                                         imapuid, folder):
    msg_uid = imapuid.msg_uid
    update_metadata(
        default_account.id,
        folder.id,
        folder.canonical_name,
        {msg_uid: GmailFlags((), ("label", ), None)},
        db.session,
    )
    assert "label" in [cat.display_name for cat in message.categories]
    remove_deleted_uids(default_account.id, folder.id, [msg_uid])
    db.session.expire_all()
    assert abs((message.deleted_at - datetime.utcnow()).total_seconds()) < 2
    # Check that message categories do get updated synchronously.
    assert "label" not in [cat.display_name for cat in message.categories]
def test_renamed_label_refresh(db, default_account, thread, message, imapuid,
                               folder, mock_imapclient, monkeypatch):
    # Check that imapuids see their labels refreshed after running
    # the LabelRenameHandler.
    msg_uid = imapuid.msg_uid
    uid_dict = {msg_uid: GmailFlags((), ("stale label", ), ("23", ))}

    update_metadata(default_account.id, folder.id, folder.canonical_name,
                    uid_dict, db.session)

    new_flags = {
        msg_uid: {
            b"FLAGS": (b"\\Seen", ),
            b"X-GM-LABELS": (b"new label", ),
            b"MODSEQ": (23, ),
        }
    }
    mock_imapclient._data["[Gmail]/All mail"] = new_flags

    mock_imapclient.add_folder_data(folder.name, new_flags)

    monkeypatch.setattr(MockIMAPClient, "search", lambda x, y: [msg_uid])

    semaphore = Semaphore(value=1)

    rename_handler = LabelRenameHandler(default_account.id,
                                        default_account.namespace.id,
                                        "new label", semaphore)

    # Acquire the semaphore to check that LabelRenameHandlers block if
    # the semaphore is in-use.
    semaphore.acquire()
    rename_handler.start()

    gevent.sleep(0)  # yield to the handler

    labels = list(imapuid.labels)
    assert len(labels) == 1
    assert labels[0].name == "stale label"
    semaphore.release()
    rename_handler.join()

    db.session.refresh(imapuid)
    # Now check that the label got updated.
    labels = list(imapuid.labels)
    assert len(labels) == 1
    assert labels[0].name == "new label"
def test_deleted_labels_get_gced(empty_db, default_account, thread, message,
                                 imapuid, folder):
    # Check that only the labels without messages attached to them
    # get deleted.
    default_namespace = default_account.namespace

    # Create a label w/ no messages attached.
    label = Label.find_or_create(empty_db.session, default_account,
                                 "dangling label")
    label.deleted_at = datetime.utcnow()
    label.category.deleted_at = datetime.utcnow()
    label_id = label.id
    empty_db.session.commit()

    # Create a label with attached messages.
    msg_uid = imapuid.msg_uid
    update_metadata(
        default_account.id,
        folder.id,
        folder.canonical_name,
        {msg_uid: GmailFlags((), ("label", ), None)},
        empty_db.session,
    )

    label_ids = []
    for cat in message.categories:
        for l in cat.labels:
            label_ids.append(l.id)

    handler = DeleteHandler(
        account_id=default_account.id,
        namespace_id=default_namespace.id,
        provider_name=default_account.provider,
        uid_accessor=lambda m: m.imapuids,
        message_ttl=0,
    )
    handler.gc_deleted_categories()
    empty_db.session.commit()

    # Check that the first label got gc'ed
    marked_deleted = empty_db.session.query(Label).get(label_id)
    assert marked_deleted is None

    # Check that the other labels didn't.
    for label_id in label_ids:
        assert empty_db.session.query(Label).get(label_id) is not None
Beispiel #14
0
def test_update_metadata(db):
    """Check that threads are updated correctly when a label that we haven't
    seen before is added to multiple threads -- previously, this would with an
    IntegrityError because autoflush was disabled."""
    first_thread = db.session.query(Thread).get(1)
    second_thread = db.session.query(Thread).get(2)
    folder = db.session.query(Folder).filter(
        Folder.account_id == ACCOUNT_ID,
        Folder.name == '[Gmail]/All Mail').one()
    uids = []

    first_thread_uids = (22222, 22223)
    for msg_uid in first_thread_uids:
        message = add_fake_message(db.session, NAMESPACE_ID, first_thread)
        uids.append(
            ImapUid(account_id=ACCOUNT_ID,
                    message=message,
                    msg_uid=msg_uid,
                    folder=folder))

    second_thread_uids = (22224, 22226)
    for msg_uid in second_thread_uids:
        message = add_fake_message(db.session, NAMESPACE_ID, second_thread)
        uids.append(
            ImapUid(account_id=ACCOUNT_ID,
                    message=message,
                    msg_uid=msg_uid,
                    folder=folder))
    db.session.add_all(uids)
    db.session.commit()

    msg_uids = first_thread_uids + second_thread_uids

    new_flags = {
        msg_uid: GmailFlags((), (u'\\some_new_label', ))
        for msg_uid in msg_uids
    }
    update_metadata(ACCOUNT_ID, db.session, folder.name, folder.id, msg_uids,
                    new_flags)
    db.session.commit()
    assert 'some_new_label' in [tag.name for tag in first_thread.tags]
    assert 'some_new_label' in [tag.name for tag in second_thread.tags]
Beispiel #15
0
def test_gmail_label_sync(db):
    folder = db.session.query(Folder).filter(
        Folder.account_id == ACCOUNT_ID,
        Folder.name == '[Gmail]/All Mail').one()
    account = db.session.query(Account).get(ACCOUNT_ID)
    if account.important_folder is not None:
        db.session.delete(account.important_folder)
    thread = db.session.query(Thread).get(1)
    message = add_fake_message(db.session, NAMESPACE_ID, thread)
    db.session.add(
        ImapUid(account_id=ACCOUNT_ID,
                message=message,
                msg_uid=22222,
                folder=folder))
    db.session.commit()

    new_flags = {22222: GmailFlags((), (u'\\Important', u'\\Starred', u'foo'))}
    update_metadata(ACCOUNT_ID, db.session, folder.name, folder.id, [22222],
                    new_flags)
    thread_tag_names = {tag.name for tag in thread.tags}
    assert {'important', 'starred', 'foo'}.issubset(thread_tag_names)