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'
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
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
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
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
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
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
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