<s> from __future__ import absolute_import , division , print_function , unicode_literals <EOL> import json <EOL> import time <EOL> from gratipay . exceptions import CannotRemovePrimaryEmail , EmailAlreadyTaken , EmailNotVerified <EOL> from gratipay . exceptions import TooManyEmailAddresses , ResendingTooFast <EOL> from gratipay . models . participant import Participant <EOL> from gratipay . testing . emails import EmailHarness <EOL> from gratipay . utils import emails , encode_for_querystring <EOL> class TestEmail ( EmailHarness ) : <EOL> def setUp ( self ) : <EOL> EmailHarness . setUp ( self ) <EOL> self . alice = self . make_participant ( '<STR_LIT>' , claimed_time = '<STR_LIT>' ) <EOL> self . _old_threshold = self . client . website . env . resend_verification_threshold <EOL> self . client . website . env . resend_verification_threshold = '<STR_LIT>' <EOL> def tearDown ( self ) : <EOL> self . client . website . env . resend_verification_threshold = self . _old_threshold <EOL> def hit_email_spt ( self , action , address , user = '<STR_LIT>' , should_fail = False ) : <EOL> P = self . client . PxST if should_fail else self . client . POST <EOL> data = { '<STR_LIT:action>' : action , '<STR_LIT:address>' : address } <EOL> headers = { b'<STR_LIT>' : b'<STR_LIT>' } <EOL> return P ( '<STR_LIT>' , data , auth_as = user , ** headers ) <EOL> def verify_email ( self , email , nonce , username = '<STR_LIT>' , should_fail = False ) : <EOL> url = '<STR_LIT>' <EOL> url %= ( username , encode_for_querystring ( email ) , nonce ) <EOL> G = self . client . GxT if should_fail else self . client . GET <EOL> return G ( url , auth_as = username ) <EOL> def verify_and_change_email ( self , old_email , new_email , username = '<STR_LIT>' ) : <EOL> self . hit_email_spt ( '<STR_LIT>' , old_email ) <EOL> nonce = Participant . from_username ( username ) . get_email ( old_email ) . nonce <EOL> self . verify_email ( old_email , nonce ) <EOL> self . hit_email_spt ( '<STR_LIT>' , new_email ) <EOL> def test_participant_can_add_email ( self ) : <EOL> response = self . hit_email_spt ( '<STR_LIT>' , '<STR_LIT>' ) <EOL> actual = json . loads ( response . body ) <EOL> assert actual <EOL> def test_adding_email_sends_verification_email ( self ) : <EOL> self . hit_email_spt ( '<STR_LIT>' , '<STR_LIT>' ) <EOL> assert self . mailer . call_count == <NUM_LIT:1> <EOL> last_email = self . get_last_email ( ) <EOL> assert last_email [ '<STR_LIT:to>' ] == '<STR_LIT>' <EOL> expected = "<STR_LIT>" <EOL> assert expected in last_email [ '<STR_LIT>' ] <EOL> def test_email_address_is_encoded_in_sent_verification_link ( self ) : <EOL> address = '<STR_LIT>' <EOL> encoded = encode_for_querystring ( address ) <EOL> self . hit_email_spt ( '<STR_LIT>' , address ) <EOL> last_email = self . get_last_email ( ) <EOL> assert "<STR_LIT>" + encoded in last_email [ '<STR_LIT>' ] <EOL> def test_verification_email_doesnt_contain_unsubscribe ( self ) : <EOL> self . hit_email_spt ( '<STR_LIT>' , '<STR_LIT>' ) <EOL> last_email = self . get_last_email ( ) <EOL> assert "<STR_LIT>" not in last_email [ '<STR_LIT>' ] <EOL> def test_adding_second_email_sends_verification_notice ( self ) : <EOL> self . verify_and_change_email ( '<STR_LIT>' , '<STR_LIT>' ) <EOL> assert self . mailer . call_count == <NUM_LIT:3> <EOL> last_email = self . get_last_email ( ) <EOL> assert last_email [ '<STR_LIT:to>' ] == '<STR_LIT>' <EOL> expected = "<STR_LIT>" <EOL> assert expected in last_email [ '<STR_LIT>' ] <EOL> def test_post_anon_returns_403 ( self ) : <EOL> response = self . hit_email_spt ( '<STR_LIT>' , '<STR_LIT>' , user = None , should_fail = True ) <EOL> assert response . code == <NUM_LIT> <EOL> def test_post_with_no_at_symbol_is_400 ( self ) : <EOL> response = self . hit_email_spt ( '<STR_LIT>' , '<STR_LIT>' , should_fail = True ) <EOL> assert response . code == <NUM_LIT> <EOL> def test_post_with_no_period_symbol_is_400 ( self ) : <EOL> response = self . hit_email_spt ( '<STR_LIT>' , '<STR_LIT>' , should_fail = True ) <EOL> assert response . code == <NUM_LIT> <EOL> def test_verify_email_without_adding_email ( self ) : <EOL> response = self . verify_email ( '<STR_LIT>' , '<STR_LIT>' ) <EOL> assert '<STR_LIT>' in response . body <EOL> def test_verify_email_wrong_nonce ( self ) : <EOL> self . hit_email_spt ( '<STR_LIT>' , '<STR_LIT>' ) <EOL> nonce = '<STR_LIT>' <EOL> r = self . alice . verify_email ( '<STR_LIT>' , nonce ) <EOL> assert r == emails . VERIFICATION_FAILED <EOL> self . verify_email ( '<STR_LIT>' , nonce ) <EOL> expected = None <EOL> actual = Participant . from_username ( '<STR_LIT>' ) . email_address <EOL> assert expected == actual <EOL> def test_verify_email_a_second_time_returns_redundant ( self ) : <EOL> address = '<STR_LIT>' <EOL> self . hit_email_spt ( '<STR_LIT>' , address ) <EOL> nonce = self . alice . get_email ( address ) . nonce <EOL> r = self . alice . verify_email ( address , nonce ) <EOL> r = self . alice . verify_email ( address , nonce ) <EOL> assert r == emails . VERIFICATION_REDUNDANT <EOL> def test_verify_email_expired_nonce ( self ) : <EOL> address = '<STR_LIT>' <EOL> self . hit_email_spt ( '<STR_LIT>' , address ) <EOL> self . db . run ( """<STR_LIT>""" , ( self . alice . id , ) ) <EOL> nonce = self . alice . get_email ( address ) . nonce <EOL> r = self . alice . verify_email ( address , nonce ) <EOL> assert r == emails . VERIFICATION_EXPIRED <EOL> actual = Participant . from_username ( '<STR_LIT>' ) . email_address <EOL> assert actual == None <EOL> def test_verify_email ( self ) : <EOL> self . hit_email_spt ( '<STR_LIT>' , '<STR_LIT>' ) <EOL> nonce = self . alice . get_email ( '<STR_LIT>' ) . nonce <EOL> self . verify_email ( '<STR_LIT>' , nonce ) <EOL> expected = '<STR_LIT>' <EOL> actual = Participant . from_username ( '<STR_LIT>' ) . email_address <EOL> assert expected == actual <EOL> def test_email_verification_is_backwards_compatible ( self ) : <EOL> """<STR_LIT>""" <EOL> self . hit_email_spt ( '<STR_LIT>' , '<STR_LIT>' ) <EOL> nonce = self . alice . get_email ( '<STR_LIT>' ) . nonce <EOL> url = '<STR_LIT>' + nonce <EOL> self . client . GET ( url , auth_as = '<STR_LIT>' ) <EOL> expected = '<STR_LIT>' <EOL> actual = Participant . from_username ( '<STR_LIT>' ) . email_address <EOL> assert expected == actual <EOL> def test_verified_email_is_not_changed_after_update ( self ) : <EOL> self . verify_and_change_email ( '<STR_LIT>' , '<STR_LIT>' ) <EOL> expected = '<STR_LIT>' <EOL> actual = Participant . from_username ( '<STR_LIT>' ) . email_address <EOL> assert expected == actual <EOL> def test_get_emails ( self ) : <EOL> self . verify_and_change_email ( '<STR_LIT>' , '<STR_LIT>' ) <EOL> emails = self . alice . get_emails ( ) <EOL> assert len ( emails ) == <NUM_LIT:2> <EOL> def test_verify_email_after_update ( self ) : <EOL> self . verify_and_change_email ( '<STR_LIT>' , '<STR_LIT>' ) <EOL> nonce = self . alice . get_email ( '<STR_LIT>' ) . nonce <EOL> self . verify_email ( '<STR_LIT>' , nonce ) <EOL> expected = '<STR_LIT>' <EOL> actual = Participant . from_username ( '<STR_LIT>' ) . email_address <EOL> assert expected == actual <EOL> def test_nonce_is_reused_when_resending_email ( self ) : <EOL> self . hit_email_spt ( '<STR_LIT>' , '<STR_LIT>' ) <EOL> nonce1 = self . alice . get_email ( '<STR_LIT>' ) . nonce <EOL> self . hit_email_spt ( '<STR_LIT>' , '<STR_LIT>' ) <EOL> nonce2 = self . alice . get_email ( '<STR_LIT>' ) . nonce <EOL> assert nonce1 == nonce2 <EOL> def test_cannot_update_email_to_already_verified ( self ) : <EOL> bob = self . make_participant ( '<STR_LIT>' , claimed_time = '<STR_LIT>' ) <EOL> self . alice . add_email ( '<STR_LIT>' ) <EOL> nonce = self . alice . get_email ( '<STR_LIT>' ) . nonce <EOL> r = self . alice . verify_email ( '<STR_LIT>' , nonce ) <EOL> assert r == emails . VERIFICATION_SUCCEEDED <EOL> with self . assertRaises ( EmailAlreadyTaken ) : <EOL> bob . add_email ( '<STR_LIT>' ) <EOL> nonce = bob . get_email ( '<STR_LIT>' ) . nonce <EOL> bob . verify_email ( '<STR_LIT>' , nonce ) <EOL> email_alice = Participant . from_username ( '<STR_LIT>' ) . email_address <EOL> assert email_alice == '<STR_LIT>' <EOL> def test_cannot_add_too_many_emails ( self ) : <EOL> self . alice . add_email ( '<STR_LIT>' ) <EOL> self . alice . add_email ( '<STR_LIT>' ) <EOL> self . alice . add_email ( '<STR_LIT>' ) <EOL> self . alice . add_email ( '<STR_LIT>' ) <EOL> self . alice . add_email ( '<STR_LIT>' ) <EOL> self . alice . add_email ( '<STR_LIT>' ) <EOL> self . alice . add_email ( '<STR_LIT>' ) <EOL> self . alice . add_email ( '<STR_LIT>' ) <EOL> self . alice . add_email ( '<STR_LIT>' ) <EOL> self . alice . add_email ( '<STR_LIT>' ) <EOL> with self . assertRaises ( TooManyEmailAddresses ) : <EOL> self . alice . add_email ( '<STR_LIT>' ) <EOL> def test_cannot_resend_verification_too_frequently ( self ) : <EOL> self . alice . add_email ( '<STR_LIT>' ) <EOL> time . sleep ( <NUM_LIT> ) <EOL> with self . assertRaises ( ResendingTooFast ) : <EOL> self . alice . add_email ( '<STR_LIT>' , '<STR_LIT>' ) <EOL> def test_can_resend_verification_after_a_while ( self ) : <EOL> self . alice . add_email ( '<STR_LIT>' ) <EOL> time . sleep ( <NUM_LIT> ) <EOL> self . alice . add_email ( '<STR_LIT>' , '<STR_LIT>' ) <EOL> def test_emails_page_shows_emails ( self ) : <EOL> self . verify_and_change_email ( '<STR_LIT>' , '<STR_LIT>' ) <EOL> body = self . client . GET ( "<STR_LIT>" , auth_as = "<STR_LIT>" ) . body <EOL> assert '<STR_LIT>' in body <EOL> assert '<STR_LIT>' in body <EOL> def test_set_primary ( self ) : <EOL> self . verify_and_change_email ( '<STR_LIT>' , '<STR_LIT>' ) <EOL> self . verify_and_change_email ( '<STR_LIT>' , '<STR_LIT>' ) <EOL> self . hit_email_spt ( '<STR_LIT>' , '<STR_LIT>' ) <EOL> def test_cannot_set_primary_to_unverified ( self ) : <EOL> with self . assertRaises ( EmailNotVerified ) : <EOL> self . hit_email_spt ( '<STR_LIT>' , '<STR_LIT>' ) <EOL> def test_remove_email ( self ) : <EOL> self . hit_email_spt ( '<STR_LIT>' , '<STR_LIT>' ) <EOL> self . hit_email_spt ( '<STR_LIT>' , '<STR_LIT>' ) <EOL> self . verify_and_change_email ( '<STR_LIT>' , '<STR_LIT>' ) <EOL> self . verify_and_change_email ( '<STR_LIT>' , '<STR_LIT>' ) <EOL> self . hit_email_spt ( '<STR_LIT>' , '<STR_LIT>' ) <EOL> with self . assertRaises ( CannotRemovePrimaryEmail ) : <EOL> self . hit_email_spt ( '<STR_LIT>' , '<STR_LIT>' ) <EOL> def test_html_escaping ( self ) : <EOL> self . alice . add_email ( "<STR_LIT>" ) <EOL> last_email = self . get_last_email ( ) <EOL> assert '<STR_LIT>' in last_email [ '<STR_LIT>' ] <EOL> assert '<STR_LIT>' not in last_email [ '<STR_LIT>' ] <EOL> def test_can_dequeue_an_email ( self ) : <EOL> larry = self . make_participant ( '<STR_LIT>' , email_address = '<STR_LIT>' ) <EOL> larry . queue_email ( "<STR_LIT>" ) <EOL> assert self . db . one ( "<STR_LIT>" ) == "<STR_LIT>" <EOL> Participant . dequeue_emails ( ) <EOL> assert self . mailer . call_count == <NUM_LIT:1> <EOL> last_email = self . get_last_email ( ) <EOL> assert last_email [ '<STR_LIT:to>' ] == '<STR_LIT>' <EOL> expected = "<STR_LIT>" <EOL> assert expected in last_email [ '<STR_LIT>' ] <EOL> assert self . db . one ( "<STR_LIT>" ) is None <EOL> def test_dequeueing_an_email_without_address_just_skips_it ( self ) : <EOL> larry = self . make_participant ( '<STR_LIT>' ) <EOL> larry . queue_email ( "<STR_LIT>" ) <EOL> assert self . db . one ( "<STR_LIT>" ) == "<STR_LIT>" <EOL> Participant . dequeue_emails ( ) <EOL> assert self . mailer . call_count == <NUM_LIT:0> <EOL> assert self . db . one ( "<STR_LIT>" ) is None </s>
