Exemple #1
0
def test_reconcile_message(db, config):
    from inbox.models.util import reconcile_message
    from inbox.sendmail.base import create_draft
    from inbox.models.account import Account
    from inbox.models.message import Message
    from inbox.log import get_logger
    log = get_logger()

    account = db.session.query(Account).get(ACCOUNT_ID)
    draft = create_draft(db.session, account)

    assert draft.inbox_uid == draft.public_id, 'draft has incorrect inbox_uid'
    inbox_uid = draft.inbox_uid

    message = Message()
    message.thread_id = THREAD_ID
    message.received_date = datetime.utcnow()
    message.size = len('')
    message.is_draft = True
    message.is_read = True
    message.sanitized_body = ''
    message.snippet = ''
    message.inbox_uid = draft.inbox_uid
    db.session.add(message)
    db.session.commit()

    reconcile_message(db.session, log, inbox_uid, message)

    assert draft.resolved_message and draft.resolved_message.id == message.id,\
        'draft not reconciled correctly'

    assert message.public_id != draft.public_id, \
        'message has incorrect public_id'
Exemple #2
0
def add_gmail_attrs(db_session, log, new_uid, flags, folder, g_thrid, g_msgid,
                    g_labels, created):
    """ Gmail-specific post-create-message bits. """
    # Disable autoflush so we don't try to flush a message with null
    # thread_id, causing a crash, and so that we don't flush on each
    # added/removed label.
    with db_session.no_autoflush:
        new_uid.message.g_msgid = g_msgid
        # NOTE: g_thrid == g_msgid on the first message in the thread :)
        new_uid.message.g_thrid = g_thrid
        new_uid.update_imap_flags(flags, g_labels)

        thread = new_uid.message.thread = ImapThread.from_gmail_message(
            db_session, new_uid.account.namespace, new_uid.message)

        # make sure this thread has all the correct labels
        new_labels = account.update_thread_labels(thread, folder.name,
                                                  g_labels, db_session)

        # Reconciliation for Drafts, Sent Mail folders:
        if (('draft' in new_labels or 'sent' in new_labels) and not
                created and new_uid.message.inbox_uid):
            reconcile_message(db_session, log, new_uid.message.inbox_uid,
                              new_uid.message)

        return new_uid
Exemple #3
0
    def add_message_attrs(self, db_session, new_uid, msg, folder):
        """ Gmail-specific post-create-message bits. """
        # Disable autoflush so we don't try to flush a message with null
        # thread_id, causing a crash, and so that we don't flush on each
        # added/removed label.
        with db_session.no_autoflush:
            new_uid.message.g_msgid = msg.g_msgid
            # NOTE: g_thrid == g_msgid on the first message in the thread :)
            new_uid.message.g_thrid = msg.g_thrid

            # we rely on Gmail's threading instead of our threading algorithm.
            new_uid.message.thread_order = 0
            new_uid.update_imap_flags(msg.flags, msg.g_labels)

            thread = new_uid.message.thread = ImapThread.from_gmail_message(
                db_session, new_uid.account.namespace, new_uid.message)

            # make sure this thread has all the correct labels
            new_labels = common.update_thread_labels(thread, folder.name,
                                                     msg.g_labels, db_session)

            # Reconciliation for Drafts, Sent Mail folders:
            if (('draft' in new_labels or 'sent' in new_labels)
                    and not msg.created and new_uid.message.inbox_uid):
                reconcile_message(db_session, new_uid.message.inbox_uid,
                                  new_uid.message)

            return new_uid
Exemple #4
0
    def add_message_attrs(self, db_session, new_uid, msg, folder):
        """ Gmail-specific post-create-message bits. """
        # Disable autoflush so we don't try to flush a message with null
        # thread_id, causing a crash, and so that we don't flush on each
        # added/removed label.
        with db_session.no_autoflush:
            new_uid.message.g_msgid = msg.g_msgid
            # NOTE: g_thrid == g_msgid on the first message in the thread :)
            new_uid.message.g_thrid = msg.g_thrid

            # we rely on Gmail's threading instead of our threading algorithm.
            new_uid.message.thread_order = 0
            new_uid.update_imap_flags(msg.flags, msg.g_labels)

            thread = new_uid.message.thread = ImapThread.from_gmail_message(
                db_session, new_uid.account.namespace, new_uid.message)

            # make sure this thread has all the correct labels
            new_labels = common.update_thread_labels(thread, folder.name,
                                                     msg.g_labels, db_session)

            # Reconciliation for Drafts, Sent Mail folders:
            if (('draft' in new_labels or 'sent' in new_labels) and not
                    msg.created and new_uid.message.inbox_uid):
                reconcile_message(db_session, new_uid.message.inbox_uid,
                                  new_uid.message)

            return new_uid
Exemple #5
0
def add_yahoo_attrs(db_session, log, new_uid, flags, folder, created):
    """ Yahoo-specific post-create-message bits."""
    with db_session.no_autoflush:
        new_uid.message.thread = ImapThread.from_yahoo_message(
            db_session, new_uid.account.namespace, new_uid.message)
        new_uid.update_imap_flags(flags)

        if folder in ('draft', 'sent') and not created and new_uid.message.inbox_uid:
            reconcile_message(db_session, log, new_uid.message.inbox_uid,
                              new_uid.message)

        return new_uid
def create_imap_message(db_session, log, account, folder, msg):
    """ IMAP-specific message creation logic.

    This is the one function in this file that gets to take an account
    object instead of an account_id, because we need to relate the
    account to ImapUids for versioning to work, since it needs to look
    up the namespace.

    Returns
    -------
    imapuid : inbox.models.tables.imap.ImapUid
        New db object, which links to new Message and Block objects through
        relationships. All new objects are uncommitted.
    """
    new_msg = Message.create_from_synced(account=account, mid=msg.uid,
                                         folder_name=folder.name,
                                         received_date=msg.internaldate,
                                         body_string=msg.body)

    # Check to see if this is a copy of a message that was first created
    # by the Inbox API. If so, don't create a new object; just use the old one.
    existing_copy = reconcile_message(new_msg, db_session)
    if existing_copy is not None:
        new_msg = existing_copy

    imapuid = ImapUid(account=account, folder=folder, msg_uid=msg.uid,
                      message=new_msg)
    imapuid.update_flags_and_labels(msg.flags, msg.g_labels)

    new_msg.is_draft = imapuid.is_draft
    new_msg.is_read = imapuid.is_seen

    update_contacts_from_message(db_session, new_msg, account.namespace)
    return imapuid
Exemple #7
0
def create_imap_message(db_session, log, account, folder, msg):
    """ IMAP-specific message creation logic.

    This is the one function in this file that gets to take an account
    object instead of an account_id, because we need to relate the
    account to ImapUids for versioning to work, since it needs to look
    up the namespace.

    Returns
    -------
    imapuid : inbox.models.tables.imap.ImapUid
        New db object, which links to new Message and Block objects through
        relationships. All new objects are uncommitted.
    """
    new_msg = Message.create_from_synced(account=account, mid=msg.uid,
                                         folder_name=folder.name,
                                         received_date=msg.internaldate,
                                         body_string=msg.body)

    # Check to see if this is a copy of a message that was first created
    # by the Inbox API. If so, don't create a new object; just use the old one.
    existing_copy = reconcile_message(new_msg, db_session)
    if existing_copy is not None:
        new_msg = existing_copy

    imapuid = ImapUid(account=account, folder=folder, msg_uid=msg.uid,
                      message=new_msg)
    imapuid.update_flags_and_labels(msg.flags, msg.g_labels)

    new_msg.is_draft = imapuid.is_draft
    new_msg.is_read = imapuid.is_seen

    update_contacts_from_message(db_session, new_msg, account.namespace)

    return imapuid
Exemple #8
0
def create_imap_message(db_session, account, folder, msg):
    """
    IMAP-specific message creation logic.

    Returns
    -------
    imapuid : inbox.models.backends.imap.ImapUid
        New db object, which links to new Message and Block objects through
        relationships. All new objects are uncommitted.

    """
    new_message = Message.create_from_synced(
        account=account, mid=msg.uid, folder_name=folder.name, received_date=msg.internaldate, body_string=msg.body
    )

    # Check to see if this is a copy of a message that was first created
    # by the Nylas API. If so, don't create a new object; just use the old one.
    existing_copy = reconcile_message(new_message, db_session)
    if existing_copy is not None:
        new_message = existing_copy

    imapuid = ImapUid(account=account, folder=folder, msg_uid=msg.uid, message=new_message)
    imapuid.update_flags(msg.flags)
    if msg.g_labels is not None:
        imapuid.update_labels(msg.g_labels)

    # Update the message's metadata
    with db_session.no_autoflush:
        is_draft = imapuid.is_draft and (folder.canonical_name == "drafts" or folder.canonical_name == "all")
        update_message_metadata(db_session, account, new_message, is_draft)

    update_contacts_from_message(db_session, new_message, account.namespace)

    return imapuid
Exemple #9
0
def add_attrs(db_session, log, new_uid, flags, folder, created):
    """ Post-create-message bits."""
    with db_session.no_autoflush:
        clean_subject = cleanup_subject(new_uid.message.subject)
        parent_threads = db_session.query(ImapThread).\
                    filter(ImapThread.subject.like(clean_subject)).all()

        if parent_threads == []:
            new_uid.message.thread = ImapThread.from_imap_message(
                db_session, new_uid.account.namespace, new_uid.message)
            new_uid.message.thread_order = 0
        else:
            # FIXME: arbitrarily select the first thread. This shouldn't
            # be a problem now but it could become one if we choose
            # to implement thread-splitting.
            parent_thread = parent_threads[0]
            parent_thread.messages.append(new_uid.message)
            constructed_thread = thread_messages(parent_thread.messages)
            for index, message in enumerate(constructed_thread):
                message.thread_order = index

        # FIXME: refactor 'new_labels' name. This is generic IMAP, not
        # gmail.
        # make sure this thread has all the correct labels
        new_labels = account.update_thread_labels(new_uid.message.thread,
                                                  folder.name,
                                                  [folder.canonical_name],
                                                  db_session)

        # Reconciliation for Drafts, Sent Mail folders:
        if (('draft' in new_labels or 'sent' in new_labels) and not created
                and new_uid.message.inbox_uid):
            reconcile_message(db_session, log, new_uid.message.inbox_uid,
                              new_uid.message)

        new_uid.update_imap_flags(flags)

        return new_uid
Exemple #10
0
def add_attrs(db_session, log, new_uid, flags, folder, created):
    """ Post-create-message bits."""
    with db_session.no_autoflush:
        clean_subject = cleanup_subject(new_uid.message.subject)
        parent_threads = db_session.query(ImapThread).filter(
            ImapThread.subject.like(clean_subject)).all()

        if parent_threads == []:
            new_uid.message.thread = ImapThread.from_imap_message(
                db_session, new_uid.account.namespace, new_uid.message)
            new_uid.message.thread_order = 0
        else:
            # FIXME: arbitrarily select the first thread. This shouldn't
            # be a problem now but it could become one if we choose
            # to implement thread-splitting.
            parent_thread = parent_threads[0]
            parent_thread.messages.append(new_uid.message)
            constructed_thread = thread_messages(parent_thread.messages)
            for index, message in enumerate(constructed_thread):
                message.thread_order = index

        # FIXME: refactor 'new_labels' name. This is generic IMAP, not
        # gmail.
        # make sure this thread has all the correct labels
        new_labels = account.update_thread_labels(new_uid.message.thread,
                                                  folder.name,
                                                  [folder.canonical_name],
                                                  db_session)

        # Reconciliation for Drafts, Sent Mail folders:
        if (('draft' in new_labels or 'sent' in new_labels) and not
                created and new_uid.message.inbox_uid):
            reconcile_message(db_session, log, new_uid.message.inbox_uid,
                              new_uid.message)

        new_uid.update_imap_flags(flags)

        return new_uid
Exemple #11
0
def create_imap_message(db_session, account, folder, msg):
    """
    IMAP-specific message creation logic.

    Returns
    -------
    imapuid : inbox.models.backends.imap.ImapUid
        New db object, which links to new Message and Block objects through
        relationships. All new objects are uncommitted.

    """
    log.debug("creating message",
              account_id=account.id,
              folder_name=folder.name,
              mid=msg.uid)
    new_message = Message.create_from_synced(
        account=account,
        mid=msg.uid,
        folder_name=folder.name,
        received_date=msg.internaldate,
        body_string=msg.body,
    )

    # Check to see if this is a copy of a message that was first created
    # by the Nylas API. If so, don't create a new object; just use the old one.
    existing_copy = reconcile_message(new_message, db_session)
    if existing_copy is not None:
        new_message = existing_copy

    imapuid = ImapUid(account=account,
                      folder=folder,
                      msg_uid=msg.uid,
                      message=new_message)
    imapuid.update_flags(msg.flags)
    if msg.g_labels is not None:
        imapuid.update_labels(msg.g_labels)

    # Update the message's metadata
    with db_session.no_autoflush:
        is_draft = imapuid.is_draft and (folder.canonical_name == "drafts"
                                         or folder.canonical_name == "all")
        update_message_metadata(db_session, account, new_message, is_draft)

    update_contacts_from_message(db_session, new_message, account.namespace.id)

    return imapuid