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 test_delete_remote_draft(db, api_client): from inbox.models.message import Message # Non-Inbox created draft, therefore don't set inbox_uid message = Message() message.namespace_id = NAMESPACE_ID message.thread_id = 1 message.received_date = datetime.utcnow() message.size = len('') message.is_draft = True message.is_read = True message.sanitized_body = '' message.snippet = '' db.session.add(message) db.session.commit() drafts = api_client.get_data('/drafts') assert len(drafts) == 1 public_id = drafts[0]['id'] version = drafts[0]['version'] assert public_id == message.public_id and version == message.version api_client.delete('/drafts/{}'.format(public_id), {'version': version}) # Check that drafts were deleted drafts = api_client.get_data('/drafts') assert not drafts
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(account=account, mid=msg.uid, folder_name=folder.name, received_date=msg.internaldate, flags=msg.flags, body_string=msg.body) imapuid = ImapUid(account=account, folder=folder, msg_uid=msg.uid, message=new_msg) imapuid.update_imap_flags(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.id) # NOTE: This might be a good place to add FolderItem entries for # non-Gmail backends. return imapuid
def test_message_body_storage(config, sample_input, encrypt): message = Message() config["ENCRYPT_SECRETS"] = encrypt message.body = None assert message._compacted_body is None message.body = sample_input assert message._compacted_body.startswith( (b"\x01" if encrypt else b"\x00") + b"\x00\x00\x00\x00" ) assert message.body == sample_input
def test_file_transactions(db, default_namespace): from inbox.models.message import Message account = default_namespace.account thread = add_fake_thread(db.session, default_namespace.id) mime_msg = mime.create.multipart('mixed') mime_msg.append( mime.create.text('plain', 'This is a message with attachments'), mime.create.attachment('image/png', 'filler', 'attached_image.png', 'attachment'), mime.create.attachment('application/pdf', 'filler', 'attached_file.pdf', 'attachment')) msg = Message.create_from_synced(account, 22, '[Gmail]/All Mail', datetime.utcnow(), mime_msg.to_string()) msg.thread = thread db.session.add(msg) db.session.commit() assert len(msg.parts) == 2 assert all(part.content_disposition == 'attachment' for part in msg.parts) block_ids = [part.block.id for part in msg.parts] with db.session.no_autoflush: transaction = get_latest_transaction(db.session, 'file', block_ids[0], default_namespace.id) assert transaction.command == 'insert' transaction = get_latest_transaction(db.session, 'file', block_ids[1], default_namespace.id) assert transaction.command == 'insert'
def test_file_transactions(db, default_namespace): from inbox.models.message import Message account = default_namespace.account thread = add_fake_thread(db.session, default_namespace.id) mime_msg = mime.create.multipart("mixed") mime_msg.append( mime.create.text("plain", "This is a message with attachments"), mime.create.attachment("image/png", "filler", "attached_image.png", "attachment"), mime.create.attachment("application/pdf", "filler", "attached_file.pdf", "attachment"), ) msg = Message.create_from_synced(account, 22, "[Gmail]/All Mail", datetime.utcnow(), mime_msg.to_string()) msg.thread = thread db.session.add(msg) db.session.commit() assert len(msg.parts) == 2 assert all(part.content_disposition == "attachment" for part in msg.parts) block_ids = [part.block.id for part in msg.parts] with db.session.no_autoflush: transaction = get_latest_transaction(db.session, "file", block_ids[0], default_namespace.id) assert transaction.command == "insert" transaction = get_latest_transaction(db.session, "file", block_ids[1], default_namespace.id) assert transaction.command == "insert"
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_imap_flags(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 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"