def test_user_profile_post_name_and_password_and_email(self): """ Test posting to the user profile page with the name, the password, and the email changed. Expected result: The form is shown with the new data. The user's name and password are changed, the email is not, but a mail has been sent to the new address. """ email = '*****@*****.**' name = 'John Doe' password = '******' user = User(email, name) user.set_password(password + '!') with mail.record_messages() as outgoing: user.set_password(password) self.assertEqual(1, len(outgoing)) self.assertIn('Your Password Has Been Changed', outgoing[0].subject) db.session.add(user) db.session.commit() user_id = user.id self.client.post('/user/login', follow_redirects=True, data=dict( email=email, password=password )) new_name = 'Jane Doe' new_password = '******' new_email = '*****@*****.**' with mail.record_messages() as outgoing: response = self.client.post('/user/profile', follow_redirects=True, data=dict( name=new_name, email=new_email, password=new_password, password_confirmation=new_password )) data = response.get_data(as_text=True) self.assertEqual(2, len(outgoing)) self.assertIn('Change Your Email Address', outgoing[1].subject) self.assertEqual([new_email], outgoing[1].recipients) self.assertIn('User Profile', data) self.assertIn(f'value="{new_name}"', data) self.assertIn(f'value="{email}"', data) self.assertIn('Your changes have been saved.', data) self.assertIn('An email has been sent to the new address', data) user = User.load_from_id(user_id) self.assertEqual(new_name, user.name) self.assertEqual(email, user.get_email()) self.assertTrue(user.check_password(new_password))
def test_reset_password_request_post_existing_user(self): """ Test accessing the password reset request form via POST with an existing user. Expected result: The password reset mail is sent to the user and a message is displayed. """ email = '*****@*****.**' password = '******' name = 'John Doe' user_id = 1 user = User(email, name) user.set_password(password) db.session.add(user) db.session.commit() self.assertEqual(user_id, user.id) with mail.record_messages() as outgoing: response = self.client.post('/user/reset-password', follow_redirects=True, data=dict( email=email )) data = response.get_data(as_text=True) self.assertEqual(1, len(outgoing)) self.assertIn('Reset Your Password', outgoing[0].subject) self.assertIn('<h1>Log In</h1>', data) self.assertIn('An email has been sent to the specified address.', data)
def test_send_success_multiple_recipients(self): """ Test sending an email to multiple recipients. Expected result: The email is sent successfully. """ subject = 'Test Subject' body_path = 'email/test' sender = '*****@*****.**' recipients = ['*****@*****.**', '*****@*****.**'] body_plain = 'Plain Body' body_html = 'HTML Body' email = Email(subject, body_path, sender) email._body_plain = body_plain email._body_html = body_html with mail.record_messages() as outgoing: email.send(recipients) self.assertEqual(1, len(outgoing)) self.assertIn(subject, outgoing[0].subject) self.assertEqual(sender, outgoing[0].sender) self.assertListEqual(recipients, outgoing[0].recipients) self.assertEqual(body_plain, outgoing[0].body) self.assertEqual(body_html, outgoing[0].html)
def test_send_failure(self): """ Test sending an email to a recipient given in a wrong type. Expected result: The email is not sent. """ subject = 'Test Subject' body_path = 'email/test' sender = '*****@*****.**' recipients = None body_plain = 'Plain Body' body_html = 'HTML Body' email = Email(subject, body_path, sender) email._body_plain = body_plain email._body_html = body_html with self.assertRaises(TypeError) as message: with mail.record_messages() as outgoing: # noinspection PyTypeChecker email.send(recipients) self.assertEqual(0, len(outgoing)) self.assertEqual('Argument "recipients" must be a string or a list of strings.', message)
def test_email_confimation_token_of_invalid_user_raise_404_error_message(self): """ Com: - email de usuário que não existe no sistema. Quando: 1. enviamos emails de confirmação (utilizando diretamente notifications.py) 2. acesssamos o link enviado por email Verificamos: - que o email enviado contem um link para confirmar email. - após acessar o link, a página mostra o erro 404 com a mensagem certa. """ # with expected_error_msg = u'Usuário não encontrado' fake_user_email = u'*****@*****.**' # when with mail.record_messages() as outbox: send_confirmation_email(fake_user_email) # then # temos um email self.assertEqual(1, len(outbox)) email_msg = outbox[0] # pegamos o link com token links_found = email_confirm_url_pattern.findall(email_msg.html) # tem pelo menos 1 link, e tem só um link para o reset/password com token self.assertGreaterEqual(1, len(links_found)) email_confirmation_url_with_token = [url for url in links_found if '/admin/confirm/' in url] # temos a url com o token self.assertEqual(1, len(email_confirmation_url_with_token)) email_confirmation_url_with_token = email_confirmation_url_with_token[0] # acessamos o link do email confirmation_response = self.client.get(email_confirmation_url_with_token, follow_redirects=True) self.assertStatus(confirmation_response, 404) self.assertTemplateUsed('errors/404.html') error_msg = self.get_context_variable('message') self.assertEqual(error_msg, error_msg)
def test_confirmation_works(self): self.register_and_login('*****@*****.**', 'test123') with mail.record_messages() as outbox: res = self.client.post('/confirm', data=dict( email=u'*****@*****.**' )) self.assertEqual(len(outbox), 1) msg = outbox[0] self.assertEqual(msg.sender, '*****@*****.**') self.assertEqual(msg.recipients, ['*****@*****.**']) assert 'http://localhost/confirm/' in msg.body assert ('Confirmation instructions have been ' 'sent to [email protected]') in res.data token = re.search( r'http:\/\/localhost\/confirm\/(.+)', msg.body, flags=re.MULTILINE ).group(1) res = self.client.get('/confirm/%s' % token) self.assertRedirects(res, '/confirm/success') res = self.client.get('/confirm/success') self.assertRedirects(res, '/activity') res = self.client.get('/activity') self.assert200(res) assert 'Your email has been confirmed' in res.data
def test_reset_password_with_unconfirmed_email_shows_unconfirm_email_error(self): """ Com: um novo usuário (com email NÃO confirmado), Quando: 1. solicitamos recuperar senha. 2. obtemos o email com a url necessária para recuperação. 3. e solicitamos uma nova senha, com o link (token) do email. Verificamos: - a pagina deve informar que é necessário confirmar o email. - a troca de senha não procede. - a pagina deve mostrar o template admin/auth/unconfirm_email.html """ # with reset_pwd_url = url_for('admin.reset') credentials = { 'email': '*****@*****.**', 'password': '******' } # when create_user(credentials['email'], credentials['password'], False) with mail.record_messages() as outbox: response = self.client.post( reset_pwd_url, data={'email': credentials['email']}, follow_redirects=True) # then # no foi enviado nenhum email self.assertEqual(0, len(outbox)) self.assertStatus(response, 200) self.assertTemplateUsed('admin/auth/unconfirm_email.html') user = get_user_by_email(credentials['email']) self.assertTrue(user.is_correct_password(credentials['password']))
def test_post_with_invalid_email_shows_error(self): with mail.record_messages() as outbox: res = self.client.post("/invite", data={"email": "blarg"}) self.assertEqual(len(outbox), 0) self.assert200(res) assert "Invalid email address" in res.data assert "Your form submission was invalid" in res.data
def test_user_profile_get(self): """ Test accessing the user profile page. Expected result: The form is shown with prepopulated data. """ email = '*****@*****.**' name = 'John Doe' password = '******' user = User(email, name) user.set_password(password) db.session.add(user) db.session.commit() self.client.post('/user/login', follow_redirects=True, data=dict( email=email, password=password )) with mail.record_messages() as outgoing: response = self.client.get('/user/profile', follow_redirects=True) data = response.get_data(as_text=True) self.assertEqual(0, len(outgoing)) self.assertIn('User Profile', data) self.assertIn(f'value="{name}"', data) self.assertIn(f'value="{email}"', data) self.assertNotIn('Your changes have been saved.', data) self.assertNotIn('An email has been sent to the new address', data)
def test_delete_profile_request_failure(self): """ Test requesting the deletion of the user's account with an invalid form. Expected result: No email is sent. """ email = '*****@*****.**' password = '******' name = 'John Doe' user_id = 1 user = User(email, name) user.set_password(password) db.session.add(user) db.session.commit() self.assertEqual(user_id, user.id) self.client.post('/user/login', follow_redirects=True, data=dict( email=email, password=password )) with mail.record_messages() as outgoing: response = self.client.post('/user/delete', follow_redirects=True, data=dict()) data = response.get_data(as_text=True) self.assertEqual(0, len(outgoing)) self.assertNotIn('An email has been sent to your email address.', data) self.assertNotIn('to delete your user profile.', data) self.assertIn('<h1>User Profile</h1>', data)
def test_post_with_valid_email_sends_invite(self): with mail.record_messages() as outbox: res = self.client.post('/invite', data={ 'email': '*****@*****.**' }, follow_redirects=True) self.assertEqual(len(outbox), 1) self.assert200(res) assert 'Invitation sent!' in res.data
def test_registration_sends_email(self): with mail.record_messages() as outbox: self.register_and_login('*****@*****.**', 'test123') self.assertEqual(len(outbox), 1) msg = outbox[0] self.assertEqual(msg.sender, '*****@*****.**') self.assertEqual(msg.recipients, ['*****@*****.**']) assert 'http://localhost/confirm/' in msg.body
def test_sends_confirmation_email_on_post(self): with mail.record_messages() as outbox: res = self.client.post('/register/step/1.5') self.assertEqual(len(outbox), 1) msg = outbox[0] self.assertEqual(msg.sender, '*****@*****.**') self.assertEqual(msg.recipients, ['*****@*****.**']) assert 'http://localhost/confirm/' in msg.body
def test_post_with_invalid_email_shows_error(self): with mail.record_messages() as outbox: res = self.client.post('/invite', data={ 'email': 'blarg' }) self.assertEqual(len(outbox), 0) self.assert200(res) assert 'Invalid email address' in res.data assert 'Your form submission was invalid' in res.data
def test_post_with_valid_email_sends_invite(self): with mail.record_messages() as outbox: res = self.client.post("/invite", data={"email": "*****@*****.**"}, follow_redirects=True) self.assertEqual(len(outbox), 1) msg = outbox[0] self.assertEqual(msg.sender, "*****@*****.**") self.assertEqual(msg.recipients, ["*****@*****.**"]) assert "https://noi.org" in msg.body self.assert200(res) assert "Invitation sent!" in res.data
def test_reset_password_with_unconfirmed_email_raise_validation_error_2(self): """ Com: um novo usuário (com email confirmado), Quando: 1. solicitamos recuperar senha. 2. obtemos o email com a url necessária para recuperação. 3. mudamos o usuário para ter seu email como NÃO confirmado. 4. e solicitamos uma nova senha, com o link (token) do email. Verificamos: - a pagina deve informar que é necessário confirmar o email. - a troca de senha não procede. - a pagina deve mostrar o template admin/auth/unconfirm_email.html """ # with reset_pwd_url = url_for('admin.reset') credentials = { 'email': '*****@*****.**', 'password': '******' } # when create_user(credentials['email'], credentials['password'], True) with mail.record_messages() as outbox: response = self.client.post( reset_pwd_url, data={'email': credentials['email']}, follow_redirects=True) # then self.assertEqual(1, len(outbox)) email_msg = outbox[0] # recupero os links do email links_found = reset_pwd_url_pattern.findall(email_msg.html) # tem pelo menos 1 link, e tem só um link para o reset/password com token self.assertGreaterEqual(1, len(links_found)) resert_url_with_token = [url for url in links_found if reset_pwd_url in url][0] # agora o usuário tem o email NÃO confirmado. user = get_user_by_email(credentials['email']) user.email_confirmed = False dbsql.session.add(user) dbsql.session.commit() # tentamos recuperar a senha com o link/token do email new_password = '******' response = self.client.post( resert_url_with_token, data={'password': new_password}, follow_redirects=True) self.assertStatus(response, 200) self.assertTemplateUsed('admin/auth/unconfirm_email.html') user = get_user_by_email(credentials['email']) self.assertTrue(user.is_correct_password(credentials['password']))
def test_post_with_valid_email_sends_invite(self): with mail.record_messages() as outbox: res = self.client.post('/invite', data={ 'email': '*****@*****.**' }, follow_redirects=True) self.assertEqual(len(outbox), 1) msg = outbox[0] self.assertEqual(msg.sender, '*****@*****.**') self.assertEqual(msg.recipients, ['*****@*****.**']) assert 'https://noi.org' in msg.body self.assert200(res) assert 'Invitation sent!' in res.data
def test_registration_complains_if_email_is_taken(self): self.register_and_login('*****@*****.**', 'test123') self.logout() with mail.record_messages() as outbox: res = self.client.post('/register', data=dict( email=u'*****@*****.**' )) self.assertEqual(len(outbox), 0) assert ('[email protected] is already ' 'associated with an account') in res.data
def test_try_to_create_user_without_email_must_raise_error_notification(self): """ Com: - usuario administrador (com email confirmado) Quando: 1. acessamos /admin 2. tentamos cadastrar um novo usuário, ** sem inserir email ** Verificamos: - o usuário não é criado. - o usuário administrado é notificodo do erro da operação. """ # with admin_user = { 'email': '*****@*****.**', 'password': '******', } create_user(admin_user['email'], admin_user['password'], True) new_user = { 'email': '*****@*****.**', 'password': '******' } login_url = url_for('admin.login_view') create_user_url = '/admin/user/new/' expected_form_error = {'email': [u'This field is required.']} # when with mail.record_messages() as outbox: with self.client as client: # login do usuario admin login_response = client.post( login_url, data=admin_user, follow_redirects=True) self.assertStatus(login_response, 200) self.assertTemplateUsed('admin/index.html') self.assertTrue(current_user.is_authenticated) # "preencher" from sem o email do novo usuário create_user_response = client.post( create_user_url, data={'email': ''}, follow_redirects=True) # then self.assertStatus(create_user_response, 200) self.assertTemplateUsed('admin/model/create.html') # tem erro no formulario context_form = self.get_context_variable('form') # self.assertIsInstance(context_form, admin_form.UserForm) self.assertEqual(expected_form_error, context_form.errors) # não temos email self.assertEqual(0, len(outbox))
def test_reset_password_with_invalid_password_raise_validation_error(self): """ Com: um novo usuário (com email confirmado), Quando: 1. solicitamos recuperar senha. 2. obtemos o email com a url necessária para recuperação. 3. e solicitamos uma nova senha, com o link do email. 4. inserimos uma senha inválida ('') Verificamos: - a pagina deve informar de que senha é requerida - a senha do usuário não deve ser modificada """ # with reset_pwd_url = url_for('admin.reset') credentials = { 'email': '*****@*****.**', 'password': '******' } # when create_user(credentials['email'], credentials['password'], True) with mail.record_messages() as outbox: response = self.client.post( reset_pwd_url, data={'email': credentials['email']}, follow_redirects=True) # then self.assertEqual(1, len(outbox)) email_msg = outbox[0] # recupero os links do email links_found = reset_pwd_url_pattern.findall(email_msg.html) # tem pelo menos 1 link, e tem só um link para o reset/password com token self.assertGreaterEqual(1, len(links_found)) resert_url_with_token = [url for url in links_found if reset_pwd_url in url][0] invalid_password = '' response = self.client.post( resert_url_with_token, data={'password': invalid_password}, follow_redirects=True) self.assertStatus(response, 200) context_form = self.get_context_variable('form') expected_form_error = {'password': [u'This field is required.']} self.assertEqual(expected_form_error, context_form.errors) self.assertIn(expected_form_error['password'][0], response.data.decode('utf-8')) user = get_user_by_email(credentials['email']) self.assertFalse(user.is_correct_password(invalid_password))
def test_link_sent_via_email_to_reset_password_works_fine(self): """ Com: um novo usuário (com email confirmado), Quando: 1. solicitamos recuperar senha. 2. obtemos o email com a url necessária para recuperação. 3. e solicitamos uma nova senha, com o link do email. 4. inserimos uma nova senha para o úsuario. Verificamos: - a pagina de recuperar senha tenha o form esperado. - a senha do usuário deve ser atualizada. """ # with reset_pwd_url = url_for('admin.reset') credentials = { 'email': '*****@*****.**', 'password': '******' } # when create_user(credentials['email'], credentials['password'], True) with mail.record_messages() as outbox: response = self.client.post( reset_pwd_url, data={'email': credentials['email']}, follow_redirects=True) # then self.assertEqual(1, len(outbox)) email_msg = outbox[0] # recupero os links do email links_found = reset_pwd_url_pattern.findall(email_msg.html) # tem pelo menos 1 link, e tem só um link para o reset/password com token self.assertGreaterEqual(1, len(links_found)) resert_url_with_token = [url for url in links_found if reset_pwd_url in url][0] new_password = '******' response = self.client.post( resert_url_with_token, data={'password': new_password}, follow_redirects=True) self.assertStatus(response, 200) # verificação da nova senha do usuario user = get_user_by_email(credentials['email']) self.assertTrue(user.is_correct_password(new_password))
def test_reset_password_send_valid_link_via_email(self): """ Com: um novo usuário (com email confirmado), Quando: solicitamos recuperar senha, e obtemos o email com a url necessária para concluir a operação. Verificamos: - o email enviado contém um link para recupear senha. - a pagina de recuparar senha com token seja a correta. """ # with reset_pwd_url = url_for('admin.reset') credentials = { 'email': '*****@*****.**', 'password': '******' } # when create_user(credentials['email'], credentials['password'], True) with mail.record_messages() as outbox: response = self.client.post( reset_pwd_url, data={'email': credentials['email']}, follow_redirects=True) # then self.assertEqual(1, len(outbox)) email_msg = outbox[0] # recupero os links do email links_found = reset_pwd_url_pattern.findall(email_msg.html) # tem pelo menos 1 link, e tem só um link para o reset/password com token self.assertGreaterEqual(1, len(links_found)) resert_url_with_token = [url for url in links_found if reset_pwd_url in url] self.assertEqual(1, len(resert_url_with_token)) resert_url_with_token = resert_url_with_token[0] # requisição de reset passoword com token reset_pwd_response = self.client.get( resert_url_with_token, follow_redirects=True) self.assertStatus(reset_pwd_response, 200) self.assertTemplateUsed('admin/auth/reset_with_token.html') context_form = self.get_context_variable('form') self.assertIsInstance(context_form, forms.PasswordForm)
def test_reset_password_request_post_non_existing_user(self): """ Test accessing the password reset request form via POST with a non-existing user. Expected result: No password reset mail is sent, but a message is displayed that it has. """ email = '*****@*****.**' with mail.record_messages() as outgoing: response = self.client.post('/user/reset-password', follow_redirects=True, data=dict( email=email )) data = response.get_data(as_text=True) self.assertEqual(0, len(outgoing)) self.assertIn('<h1>Log In</h1>', data) self.assertIn('An email has been sent to the specified address.', data)
def test_user_profile_post_only_name(self): """ Test posting to the user profile page with only the name changed. Expected result: The form is shown with the new data. The user's name is changed, everything else is not. """ email = '*****@*****.**' name = 'John Doe' password = '******' user = User(email, name) user.set_password(password) db.session.add(user) db.session.commit() user_id = user.id self.client.post('/user/login', follow_redirects=True, data=dict( email=email, password=password )) new_name = 'Jane Doe' with mail.record_messages() as outgoing: response = self.client.post('/user/profile', follow_redirects=True, data=dict( name=new_name, email=email )) data = response.get_data(as_text=True) self.assertEqual(0, len(outgoing)) self.assertIn('User Profile', data) self.assertIn(f'value="{new_name}"', data) self.assertIn(f'value="{email}"', data) self.assertIn('Your changes have been saved.', data) self.assertNotIn('An email has been sent to the new address', data) user = User.load_from_id(user_id) self.assertEqual(new_name, user.name) self.assertEqual(email, user.get_email()) self.assertTrue(user.check_password(password))
def test_reset_password_of_valid_user_email_sent(self): """ Com: um novo usuário (com email confirmado) Quando: solicitar a recuperação de senha Verificamos: Que a mensagem no email enviado contém o link para continuar a operação. """ # with reset_pwd_url = url_for('admin.reset') credentials = { 'email': '*****@*****.**', 'password': '******' } expected_email = { 'subject': 'Instruções para recuperar sua senha', 'recipients': [credentials['email'], ], 'body_has_link': u'<a href="http://localhost%s' % reset_pwd_url } # when create_user(credentials['email'], credentials['password'], True) with mail.record_messages() as outbox: response = self.client.post( reset_pwd_url, data={'email': credentials['email']}, follow_redirects=True) # then self.assertStatus(response, 200) self.assertEqual(1, len(outbox)) email_msg = outbox[0] self.assertEqual(expected_email['subject'], email_msg.subject) self.assertEqual(expected_email['recipients'], email_msg.recipients) self.assertIn(expected_email['body_has_link'], email_msg.html.decode('utf-8'))
def test_create_user_from_admin_page_creates_a_new_user(self): """ Com: - usuario administrador (com email confirmado) Quando: 1. acessamos /admin e cadastramos um novo usuário 2. acesssamos o link enviado por email Verificamos: - o usuário é criado. - o usuário administrador é notificodo do sucesso da operação. - o novo usuário não tem email confirmado. - o novo usuário é notificado por email para confirmar email. """ # with admin_user = { 'email': '*****@*****.**', 'password': '******', } create_user(admin_user['email'], admin_user['password'], True) new_user = { 'email': '*****@*****.**', 'password': '******' } login_url = url_for('admin.login_view') create_user_url = '/admin/user/new/' expected_msgs = [ u'Enviamos o email de confirmação para: %s' % new_user['email'], u'Registro criado com sucesso.', ] # when with mail.record_messages() as outbox: with self.client as client: # login do usuario admin login_response = client.post( login_url, data=admin_user, follow_redirects=True) self.assertStatus(login_response, 200) self.assertTemplateUsed('admin/index.html') self.assertTrue(current_user.is_authenticated) # requisição da ação para enviar email de confirmação create_user_response = client.post( create_user_url, data={'email': new_user['email']}, follow_redirects=True) # then self.assertStatus(create_user_response, 200) self.assertTemplateUsed('admin/model/list.html') for msg in expected_msgs: self.assertIn(msg, action_response.data.decode('utf-8')) # temos um email self.assertEqual(1, len(outbox)) email_msg = outbox[0] # pegamos o link com token links_found = email_confirm_url_pattern.findall(email_msg.html) # tem pelo menos 1 link, e tem só um link para o reset/password com token self.assertGreaterEqual(1, len(links_found)) email_confirmation_url_with_token = [url for url in links_found if '/admin/confirm/' in url] # temos a url com o token self.assertEqual(1, len(email_confirmation_url_with_token)) email_confirmation_url_with_token = email_confirmation_url_with_token[0] self.assertIsNotNone(email_confirmation_url_with_token) self.assertFalse(email_confirmation_url_with_token == '') # acessamos o link do email user = get_user_by_email(new_user['email']) confirmation_response = self.client.get(email_confirmation_url_with_token, follow_redirects=True) self.assertStatus(confirmation_response, 200) self.assertTemplateUsed('admin/index.html') # confirmação com sucesso self.assertIn(expected_msg, confirmation_response.data.decode('utf-8')) # confirmamos alteração do usuário self.assertTrue(user.email_confirmed)
def mail_outbox(): with mail.record_messages() as outbox: yield outbox
def test_email(self): with mail.record_messages() as outbox: self.app.post('/wt_feed', data=json.dumps(self.data), content_type='application/json') self.assertEqual(len(outbox), 1)
def mailbox(app): return _mail.record_messages()
def test_fix_registration_email(client, user_info, user2_info, test_config): """Registered users can fix errors in their email addresses.""" rv = client.get(url_for("auth.register")) data = dict( csrf_token=csrf_token(rv.data), username=user_info["username"], password=user_info["password"], confirm=user_info["password"], email_required=user_info["email"], invitecode="", accept_tos=True, captcha="xyzzy", ) # Register and save the link from the first email. with mail.record_messages() as outbox: rv = client.post(url_for("auth.register"), data=data, follow_redirects=True) assert b"spam" in rv.data # Telling user to go check it. message = outbox.pop() soup = BeautifulSoup(message.html, "html.parser") first_token = soup.a["href"].split("/")[-1] # Find the resend link. soup = BeautifulSoup(rv.data, "html.parser", from_encoding="utf-8") links = soup.find_all( lambda tag: tag.name == "a" and tag.string == "Resend") url = links[0]["href"] # Request the resend form and verify the registered email is shown. rv = client.get(url) assert b"Resend account confirmation instructions" in rv.data soup = BeautifulSoup(rv.data, "html.parser", from_encoding="utf-8") tag = soup.find_all(lambda tag: tag.get("name") == "email")[0] assert tag["value"] == user_info["email"] # Ask for emails to be sent to a different address. with mail.record_messages() as outbox: rv = client.post( url, data=dict(csrf_token=csrf_token(rv.data), email=user2_info["email"]), follow_redirects=True, ) assert b"spam" in rv.data # Telling user to go check it. message = outbox.pop() assert message.recipients == [user2_info["email"]] soup = BeautifulSoup(message.html, "html.parser") token = soup.a["href"].split("/")[-1] # Use the confirmation link from the email. rv = client.get(url_for("auth.login_with_token", token=token), follow_redirects=True) assert b"Log out" in rv.data # Verify that the user's confirmed email is the second one. rv = client.get(url_for("user.edit_account")) soup = BeautifulSoup(rv.data, "html.parser", from_encoding="utf-8") tag = soup.find_all(lambda tag: tag.get("name") == "email_required")[0] assert tag["value"] == user2_info["email"] log_out_current_user(client) # Try to use the first token and verify that it is no longer valid. rv = client.get(url_for("auth.login_with_token", token=first_token), follow_redirects=True) assert b"The link you used is invalid or has expired" in rv.data assert b"Log out" not in rv.data # Try to use the resend form and verify that it no longer works. rv = client.get(url, follow_redirects=True) assert b"The link you used is invalid or has expired" in rv.data assert b"Log out" not in rv.data
def test_confirmation_email_send_email_with_token(self): """ Com: - o usuário 'administrador' logado (email confirmado) - um novo usuário, com email NÃO confirmado Quando: 1. enviamos emails de confirmação (utilizando a ação do admin/user) 2. Verificamos: - que o email enviado contem um link para confirmar email. - o email é enviado para o destinatario certo. - após a operação, a página é a correta. - as notifiação para usuário deve ser mostrada na página. """ # with admin_user = { 'email': '*****@*****.**', 'password': '******', } create_user(admin_user['email'], admin_user['password'], True) normal_user = { 'email': '*****@*****.**', 'password': '******' } create_user(normal_user['email'], normal_user['password'], False) login_url = url_for('admin.login_view') action_payload = { 'action': 'confirm_email', 'rowid': get_user_by_email(normal_user['email']).id, 'url': '/admin/user/' } expected_email_sent_notifications = [ u"Enviamos o email de confirmação para: %s" % normal_user['email'], u"1 usuários foram notificados com sucesso!", ] expected_email = { 'subject': u'Confirmação de email', 'recipients': [normal_user['email'], ], } # when # login do usuario admin login_response = self.client.post( login_url, data=admin_user, follow_redirects=True) self.assertStatus(login_response, 200) self.assertTemplateUsed('admin/index.html') # requisição da ação para enviar email de confirmação with mail.record_messages() as outbox: action_response = self.client.post( '/admin/user/action/', data=action_payload, follow_redirects=True) # then self.assertStatus(action_response, 200) self.assertTemplateUsed('admin/model/list.html') for msg in expected_email_sent_notifications: self.assertIn(msg, action_response.data.decode('utf-8')) # temos um email self.assertEqual(1, len(outbox)) email_msg = outbox[0] # email enviado ao destinatario certo, com assunto certo self.assertEqual(expected_email['recipients'], email_msg.recipients) self.assertEqual(expected_email['subject'], email_msg.subject.decode('utf-8')) # pegamos o link com token links_found = email_confirm_url_pattern.findall(email_msg.html) # tem pelo menos 1 link, e tem só um link para o reset/password com token self.assertGreaterEqual(1, len(links_found)) email_confirmation_url_with_token = [url for url in links_found if '/admin/confirm/' in url] # temos a url com o token self.assertEqual(1, len(email_confirmation_url_with_token)) email_confirmation_url_with_token = email_confirmation_url_with_token[0] self.assertIsNotNone(email_confirmation_url_with_token) self.assertFalse(email_confirmation_url_with_token == '')
def test_open_confirm_url_with_token_sent_via_email_open_the_correct_page(self): """ Com: - o usuário 'administrador' logado (email confirmado) - um novo usuário, com email NÃO confirmado Quando: 1. enviamos emails de confirmação (utilizando a ação do admin/user) 2. acesssamos o link enviado por email Verificamos: - que o email enviado contem um link para confirmar email. - após acessar o link, a página é a correta. - após acessar o link, a págian mostra a notificação de operação ok. - após acessar o link, o usuário tem seu email confirmado. """ # with admin_user = { 'email': '*****@*****.**', 'password': '******', } create_user(admin_user['email'], admin_user['password'], True) normal_user = { 'email': '*****@*****.**', 'password': '******' } create_user(normal_user['email'], normal_user['password'], False) login_url = url_for('admin.login_view') action_payload = { 'action': 'confirm_email', 'rowid': get_user_by_email(normal_user['email']).id, 'url': '/admin/user/' } expected_msg = u'Email: %s confirmado com sucesso!' % normal_user['email'] # when # login do usuario admin login_response = self.client.post( login_url, data=admin_user, follow_redirects=True) self.assertStatus(login_response, 200) # requisição da ação para enviar email de confirmação with mail.record_messages() as outbox: action_response = self.client.post( '/admin/user/action/', data=action_payload, follow_redirects=True) # then self.assertStatus(action_response, 200) # temos um email self.assertEqual(1, len(outbox)) email_msg = outbox[0] # pegamos o link com token links_found = email_confirm_url_pattern.findall(email_msg.html) # tem pelo menos 1 link, e tem só um link para o reset/password com token self.assertGreaterEqual(1, len(links_found)) email_confirmation_url_with_token = [url for url in links_found if '/admin/confirm/' in url] # temos a url com o token self.assertEqual(1, len(email_confirmation_url_with_token)) email_confirmation_url_with_token = email_confirmation_url_with_token[0] # acessamos o link do email confirmation_response = self.client.get(email_confirmation_url_with_token, follow_redirects=True) self.assertStatus(confirmation_response, 200) self.assertTemplateUsed('admin/index.html') # confirmação com sucesso self.assertIn(expected_msg, confirmation_response.data.decode('utf-8')) # confirmamos alteração do usuário user = get_user_by_email(normal_user['email']) self.assertTrue(user.email_confirmed)
def test_change_password_recovery_email(client, user_info): """The user can change their password recovery email.""" register_user(client, user_info) new_email = '*****@*****.**' assert new_email != user_info['email'] rv = client.get(url_for('user.edit_account')) data = dict(csrf_token=csrf_token(rv.data), oldpassword=user_info['password'], password='', confirm='') if email_validation_is_required(): data['email_required'] = new_email else: data['email_optional'] = new_email with mail.record_messages() as outbox: rv = client.post(url_for('do.edit_account'), data=data, follow_redirects=True) log_out_current_user(client) if email_validation_is_required(): message = outbox.pop() # Make sure that password recovery emails go to the former address # if the new one has not yet been confirmed. rv = client.get(url_for('user.password_recovery')) rv = client.post(url_for('user.password_recovery'), data=dict(csrf_token=csrf_token(rv.data), email=new_email, captcha='xyzzy')) assert len(outbox) == 0 rv = client.get(url_for('user.password_recovery')) rv = client.post(url_for('user.password_recovery'), data=dict(csrf_token=csrf_token(rv.data), email=user_info['email'], captcha='xyzzy')) assert outbox.pop().send_to == {user_info['email']} # Now click the confirm link. assert message.send_to == {new_email} soup = BeautifulSoup(message.html, 'html.parser') token = soup.a['href'].split('/')[-1] rv = client.get(url_for('user.confirm_email_change', token=token), follow_redirects=True) else: assert len(outbox) == 0 # Verify password recovery email goes to the right place. with mail.record_messages() as outbox: rv = client.get(url_for('user.password_recovery')) rv = client.post(url_for('user.password_recovery'), data=dict(csrf_token=csrf_token(rv.data), email=user_info['email'], captcha='xyzzy')) assert len(outbox) == 0 rv = client.get(url_for('user.password_recovery')) rv = client.post(url_for('user.password_recovery'), data=dict(csrf_token=csrf_token(rv.data), email=new_email, captcha='xyzzy')) assert outbox.pop().send_to == {new_email}
def test_send_mail(client, init_database): """ GIVEN a Flask application, admin, study WHEN study is today THEN check emails are sent with correct content """ with client.application.test_request_context(): admin = create_admin(client, username="******", password="******") participant_1 = create_participant(client, username="******") participant_2 = create_participant(client, username="******") participant_3 = create_participant(client, username="******") participant_4 = create_participant(client, username="******") participant_5 = create_participant(client, username="******") user_group = create_user_group( client, creator=admin, participants=[participant_1, participant_2]) user_group_2 = create_user_group( client, creator=admin, participants=[participant_3, participant_4, participant_5], ) study = create_study( client, start_date=date.today(), creator=admin, user_group=user_group, ) study2 = create_study(client, creator=admin, start_date=date.today() + timedelta(days=3)) study_3 = create_study( client, creator=admin, start_date=date.today(), user_group=user_group_2, ) studies = Study.query.filter( func.DATE(Study.start_date) == date.today()).all() assert study2 not in studies letters = string.ascii_letters strength = 8 for study in studies: if study.mail_sent == False: user_group = UserGroup.query.filter_by( id=study.user_group_id).first() if user_group: with mail.record_messages() as outbox: for user in user_group.users: password = "".join( random.choice(letters) for i in range(strength)) user.set_password(password) body = render_template( "email.html", study=study, username=user.username, password=password, ) msg = Message( "You Have Been Invited To A Study!", recipients=[user.email], sender=current_app.config["MAIL_USERNAME"], ) msg.html = body assert password in msg.html assert user.username in msg.html assert msg.recipients[0] == user.email mail.send(msg) user.email = None assert user.email is None assert len(outbox) == len(user_group.users) try: study.mail_sent = True db.session.commit() except: db.session.rollback()
def test_auth_registeration_login_logout(self): # Check that Sign In and Register Links are present in the main page response = self.client.get(url_for('main.index')) data = response.get_data(as_text=True) assert_true("Sign In" in data) assert_true("Register" in data) # Check that the Registration page has the form response = self.client.get(url_for("auth.register")) data = response.get_data(as_text=True) assert_true('Register' in data) assert_true('Email' in data) assert_true('Username' in data) assert_true('Password' in data) assert_true('Confirm Password' in data) # Register - should redirect to main page with mail.record_messages() as outbox: response = self.client.post(url_for('auth.register'), data={ "email": "*****@*****.**", "username": "******", "password": "******", "password2": "cat" }, follow_redirects=True) data = response.get_data(as_text=True) assert_true("A confirmation email has been sent to your email address." in data) assert_true(len(outbox) == 1) # Mail was sent assert_true('Confirm Your Account' in outbox[0].subject) # Login page contains the form response = self.client.get(url_for('auth.login')) data = response.get_data(as_text=True) assert_true('Login' in data) assert_true('Email' in data) assert_true('Password' in data) assert_true('Keep me logged in' in data) assert_true('Log In' in data) # Incorrect logins return error response = self.login('*****@*****.**', 'badpassword') assert_true('Invalid email or password' in response.get_data(as_text=True)) response = self.login('*****@*****.**', 'badpassword') assert_true('Invalid email or password' in response.get_data(as_text=True)) # Correct login response = self.login('*****@*****.**', 'cat') data = response.get_data(as_text=True) assert_true('You were logged in' in data) assert_true(re.compile("Hello,\s+sam").search(data)) # Should prompt the user to confirm their email address assert_true("You have not confirmed your account yet" in data) # Resend confirmation with mail.record_messages() as outbox: response = self.client.get(url_for('auth.resend_confirmation'), follow_redirects=True) data = response.get_data(as_text=True) assert_true('A new confirmation email has been sent to you' in data) assert_true(len(outbox) == 1) # Confirm account user = User.query.filter_by(email='*****@*****.**').first() # Attempt to use another user's token rejected token = User.query.filter_by(email='*****@*****.**').first().generate_confirmation_token() response = self.client.get(url_for('auth.confirm', token=token), follow_redirects=True) data = response.get_data(as_text=True) assert_true(re.compile('The confirmation link is invalid or has expired.').search(data)) # Incorrect token rejected token = user.generate_confirmation_token() response = self.client.get(url_for('auth.confirm', token=' ' + token), follow_redirects=True) data = response.get_data(as_text=True) assert_true(re.compile('The confirmation link is invalid or has expired.').search(data)) # Correct token accepted response = self.client.get(url_for('auth.confirm', token=token), follow_redirects=True) data = response.get_data(as_text=True) assert_true("You have confirmed your account." in data) # Main page should have Sign Out link, and welcome us by username response = self.client.get(url_for('main.index')) data = response.get_data(as_text=True) assert_true(re.compile("Hello,\s+sam").search(data)) assert_true("Sign Out" in data) # Check logout - should redirect to main page response = self.client.get(url_for('auth.logout'), follow_redirects=False) assert_true(response.status_code == 302) # Should have Sign In link on main page now response = self.client.get(url_for('main.index')) assert_true("Sign In" in response.get_data(as_text=True)) # Delete test user User.query.filter_by(email='*****@*****.**').delete()
def send_message(to_address_list=None, **kwargs): """Send an email with the parameters as: to_address_list=[list of tuples (recipient name,recipient address)]=None If the to_address_list is not provided, mail will be sent to the admin -- all templates must use 'context' as their only context variable **kwargs: context = {a dictionary like object with data for rendering all emails} = {} body = <text for body of email> = None body_text_is_html = <True | False> = False text_template=<template to render as plain text message> = None html_template=<template to render as html message> = None subject=<subject text (will be rendered with the current context>)>= a default subject subject_prefix=<some text to prepend to the subject: = '' from_address=<from address> = app.config['MAIL_DEFAULT_ADDR'] from_sender=<name of sender> = app.config['MAIL_DEFAULT_SENDER'] reply_to_address=<replyto address> = from_address reply_to_name=<name of reply to account> = from_sender On completion returns a tuple of: success [True or False] message "some message" """ #import pdb;pdb.set_trace() app_config = get_app_config( ) #update the settings. this also recreates the mail var in app with new settings context = kwargs.get('context', {}) body = kwargs.get('body', None) body_is_html = kwargs.get('body_is_html', None) text_template = kwargs.get('text_template', None) html_template = kwargs.get('html_template', None) subject_prefix = kwargs.get('subject_prefix', '') try: admin_addr = app_config['MAIL_DEFAULT_ADDR'] admin_name = app_config['MAIL_DEFAULT_SENDER'] except KeyError as e: mes = "MAIL Settings not found" mes = printException(mes, 'error', e) return (False, mes) from_address = kwargs.get('from_address', admin_addr) from_sender = kwargs.get('from_sender', admin_name) reply_to = kwargs.get('reply_to', from_address) subject = subject_prefix + ' ' + kwargs.get( 'subject', 'A message from {}'.format(from_sender)) if not text_template and not html_template and not body: mes = "No message body was specified" printException(mes, "error") return (False, mes) if not to_address_list or len(to_address_list) == 0: #no valid address, so send it to the admin to_address_list = [ (admin_name, admin_addr), ] with mail.record_messages() as outbox: sent_cnt = 0 err_cnt = 0 err_list = [] result = True for who in to_address_list: #import pdb;pdb.set_trace() name = "" address = "" body_err_head = "" if type(who) is tuple: if len(who) == 1: # extend whp who = who[0] + (who[0], ) name = who[0] address = who[1] else: address = who #assume its a str name = who if not looksLikeEmailAddress(address) and looksLikeEmailAddress( name): # swap values temp = address address = name name = temp if not looksLikeEmailAddress(address): # still not a good address... address = admin_addr name = admin_name if not body: body = "" body_err_head = "Bad Addres: {}\r\r".format(who, ) subject = render_template_string(subject.strip(), context=context) #Start a message msg = Message(subject, sender=(from_sender, from_address), recipients=[(name, address)]) #Get the text body verson if body: if body_is_html: msg.html = render_template_string("{}{}".format( body_err_head, body, ), context=context) else: msg.body = render_template_string("{}{}".format( body_err_head, body, ), context=context) if html_template: msg.html = render_template(html_template, context=context) if text_template: msg.body = render_template(text_template, context=context) msg.reply_to = reply_to try: mail.send(msg) sent_cnt += 1 except Exception as e: mes = "Error Sending email" printException(mes, "error", e) err_cnt += 1 err_list.append("Error sending message to {} err: {}".format( who, str(e))) # End Loop if sent_cnt == 0: mes = "No messages were sent." result = False else: mes = "{} messages sent successfully.".format(sent_cnt) if err_cnt > 0: mes = mes + " {} messages had errors.\r\r{}".format( err_cnt, err_list) return (result, mes)
def test_silent_reset_failures(client): with mail.record_messages() as outbox: client.post('/reset', data=dict(email='*****@*****.**'), follow_redirects=True) assert len(outbox) == 0
def test_change_password_recovery_email(client, user_info, test_config): """The user can change their password recovery email.""" register_user(client, user_info) new_email = "*****@*****.**" assert new_email != user_info["email"] rv = client.get(url_for("user.edit_account")) data = dict( csrf_token=csrf_token(rv.data), oldpassword=user_info["password"], password="", confirm="", ) if email_validation_is_required(): data["email_required"] = new_email else: data["email_optional"] = new_email with mail.record_messages() as outbox: rv = client.post(url_for("do.edit_account"), data=data, follow_redirects=True) log_out_current_user(client) if email_validation_is_required(): message = outbox.pop() # Make sure that password recovery emails go to the former address # if the new one has not yet been confirmed. rv = client.get(url_for("user.password_recovery")) rv = client.post( url_for("user.password_recovery"), data=dict(csrf_token=csrf_token(rv.data), email=new_email, captcha="xyzzy"), ) assert len(outbox) == 0 rv = client.get(url_for("user.password_recovery")) rv = client.post( url_for("user.password_recovery"), data=dict( csrf_token=csrf_token(rv.data), email=user_info["email"], captcha="xyzzy", ), ) assert outbox.pop().send_to == {user_info["email"]} # Now click the confirm link. assert message.send_to == {new_email} soup = BeautifulSoup(message.html, "html.parser") token = soup.a["href"].split("/")[-1] rv = client.get(url_for("user.confirm_email_change", token=token), follow_redirects=True) else: assert len(outbox) == 0 # Verify password recovery email goes to the right place. with mail.record_messages() as outbox: rv = client.get(url_for("user.password_recovery")) rv = client.post( url_for("user.password_recovery"), data=dict( csrf_token=csrf_token(rv.data), email=user_info["email"], captcha="xyzzy", ), ) assert len(outbox) == 0 rv = client.get(url_for("user.password_recovery")) rv = client.post( url_for("user.password_recovery"), data=dict(csrf_token=csrf_token(rv.data), email=new_email, captcha="xyzzy"), ) assert outbox.pop().send_to == {new_email}