Exemple #1
0
def add_gmail_attrs(db_session, log, new_uid, flags, folder_name, g_thrid,
                    g_msgid, g_labels, created):
    """ Gmail-specific post-create-message bits."""

    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)

    # NOTE: This code _requires_ autoflush=True, otherwise duplicate
    # threads may attempt to be created and crash.
    thread = new_uid.message.thread = ImapThread.from_gmail_message(
        db_session, new_uid.imapaccount.namespace, new_uid.message)
    # make sure this thread has all the correct labels
    existing_labels = {l.folder_name.lower() for l in thread.folders}
    # convert things like \Inbox -> Inbox, \Important -> Important
    # also, gmail labels are case-insensitive
    new_labels = {l.lstrip('\\').lower() for l in g_labels} | \
        {folder_name.lower()}
    # remove labels that have been deleted -- note that the \Sent label is
    # per-message, not per-thread, but since we always work at the thread
    # level, _we_ apply the label to the whole thread. same goes for
    # \Important.
    thread.folders = [l for l in thread.folders if l.folder_name in new_labels
                      or l.folder_name in ('sent', 'important')]
    # canonicalize "All Mail" to be "archive" in Inbox's data representation
    if new_uid.imapaccount.archive_folder_name:
        archive_folder_name = new_uid.imapaccount.archive_folder_name.lower()
        if archive_folder_name in new_labels:
            new_labels.remove(archive_folder_name)
            new_labels.add('archive')
    # add new labels
    for label in new_labels:
        if label not in existing_labels:
            item = FolderItem(thread=thread, folder_name=label)
            db_session.add(item)

    # Reconciliation for Sent Mail folder:
    if '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 #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."""

    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)

    # If we don't disable autoflush here, the thread query may flush a
    # message to the database with a NULL thread_id, causing a crash.
    with db_session.no_autoflush:
        thread = new_uid.message.thread = ImapThread.from_gmail_message(
            db_session, new_uid.imapaccount.namespace, new_uid.message)

    # make sure this thread has all the correct labels
    existing_labels = {folder.name.lower() for folder in thread.folders}
    # convert things like \Inbox -> Inbox, \Important -> Important
    new_labels = {l.lstrip('\\') for l in g_labels} | {folder.name}
    # The IMAP folder name for the inbox on Gmail is INBOX, but there's ALSO a
    # flag called '\Inbox' on all messages in it... that only appears when you
    # look at the message with a folder OTHER than INBOX selected.  Standardize
    # on keeping \Inbox in our database.
    if 'Inbox' in new_labels or 'INBOX' in new_labels:
        new_labels.discard('INBOX')
        new_labels.discard('Inbox')
        new_labels.add('Inbox')
    # NOTE: Gmail labels are case-insensitive, though we store them in the
    # original case in the db to not confuse users when displayed.
    new_labels_ci = {l.lower() for l in new_labels}

    # Remove labels that have been deleted -- note that the \Inbox, \Sent,
    # \Important, and \Drafts labels are per-message, not per-thread, but since
    # we always work at the thread level, _we_ apply the label to the whole
    # thread.
    thread.folders = {folder for folder in thread.folders if
                      folder.name.lower() in new_labels_ci or
                      folder.name.lower() in ('inbox', 'sent', 'drafts',
                                              'important')}

    # add new labels
    for label in new_labels:
        if label.lower() not in existing_labels:
            # The problem here is that Gmail's attempt to squash labels and
            # IMAP folders into the same abstraction doesn't work perfectly. In
            # particular, there is a '[Gmail]/Sent' folder, but *also* a 'Sent'
            # label, and so on. We handle this by only maintaining one folder
            # object that encapsulates both of these.
            if label == 'Sent':
                thread.folders.add(thread.namespace.account.sent_folder)
            elif label == 'Draft':
                thread.folders.add(thread.namespace.account.drafts_folder)
            elif label == 'Starred':
                thread.folders.add(thread.namespace.account.starred_folder)
            elif label == 'Important':
                thread.folders.add(thread.namespace.account.important_folder)
            else:
                folder = Folder.find_or_create(db_session,
                                               thread.namespace.account,
                                               label)
                thread.folders.add(folder)

    # Reconciliation for Sent Mail folder:
    if ('sent' in new_labels_ci and not created and
            new_uid.message.inbox_uid):
        if not thread.id:
            db_session.flush()
        reconcile_gmail_message(db_session, log, new_uid.message.inbox_uid,
                                new_uid.message, thread.id, g_thrid)

    return new_uid
Exemple #3
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."""

    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)

    # If we don't disable autoflush here, the thread query may flush a
    # message to the database with a NULL thread_id, causing a crash.
    with db_session.no_autoflush:
        thread = new_uid.message.thread = ImapThread.from_gmail_message(
            db_session, new_uid.imapaccount.namespace, new_uid.message)

    # make sure this thread has all the correct labels
    existing_labels = {folder.name.lower() for folder in thread.folders}
    # convert things like \Inbox -> Inbox, \Important -> Important
    new_labels = {l.lstrip('\\') for l in g_labels} | {folder.name}
    # The IMAP folder name for the inbox on Gmail is INBOX, but there's ALSO a
    # flag called '\Inbox' on all messages in it... that only appears when you
    # look at the message with a folder OTHER than INBOX selected.  Standardize
    # on keeping \Inbox in our database.
    if 'Inbox' in new_labels or 'INBOX' in new_labels:
        new_labels.discard('INBOX')
        new_labels.discard('Inbox')
        new_labels.add('Inbox')
    # NOTE: Gmail labels are case-insensitive, though we store them in the
    # original case in the db to not confuse users when displayed.
    new_labels_ci = {l.lower() for l in new_labels}

    # Remove labels that have been deleted -- note that the \Inbox, \Sent,
    # \Important, and \Drafts labels are per-message, not per-thread, but since
    # we always work at the thread level, _we_ apply the label to the whole
    # thread.
    thread.folders = {folder for folder in thread.folders if
                      folder.name.lower() in new_labels_ci or
                      folder.name.lower() in ('inbox', 'sent', 'drafts',
                                              'important')}

    # add new labels
    for label in new_labels:
        if label.lower() not in existing_labels:
            # The problem here is that Gmail's attempt to squash labels and
            # IMAP folders into the same abstraction doesn't work perfectly. In
            # particular, there is a '[Gmail]/Sent' folder, but *also* a 'Sent'
            # label, and so on. We handle this by only maintaining one folder
            # object that encapsulates both of these.
            if label == 'Sent':
                thread.folders.add(thread.namespace.account.sent_folder)
            elif label == 'Draft':
                thread.folders.add(thread.namespace.account.drafts_folder)
            elif label == 'Starred':
                thread.folders.add(thread.namespace.account.starred_folder)
            elif label == 'Important':
                thread.folders.add(thread.namespace.account.important_folder)
            else:
                folder = Folder.find_or_create(db_session,
                                               thread.namespace.account,
                                               label)
                thread.folders.add(folder)

    # Reconciliation for Sent Mail folder:
    if ('sent' in new_labels_ci and not created and
            new_uid.message.inbox_uid):
        if not thread.id:
            db_session.flush()
        reconcile_gmail_message(db_session, log, new_uid.message.inbox_uid,
                                new_uid.message, thread.id, g_thrid)

    return new_uid