def test_send_with_event(patch_smtp, api_client, example_draft, event): # Create a draft r = api_client.post_data('/drafts', example_draft) msgs = patch_smtp assert r.status_code == 200 draft_public_id = json.loads(r.data)['id'] version = json.loads(r.data)['version'] # Send the draft along with an event ID to use for invites r = api_client.post_data('/send', {'draft_id': draft_public_id, 'version': version, 'event_id': event.public_id}) assert r.status_code == 200 # Make sure one message was sent assert len(msgs) == 1 recipients, raw_msg = msgs[0] msg = mime.from_string(raw_msg) # Check the MIME body of the message to make sure the event is there parts = [] for mimepart in msg.walk(with_self=msg.content_type.is_singlepart()): format_type = mimepart.content_type.format_type subtype = mimepart.content_type.subtype parts.append((format_type, subtype)) assert ('text', 'plain') in parts assert ('text', 'html') in parts assert ('text', 'calendar') in parts
def test_contacts_updated(api_client): """Tests that draft-contact associations are properly created and updated.""" draft = {"to": [{"email": "*****@*****.**"}, {"email": "*****@*****.**"}]} r = api_client.post_data("/drafts", draft) assert r.status_code == 200 draft_id = json.loads(r.data)["id"] draft_version = json.loads(r.data)["version"] r = api_client.get_data("/[email protected]") assert len(r) == 1 updated_draft = {"to": [{"email": "*****@*****.**"}, {"email": "*****@*****.**"}], "version": draft_version} r = api_client.put_data("/drafts/{}".format(draft_id), updated_draft) assert r.status_code == 200 r = api_client.get_data("/[email protected]") assert len(r) == 1 r = api_client.get_data("/[email protected]") assert len(r) == 0 r = api_client.get_data("/[email protected]") assert len(r) == 1 # Check that contacts aren't created for garbage recipients. r = api_client.post_data("/drafts", {"to": [{"name": "who", "email": "nope"}]}) assert r.status_code == 200 r = api_client.get_data("/threads?to=nope") assert len(r) == 0 r = api_client.get_data("/contacts?filter=nope") assert len(r) == 0
def test_write_endpoints(db, setup_account, api_client, default_account): # Write operations (create, update, delete) succeed. r = api_client.post_data( '/drafts', data={ 'body': '<html><body><h2>Sea, birds and sand.</h2></body></html>' }) assert r.status_code == 200 draft_id = json.loads(r.data)['id'] endpoint = '/messages/{}'.format(setup_account['message']) r = api_client.put_data(endpoint, data={"starred": True}) assert r.status_code == 200 endpoint = '/events/{}'.format(setup_account['event']) r = api_client.delete(endpoint) assert r.status_code == 200 default_account.sync_state = 'invalid' db.session.commit() # Write operations fail with an HTTP 403. r = api_client.post_data('/labels', data={"display_name": "Neu!"}) assert r.status_code == 403 endpoint = '/threads/{}'.format(setup_account['thread']) r = api_client.put_data(endpoint, data={"starred": True}) assert r.status_code == 403 endpoint = '/drafts/{}'.format(draft_id) r = api_client.delete(endpoint) assert r.status_code == 403
def test_send_draft(db, api_client, example_draft, default_account): r = api_client.post_data('/drafts', example_draft) assert r.status_code == 200 public_id = json.loads(r.data)['id'] version = json.loads(r.data)['version'] r = api_client.post_data('/send', {'draft_id': public_id, 'version': version}) assert r.status_code == 200 draft = api_client.get_data('/drafts/{}'.format(public_id)) assert draft is not None assert draft['object'] != 'draft' with crispin_client(default_account.id, default_account.provider) as c: criteria = ['NOT DELETED', 'SUBJECT "{0}"'.format( example_draft['subject'])] c.conn.select_folder(default_account.drafts_folder.name, readonly=False) draft_uids = c.conn.search(criteria) assert not draft_uids, 'Message still in Drafts folder' c.conn.select_folder(default_account.sent_folder.name, readonly=False) sent_uids = c.conn.search(criteria) assert sent_uids, 'Message missing from Sent folder' c.conn.delete_messages(sent_uids) c.conn.expunge()
def test_quoted_printable_encoding_avoided_for_compatibility( patch_smtp, api_client): # Test that messages with long lines don't get quoted-printable encoded, # for maximum server compatibility. api_client.post_data( '/send', {'to': [{'email': '*****@*****.**'}], 'subject': 'In Catilinam', 'body': 'Etenim quid est, Catilina, quod iam amplius exspectes, si ' 'neque nox tenebris obscurare coeptus nefarios neque privata domus ' 'parietibus continere voces conjurationis tuae potest? Si ' 'illustrantur, si erumpunt omnia? Muta iam istam mentem, mihi crede! ' 'obliviscere caedis atque incendiorum. Teneris undique: luce sunt ' 'clariora nobis tua consilia omnia; quae iam mecum licet recognoscas.' ' Meministine me ante diem duodecimum Kalendas Novembres dicere in ' 'senatu, fore in armis certo die, qui dies futurus esset ante diem ' 'sextum Kalendas Novembres, C. Manlium, audaciae satellitem atque ' 'administrum tuae? Num me fefellit, Catilina, non modo res tanta, tam' ' atrox, tamque incredibilis, verum id quod multo magis admirandum, ' 'dies? '}) _, msg = patch_smtp[-1] parsed = mime.from_string(msg) assert len(parsed.parts) == 2 for part in parsed.parts: if part.content_type.value == 'text/html': assert part.content_encoding[0] == 'base64' elif part.content_type.value == 'text/plain': assert part.content_encoding[0] in ('7bit', 'base64')
def test_api_get(db, api_client, calendar): e_data = {'title': 'subj', 'when': {'time': 1}, 'calendar_id': calendar.public_id, 'location': 'InboxHQ'} e_data2 = {'title': 'subj2', 'when': {'time': 1}, 'calendar_id': calendar.public_id, 'location': 'InboxHQ'} api_client.post_data('/events', e_data) api_client.post_data('/events', e_data2) event_list = api_client.get_data('/events') event_ids = [event['id'] for event in event_list] c1found = False c2found = False for c_id in event_ids: event = api_client.get_data('/events/' + c_id) if event['title'] == 'subj': c1found = True if event['title'] == 'subj2': c2found = True assert c1found assert c2found
def test_api_list(db, api_client, calendar): e_data = {'title': 'subj', 'description': 'body1', 'calendar_id': calendar.public_id, 'when': {'time': 1}, 'location': 'InboxHQ'} e_data2 = {'title': 'subj2', 'description': 'body2', 'calendar_id': calendar.public_id, 'when': {'time': 1}, 'location': 'InboxHQ'} api_client.post_data('/events', e_data) api_client.post_data('/events', e_data2) event_list = api_client.get_data('/events') event_titles = [event['title'] for event in event_list] assert 'subj' in event_titles assert 'subj2' in event_titles event_descriptions = [event['description'] for event in event_list] assert 'body1' in event_descriptions assert 'body2' in event_descriptions event_ids = [event['id'] for event in event_list] for e_id in event_ids: ev = db.session.query(Event).filter_by(public_id=e_id).one() db.session.delete(ev) db.session.commit()
def test_send_rejected_without_recipients(api_client): r = api_client.post_data('/drafts', {'subject': 'Hello there'}) draft_public_id = json.loads(r.data)['id'] version = json.loads(r.data)['version'] r = api_client.post_data('/send', {'draft_id': draft_public_id, 'version': version}) assert r.status_code == 400
def test_multisend_init_rejected_with_existing_draft(api_client, example_draft): r = api_client.post_data('/drafts', example_draft) draft_public_id = json.loads(r.data)['id'] version = json.loads(r.data)['version'] r = api_client.post_data('/send-multiple', {'draft_id': draft_public_id, 'version': version}) assert r.status_code == 400
def test_invalid_timestamp(api_client, default_namespace): # Valid UNIX timestamp response = api_client.post_data( '/delta/generate_cursor', data={'start': int(time.time())}) assert response.status_code == 200 # Invalid timestamp response = api_client.post_data( '/delta/generate_cursor', data={'start': 1434591487647}) assert response.status_code == 400
def test_create_event(db, api_client, calendar): e_data = {'title': 'subj', 'description': 'body1', 'calendar_id': calendar.public_id, 'when': {'time': 1}, 'location': 'InboxHQ'} e_data2 = {'title': 'subj2', 'description': 'body2', 'calendar_id': calendar.public_id, 'when': {'time': 1}, 'location': 'InboxHQ'} api_client.post_data('/events', e_data) api_client.post_data('/events', e_data2) db.session.commit()
def test_sent_messages_shown_in_delta(patch_smtp, api_client, example_draft): ts = int(time.time()) r = api_client.post_data('/delta/generate_cursor', {'start': ts}) cursor = json.loads(r.data)['cursor'] r = api_client.post_data('/send', example_draft) message_id = json.loads(r.data)['id'] deltas = api_client.get_data('/delta?cursor={}'.format(cursor))['deltas'] message_delta = next((d for d in deltas if d['id'] == message_id), None) assert message_delta is not None assert message_delta['object'] == 'message' assert message_delta['event'] == 'create'
def test_sending_from_email_alias(patch_smtp, api_client): api_client.post_data('/send', {'to': [{'email': '*****@*****.**'}], 'from': [{'name': 'admin', 'email': '*****@*****.**'}], 'subject': 'Banalities', 'body': '<html>Hello there</html>'}) _, msg = patch_smtp[-1] parsed = mime.from_string(msg) assert 'From' in parsed.headers assert parsed.headers['From'] == 'admin <*****@*****.**>'
def test_get_all_drafts(api_client, example_draft): r = api_client.post_data("/drafts", example_draft) first_public_id = json.loads(r.data)["id"] r = api_client.post_data("/drafts", example_draft) second_public_id = json.loads(r.data)["id"] drafts = api_client.get_data("/drafts") assert len(drafts) == 2 assert first_public_id != second_public_id assert {first_public_id, second_public_id} == {draft["id"] for draft in drafts} assert all(item["object"] == "draft" for item in drafts)
def test_reply_headers_set(db, patch_smtp, api_client, example_draft, thread, message): message.message_id_header = '<*****@*****.**>' db.session.commit() thread_id = api_client.get_data('/threads')[0]['id'] api_client.post_data('/send', {'to': [{'email': '*****@*****.**'}], 'thread_id': thread_id}) _, msg = patch_smtp[-1] parsed = mime.from_string(msg) assert 'In-Reply-To' in parsed.headers assert 'References' in parsed.headers
def test_get_all_drafts(api_client, example_draft): r = api_client.post_data('/drafts', example_draft) first_public_id = json.loads(r.data)['id'] r = api_client.post_data('/drafts', example_draft) second_public_id = json.loads(r.data)['id'] drafts = api_client.get_data('/drafts') assert len(drafts) == 2 assert first_public_id != second_public_id assert {first_public_id, second_public_id} == {draft['id'] for draft in drafts} assert all(item['object'] == 'draft' for item in drafts)
def test_delete_draft(api_client, thread, message): original_draft = { 'subject': 'parent draft', 'body': 'parent draft' } r = api_client.post_data('/drafts', original_draft) draft_public_id = json.loads(r.data)['id'] version = json.loads(r.data)['version'] updated_draft = { 'subject': 'updated draft', 'body': 'updated draft', 'version': version } r = api_client.put_data('/drafts/{}'.format(draft_public_id), updated_draft) updated_public_id = json.loads(r.data)['id'] updated_version = json.loads(r.data)['version'] r = api_client.delete('/drafts/{}'.format(updated_public_id), {'version': updated_version}) # Check that drafts were deleted drafts = api_client.get_data('/drafts') assert not drafts # Check that no orphaned threads are around threads = api_client.get_data('/threads?subject=parent%20draft') assert not threads threads = api_client.get_data('/threads?subject=updated%20draft') assert not threads # And check that threads aren't deleted if they still have messages. thread_public_id = api_client.get_data('/threads')[0]['id'] reply_draft = { 'subject': 'test reply', 'body': 'test reply', 'thread_id': thread_public_id } r = api_client.post_data('/drafts', reply_draft) public_id = json.loads(r.data)['id'] version = json.loads(r.data)['version'] thread = api_client.get_data('/threads/{}'.format(thread_public_id)) assert len(thread['draft_ids']) > 0 api_client.delete('/drafts/{}'.format(public_id), {'version': version}) thread = api_client.get_data('/threads/{}'.format(thread_public_id)) assert thread assert len(thread['draft_ids']) == 0
def label_client(db, gmail_account): api_client = new_api_client(db, gmail_account.namespace) # Whereas calling generic_account always makes a new IMAP account, # calling gmail_account checks first to see if there's an existing # Gmail account and uses it if so. This can cause namespace # conflicts if a label is "created" more than once. Since # labels can't be deleted and then re-created, this fixture only # makes a new label if there are no existing labels. g_data = api_client.get_raw('/labels/') if not json.loads(g_data.data): api_client.post_data('/labels/', {"display_name": "Test_Label"}) return api_client
def test_api_pessimistic_update(db, api_client, calendar, default_account): e_data = { 'title': '', 'calendar_id': calendar.public_id, 'when': {'time': 1407542195}, } e_resp = api_client.post_data('/events', e_data, headers={ "Api-Version": API_VERSIONS[1] }) e_resp_data = json.loads(e_resp.data) assert e_resp_data['object'] == 'event' assert e_resp_data['account_id'] == default_account.namespace.public_id assert e_resp_data['title'] == e_data['title'] assert e_resp_data['when']['time'] == e_data['when']['time'] assert 'id' in e_resp_data e_id = e_resp_data['id'] e_update_data = {'title': 'new title'} e_put_resp = api_client.put_data('/events/' + e_id, e_update_data, headers={ "Api-Version": API_VERSIONS[1] }) e_put_data = json.loads(e_put_resp.data) assert e_put_data['object'] == 'event' assert e_put_data['account_id'] == default_account.namespace.public_id assert e_put_data['id'] == e_id assert e_put_data['title'] == '' assert e_put_data['when']['object'] == 'time' assert e_put_data['when']['time'] == e_data['when']['time']
def test_drafts_filter(api_client, example_draft): r = api_client.post_data("/drafts", example_draft) thread_id = json.loads(r.data)["thread_id"] reply_draft = {"subject": "test reply", "body": "test reply", "thread_id": thread_id} r = api_client.post_data("/drafts", reply_draft) _filter = "?thread_id=0000000000000000000000000" results = api_client.get_data("/drafts" + _filter) assert len(results) == 0 results = api_client.get_data("/drafts?thread_id={}".format(thread_id)) assert len(results) == 2 results = api_client.get_data("/drafts?offset={}&thread_id={}".format(1, thread_id)) assert len(results) == 1
def test_api_create(db, api_client, calendar, default_account): e_data = { "title": "Friday Office Party", "calendar_id": calendar.public_id, "when": { "time": 1407542195 }, "location": "Nylas HQ", } e_resp = api_client.post_data("/events", e_data) e_resp_data = json.loads(e_resp.data) assert e_resp_data["object"] == "event" assert e_resp_data["account_id"] == default_account.namespace.public_id assert e_resp_data["title"] == e_data["title"] assert e_resp_data["location"] == e_data["location"] assert e_resp_data["when"]["time"] == e_data["when"]["time"] assert "id" in e_resp_data e_id = e_resp_data["id"] e_get_resp = api_client.get_data("/events/" + e_id) assert e_get_resp["object"] == "event" assert e_get_resp["account_id"] == default_account.namespace.public_id assert e_get_resp["id"] == e_id assert e_get_resp["title"] == e_data["title"] assert e_get_resp["when"]["time"] == e_data["when"]["time"]
def test_update_draft(api_client): with freeze_time(datetime.now()) as freezer: original_draft = {"subject": "original draft", "body": "parent draft"} r = api_client.post_data("/drafts", original_draft) draft_public_id = json.loads(r.data)["id"] version = json.loads(r.data)["version"] assert version == 0 freezer.tick() updated_draft = {"subject": "updated draft", "body": "updated draft", "version": version} r = api_client.put_data("/drafts/{}".format(draft_public_id), updated_draft) updated_public_id = json.loads(r.data)["id"] updated_version = json.loads(r.data)["version"] assert updated_public_id == draft_public_id assert updated_version > 0 drafts = api_client.get_data("/drafts") assert len(drafts) == 1 assert drafts[0]["id"] == updated_public_id # Check that the thread is updated too. thread = api_client.get_data("/threads/{}".format(drafts[0]["thread_id"])) assert thread["subject"] == "updated draft" assert thread["first_message_timestamp"] == drafts[0]["date"] assert thread["last_message_timestamp"] == drafts[0]["date"]
def test_api_create_multiple(db, api_client, calendar): e_data = { 'title': 'Friday Office Party', 'when': {'time': 1407542195}, 'calendar_id': calendar.public_id, 'participants': [{ 'email': '*****@*****.**', }, { 'email': '*****@*****.**', }] } e_resp = api_client.post_data('/events', e_data) e_resp_data = json.loads(e_resp.data) assert len(e_resp_data['participants']) == 2 for participant in e_resp_data['participants']: res = [e for e in e_data['participants'] if e['email'] == participant['email']] assert len(res) == 1 participant0 = e_resp_data['participants'][0] participant1 = e_resp_data['participants'][1] assert participant0['name'] is None assert participant0['status'] == 'noreply' assert participant1['name'] is None assert participant1['status'] == 'noreply'
def test_api_pessimistic_update(db, api_client, calendar, default_account): e_data = { "title": "", "calendar_id": calendar.public_id, "when": { "time": 1407542195 }, } e_resp = api_client.post_data("/events", e_data, headers={"Api-Version": API_VERSIONS[1]}) e_resp_data = json.loads(e_resp.data) assert e_resp_data["object"] == "event" assert e_resp_data["account_id"] == default_account.namespace.public_id assert e_resp_data["title"] == e_data["title"] assert e_resp_data["when"]["time"] == e_data["when"]["time"] assert "id" in e_resp_data e_id = e_resp_data["id"] e_update_data = {"title": "new title"} e_put_resp = api_client.put_data("/events/" + e_id, e_update_data, headers={"Api-Version": API_VERSIONS[1]}) e_put_data = json.loads(e_put_resp.data) assert e_put_data["object"] == "event" assert e_put_data["account_id"] == default_account.namespace.public_id assert e_put_data["id"] == e_id assert e_put_data["title"] == "" assert e_put_data["when"]["object"] == "time" assert e_put_data["when"]["time"] == e_data["when"]["time"]
def test_update_draft(api_client): with freeze_time(datetime.now()) as freezer: original_draft = {"subject": "original draft", "body": "parent draft"} r = api_client.post_data("/drafts", original_draft) draft_public_id = json.loads(r.data)["id"] version = json.loads(r.data)["version"] assert version == 0 freezer.tick() updated_draft = { "subject": "updated draft", "body": "updated draft", "version": version, } r = api_client.put_data("/drafts/{}".format(draft_public_id), updated_draft) updated_public_id = json.loads(r.data)["id"] updated_version = json.loads(r.data)["version"] assert updated_public_id == draft_public_id assert updated_version > 0 drafts = api_client.get_data("/drafts") assert len(drafts) == 1 assert drafts[0]["id"] == updated_public_id # Check that the thread is updated too. thread = api_client.get_data("/threads/{}".format( drafts[0]["thread_id"])) assert thread["subject"] == "updated draft" assert thread["first_message_timestamp"] == drafts[0]["date"] assert thread["last_message_timestamp"] == drafts[0]["date"]
def test_malformed_subject_rejected(api_client, example_draft_bad_subject): r = api_client.post_data('/send', example_draft_bad_subject) assert r.status_code == 400 decoded = json.loads(r.get_data()) assert decoded['type'] == 'invalid_request_error' assert decoded['message'] == '"subject" should be a string'
def test_multisend_handle_recipients_rejected(recipients_refused, api_client, multisend, patch_crispin_del_sent): r = api_client.post_data('/send-multiple/' + multisend['id'], multisend['send_req']) assert r.status_code == 402 assert json.loads(r.data)['message'] == 'Sending to all recipients failed'
def test_account_validation(api_client, db, default_namespace): draft = {'body': '<html><body><h2>Sea, birds and sand.</h2></body></html>'} r = api_client.post_data('/drafts', draft) assert r.status_code == 200 namespace_id = json.loads(r.data)['account_id'] account = db.session.query(Namespace).filter( Namespace.public_id == namespace_id).first().account account.sync_state = 'invalid' db.session.commit() r = api_client.post_data('/drafts', draft) assert r.status_code == 403
def test_attachment_has_same_id(api_client, uploaded_file_ids, draft): attachment_id = uploaded_file_ids.pop() draft['file_ids'] = [attachment_id] r = api_client.post_data('/drafts', draft) assert r.status_code == 200 draft_resp = json.loads(r.data) assert attachment_id in [x['id'] for x in draft_resp['files']]
def test_conflicting_updates(api_client): original_draft = {'subject': 'parent draft', 'body': 'parent draft'} r = api_client.post_data('/drafts', original_draft) original_public_id = json.loads(r.data)['id'] version = json.loads(r.data)['version'] updated_draft = { 'subject': 'updated draft', 'body': 'updated draft', 'version': version } r = api_client.put_data('/drafts/{}'.format(original_public_id), updated_draft) assert r.status_code == 200 updated_public_id = json.loads(r.data)['id'] updated_version = json.loads(r.data)['version'] assert updated_version != version conflicting_draft = { 'subject': 'conflicting draft', 'body': 'conflicting draft', 'version': version } r = api_client.put_data('/drafts/{}'.format(original_public_id), conflicting_draft) assert r.status_code == 409 drafts = api_client.get_data('/drafts') assert len(drafts) == 1 assert drafts[0]['id'] == updated_public_id
def test_update_draft(api_client): with freeze_time(datetime.now()) as freezer: original_draft = {'subject': 'original draft', 'body': 'parent draft'} r = api_client.post_data('/drafts', original_draft) draft_public_id = json.loads(r.data)['id'] version = json.loads(r.data)['version'] assert version == 0 freezer.tick() updated_draft = { 'subject': 'updated draft', 'body': 'updated draft', 'version': version } r = api_client.put_data('/drafts/{}'.format(draft_public_id), updated_draft) updated_public_id = json.loads(r.data)['id'] updated_version = json.loads(r.data)['version'] assert updated_public_id == draft_public_id assert updated_version > 0 drafts = api_client.get_data('/drafts') assert len(drafts) == 1 assert drafts[0]['id'] == updated_public_id # Check that the thread is updated too. thread = api_client.get_data('/threads/{}'.format( drafts[0]['thread_id'])) assert thread['subject'] == 'updated draft' assert thread['first_message_timestamp'] == drafts[0]['date'] assert thread['last_message_timestamp'] == drafts[0]['date']
def test_api_create(db, api_client, calendar): e_data = { 'title': 'Friday Office Party', 'when': {'time': 1407542195}, 'calendar_id': calendar.public_id, 'participants': [{ 'name': 'alyssa p. hacker', 'email': '*****@*****.**' }] } e_resp = api_client.post_data('/events', e_data) e_resp_data = json.loads(e_resp.data) assert len(e_resp_data['participants']) == 1 participant = e_resp_data['participants'][0] assert participant['name'] == e_data['participants'][0]['name'] assert participant['email'] == e_data['participants'][0]['email'] assert participant['status'] == 'noreply' e_resp_data = api_client.get_data('/events/' + e_resp_data['id']) assert len(e_resp_data['participants']) == 1 participant = e_resp_data['participants'][0] assert participant['name'] == e_data['participants'][0]['name'] assert participant['email'] == e_data['participants'][0]['email'] assert participant['status'] == 'noreply'
def test_conflicting_updates(api_client): original_draft = {"subject": "parent draft", "body": "parent draft"} r = api_client.post_data("/drafts", original_draft) original_public_id = json.loads(r.data)["id"] version = json.loads(r.data)["version"] updated_draft = { "subject": "updated draft", "body": "updated draft", "version": version, } r = api_client.put_data("/drafts/{}".format(original_public_id), updated_draft) assert r.status_code == 200 updated_public_id = json.loads(r.data)["id"] updated_version = json.loads(r.data)["version"] assert updated_version != version conflicting_draft = { "subject": "conflicting draft", "body": "conflicting draft", "version": version, } r = api_client.put_data("/drafts/{}".format(original_public_id), conflicting_draft) assert r.status_code == 409 drafts = api_client.get_data("/drafts") assert len(drafts) == 1 assert drafts[0]["id"] == updated_public_id
def test_reply_headers_set(db, patch_smtp, api_client, example_draft, thread, message): message.message_id_header = '<*****@*****.**>' db.session.commit() thread_id = api_client.get_data('/threads')[0]['id'] api_client.post_data('/send', { 'to': [{ 'email': '*****@*****.**' }], 'thread_id': thread_id }) _, msg = patch_smtp[-1] parsed = mime.from_string(msg) assert 'In-Reply-To' in parsed.headers assert 'References' in parsed.headers
def test_contacts_updated(api_client): """Tests that draft-contact associations are properly created and updated.""" draft = { 'to': [{'email': '*****@*****.**'}, {'email': '*****@*****.**'}] } r = api_client.post_data('/drafts', draft) assert r.status_code == 200 draft_id = json.loads(r.data)['id'] draft_version = json.loads(r.data)['version'] r = api_client.get_data('/[email protected]') assert len(r) == 1 updated_draft = { 'to': [{'email': '*****@*****.**'}, {'email': '*****@*****.**'}], 'version': draft_version } r = api_client.put_data('/drafts/{}'.format(draft_id), updated_draft) assert r.status_code == 200 r = api_client.get_data('/[email protected]') assert len(r) == 1 r = api_client.get_data('/[email protected]') assert len(r) == 0 r = api_client.get_data('/[email protected]') assert len(r) == 1
def test_api_pessimistic_delete(db, api_client, calendar, default_account): e_data = { "title": "", "calendar_id": calendar.public_id, "when": { "time": 1407542195 }, } e_resp = api_client.post_data("/events", e_data, headers={"Api-Version": API_VERSIONS[1]}) e_resp_data = json.loads(e_resp.data) assert e_resp_data["object"] == "event" assert e_resp_data["title"] == e_data["title"] assert e_resp_data["when"]["time"] == e_data["when"]["time"] assert "id" in e_resp_data e_id = e_resp_data["id"] e_delete_resp = api_client.delete("/events/" + e_id, headers={"Api-Version": API_VERSIONS[1]}) assert e_delete_resp.status_code == 200 e_resp = api_client.get_data("/events/" + e_id) assert e_resp["status"] == "confirmed"
def test_conflicting_updates(api_client): original_draft = { 'subject': 'parent draft', 'body': 'parent draft' } r = api_client.post_data('/drafts', original_draft) original_public_id = json.loads(r.data)['id'] version = json.loads(r.data)['version'] updated_draft = { 'subject': 'updated draft', 'body': 'updated draft', 'version': version } r = api_client.put_data('/drafts/{}'.format(original_public_id), updated_draft) assert r.status_code == 200 updated_public_id = json.loads(r.data)['id'] updated_version = json.loads(r.data)['version'] assert updated_version != version conflicting_draft = { 'subject': 'conflicting draft', 'body': 'conflicting draft', 'version': version } r = api_client.put_data('/drafts/{}'.format(original_public_id), conflicting_draft) assert r.status_code == 409 drafts = api_client.get_data('/drafts') assert len(drafts) == 1 assert drafts[0]['id'] == updated_public_id
def test_api_remove_participant(db, api_client, calendar): e_data = { 'title': 'Friday Office Party', 'when': {'time': 1407542195}, 'calendar_id': calendar.public_id, 'participants': [{'email': '*****@*****.**'}, {'email': '*****@*****.**'}, {'email': '*****@*****.**'}, {'email': '*****@*****.**'}, {'email': '*****@*****.**'}] } e_resp = api_client.post_data('/events', e_data) e_resp_data = json.loads(e_resp.data) assert len(e_resp_data['participants']) == 5 for i, p in enumerate(e_resp_data['participants']): res = [e for e in e_resp_data['participants'] if e['email'] == p['email']] assert len(res) == 1 assert res[0]['name'] is None event_id = e_resp_data['id'] e_data['participants'].pop() e_resp = api_client.put_data('/events/' + event_id, e_data) e_resp_data = json.loads(e_resp.data) assert len(e_resp_data['participants']) == 4 for i, p in enumerate(e_resp_data['participants']): res = [e for e in e_resp_data['participants'] if e['email'] == p['email']] assert len(res) == 1 assert p['name'] is None
def test_attachment_has_same_id(api_client, uploaded_file_ids, draft): attachment_id = uploaded_file_ids.pop() draft["file_ids"] = [attachment_id] r = api_client.post_data("/drafts", draft) assert r.status_code == 200 draft_resp = json.loads(r.data) assert attachment_id in [x["id"] for x in draft_resp["files"]]
def test_api_create(db, api_client, calendar, default_account): e_data = { 'title': 'Friday Office Party', 'calendar_id': calendar.public_id, 'when': { 'time': 1407542195 }, 'location': 'Nylas HQ', } e_resp = api_client.post_data('/events', e_data) e_resp_data = json.loads(e_resp.data) assert e_resp_data['object'] == 'event' assert e_resp_data['account_id'] == default_account.namespace.public_id assert e_resp_data['title'] == e_data['title'] assert e_resp_data['location'] == e_data['location'] assert e_resp_data['when']['time'] == e_data['when']['time'] assert 'id' in e_resp_data e_id = e_resp_data['id'] e_get_resp = api_client.get_data('/events/' + e_id) assert e_get_resp['object'] == 'event' assert e_get_resp['account_id'] == default_account.namespace.public_id assert e_get_resp['id'] == e_id assert e_get_resp['title'] == e_data['title'] assert e_get_resp['when']['time'] == e_data['when']['time']
def test_api_update_title(db, api_client, calendar, default_account): e_data = { 'title': '', 'calendar_id': calendar.public_id, 'when': {'time': 1407542195}, } e_resp = api_client.post_data('/events', e_data) e_resp_data = json.loads(e_resp.data) assert e_resp_data['object'] == 'event' assert e_resp_data['account_id'] == default_account.namespace.public_id assert e_resp_data['title'] == e_data['title'] assert e_resp_data['when']['time'] == e_data['when']['time'] assert 'id' in e_resp_data e_id = e_resp_data['id'] e_update_data = {'title': 'new title'} e_put_resp = api_client.put_data('/events/' + e_id, e_update_data) e_put_data = json.loads(e_put_resp.data) assert e_put_data['object'] == 'event' assert e_put_data['account_id'] == default_account.namespace.public_id assert e_put_data['id'] == e_id assert e_put_data['title'] == 'new title' assert e_put_data['when']['object'] == 'time' assert e_put_data['when']['time'] == e_data['when']['time']
def test_rsvp_idempotent(db, patch_smtp, api_client, example_rsvp, imported_event, status, comment): part = imported_event.participants[0] part['status'] = status part['comment'] = comment # MutableList shenanigans -- it won't update # what's stored in the db otherwise. imported_event.participants = [] db.session.commit() imported_event.participants = [part] db.session.commit() old_update_date = imported_event.updated_at db.session.expunge(imported_event) rsvp = {'event_id': imported_event.public_id, 'status': status, 'comment': comment} r = api_client.post_data('/send-rsvp', rsvp) assert r.status_code == 200 dct = json.loads(r.data) # check that the event's status is the same. assert len(dct['participants']) == 1 assert dct['participants'][0]['email'] == '*****@*****.**' assert dct['participants'][0]['status'] == status assert dct['participants'][0]['comment'] == comment # Check that the event hasn't been updated. refreshed_event = db.session.query(Event).get(imported_event.id) assert refreshed_event.updated_at == old_update_date
def test_delete_draft(api_client, thread, message): original_draft = {"subject": "parent draft", "body": "parent draft"} r = api_client.post_data("/drafts", original_draft) draft_public_id = json.loads(r.data)["id"] version = json.loads(r.data)["version"] updated_draft = { "subject": "updated draft", "body": "updated draft", "version": version, } r = api_client.put_data("/drafts/{}".format(draft_public_id), updated_draft) updated_public_id = json.loads(r.data)["id"] updated_version = json.loads(r.data)["version"] r = api_client.delete("/drafts/{}".format(updated_public_id), {"version": updated_version}) # Check that drafts were deleted drafts = api_client.get_data("/drafts") assert not drafts # Check that no orphaned threads are around threads = api_client.get_data("/threads?subject=parent%20draft") assert not threads threads = api_client.get_data("/threads?subject=updated%20draft") assert not threads # And check that threads aren't deleted if they still have messages. thread_public_id = api_client.get_data("/threads")[0]["id"] reply_draft = { "subject": "test reply", "body": "test reply", "thread_id": thread_public_id, } r = api_client.post_data("/drafts", reply_draft) public_id = json.loads(r.data)["id"] version = json.loads(r.data)["version"] thread = api_client.get_data("/threads/{}".format(thread_public_id)) assert len(thread["draft_ids"]) > 0 api_client.delete("/drafts/{}".format(public_id), {"version": version}) thread = api_client.get_data("/threads/{}".format(thread_public_id)) assert thread assert len(thread["draft_ids"]) == 0
def test_delete_draft(api_client, thread, message): original_draft = {'subject': 'parent draft', 'body': 'parent draft'} r = api_client.post_data('/drafts', original_draft) draft_public_id = json.loads(r.data)['id'] version = json.loads(r.data)['version'] updated_draft = { 'subject': 'updated draft', 'body': 'updated draft', 'version': version } r = api_client.put_data('/drafts/{}'.format(draft_public_id), updated_draft) updated_public_id = json.loads(r.data)['id'] updated_version = json.loads(r.data)['version'] r = api_client.delete('/drafts/{}'.format(updated_public_id), {'version': updated_version}) # Check that drafts were deleted drafts = api_client.get_data('/drafts') assert not drafts # Check that no orphaned threads are around threads = api_client.get_data('/threads?subject=parent%20draft') assert not threads threads = api_client.get_data('/threads?subject=updated%20draft') assert not threads # And check that threads aren't deleted if they still have messages. thread_public_id = api_client.get_data('/threads')[0]['id'] reply_draft = { 'subject': 'test reply', 'body': 'test reply', 'thread_id': thread_public_id } r = api_client.post_data('/drafts', reply_draft) public_id = json.loads(r.data)['id'] version = json.loads(r.data)['version'] thread = api_client.get_data('/threads/{}'.format(thread_public_id)) assert len(thread['draft_ids']) > 0 api_client.delete('/drafts/{}'.format(public_id), {'version': version}) thread = api_client.get_data('/threads/{}'.format(thread_public_id)) assert thread assert len(thread['draft_ids']) == 0
def test_multisend_handle_invalid_credentials(disallow_auth, api_client, multisend, patch_crispin_del_sent): r = api_client.post_data('/send-multiple/' + multisend['id'], multisend['send_req']) assert r.status_code == 403 assert json.loads(r.data)['message'] == 'Could not authenticate with ' \ 'the SMTP server.'
def test_multisend_handle_server_disconnected(connection_closed, api_client, multisend, patch_crispin_del_sent): r = api_client.post_data('/send-multiple/' + multisend['id'], multisend['send_req']) assert r.status_code == 503 assert json.loads(r.data)['message'] == 'The server unexpectedly closed ' \ 'the connection'
def test_multisend_message_rejected_for_security(insecure_content, api_client, multisend, patch_crispin_del_sent): r = api_client.post_data('/send-multiple/' + multisend['id'], multisend['send_req']) assert r.status_code == 402 assert json.loads(r.data)['message'] == 'Message content rejected ' \ 'for security reasons'
def test_multisend_handle_server_disconnected(connection_closed, api_client, multisend, patch_crispin_del_sent): r = api_client.post_data("/send-multiple/" + multisend["id"], multisend["send_req"]) assert r.status_code == 503 assert (json.loads(r.data)["message"] == "The server unexpectedly closed " "the connection")
def test_multisend_message_rejected_for_security(insecure_content, api_client, multisend, patch_crispin_del_sent): r = api_client.post_data("/send-multiple/" + multisend["id"], multisend["send_req"]) assert r.status_code == 402 assert (json.loads(r.data)["message"] == "Message content rejected " "for security reasons")
def test_smtp_ssl_verification_bad_cert(db, bad_cert_smtp_server, example_draft, local_smtp_account, api_client, patched_smtp): api_client = new_api_client(db, local_smtp_account.namespace) gevent.sleep(0.2) # let SMTP daemon start up r = api_client.post_data('/send', example_draft) assert r.status_code == 200
def test_malformed_body_rejected(api_client, example_draft_bad_body): r = api_client.post_data("/send", example_draft_bad_body) assert r.status_code == 400 decoded = json.loads(r.get_data()) assert decoded["type"] == "invalid_request_error" assert decoded["message"] == '"body" should be a string'
def test_multisend_init_malformed_subject_rejected(api_client, example_draft_bad_subject): r = api_client.post_data("/send-multiple", example_draft_bad_subject) assert r.status_code == 400 decoded = json.loads(r.get_data()) assert decoded["type"] == "invalid_request_error" assert decoded["message"] == '"subject" should be a string'
def test_multisend_handle_invalid_credentials(disallow_auth, api_client, multisend, patch_crispin_del_sent): r = api_client.post_data("/send-multiple/" + multisend["id"], multisend["send_req"]) assert r.status_code == 403 assert (json.loads(r.data)["message"] == "Could not authenticate with " "the SMTP server.")
def test_sending_from_email_alias(patch_smtp, api_client): api_client.post_data( '/send', { 'to': [{ 'email': '*****@*****.**' }], 'from': [{ 'name': 'admin', 'email': '*****@*****.**' }], 'subject': 'Banalities', 'body': '<html>Hello there</html>' }) _, msg = patch_smtp[-1] parsed = mime.from_string(msg) assert 'From' in parsed.headers assert parsed.headers['From'] == 'admin <*****@*****.**>'
def test_create_draft_with_attachments(api_client, attachments, example_draft): attachment_ids = [] upload_path = '/files' for filename, path in attachments: data = {'file': (open(path, 'rb'), filename)} r = api_client.post_raw(upload_path, data=data) assert r.status_code == 200 attachment_id = json.loads(r.data)[0]['id'] attachment_ids.append(attachment_id) first_attachment = attachment_ids.pop() example_draft['file_ids'] = [first_attachment] r = api_client.post_data('/drafts', example_draft) assert r.status_code == 200 returned_draft = json.loads(r.data) draft_public_id = returned_draft['id'] assert returned_draft['version'] == 0 example_draft['version'] = returned_draft['version'] assert len(returned_draft['files']) == 1 attachment_ids.append(first_attachment) example_draft['file_ids'] = attachment_ids r = api_client.put_data('/drafts/{}'.format(draft_public_id), example_draft) assert r.status_code == 200 returned_draft = json.loads(r.data) assert len(returned_draft['files']) == 3 assert returned_draft['version'] == 1 example_draft['version'] = returned_draft['version'] # Make sure we can't delete the files now for file_id in attachment_ids: r = api_client.delete('/files/{}'.format(file_id)) assert r.status_code == 400 # Now remove the attachment example_draft['file_ids'] = [first_attachment] r = api_client.put_data('/drafts/{}'.format(draft_public_id), example_draft) draft_data = api_client.get_data('/drafts/{}'.format(draft_public_id)) assert len(draft_data['files']) == 1 assert draft_data['version'] == 2 example_draft['version'] = draft_data['version'] example_draft['file_ids'] = [] r = api_client.put_data('/drafts/{}'.format(draft_public_id), example_draft) draft_data = api_client.get_data('/drafts/{}'.format(draft_public_id)) assert r.status_code == 200 assert len(draft_data['files']) == 0 assert draft_data['version'] == 3 # now that they're not attached, we should be able to delete them for file_id in attachment_ids: r = api_client.delete('/files/{}'.format(file_id)) assert r.status_code == 200
def test_invalid_input(api_client): cursor_response = api_client.post_data('/delta/generate_cursor', {'start': "I'm not a timestamp!"}) assert cursor_response.status_code == 400 sync_response = api_client.client.get( '/delta?cursor={}'.format('fake cursor'), headers=api_client.auth_header) assert sync_response.status_code == 400
def test_multisend_init_malformed_body_rejected(api_client, example_draft_bad_body): r = api_client.post_data('/send-multiple', example_draft_bad_body) assert r.status_code == 400 decoded = json.loads(r.get_data()) assert decoded['type'] == 'invalid_request_error' assert decoded['message'] == '"body" should be a string'