text: # -*- coding: utf-8 -*-
  """
      test_emails
      ~~~~~~~~~~~
  
      Email functionality tests
  """
  
  import pytest
  
  from flask_security import Security
  from flask_security.forms import LoginForm, RegisterForm, ConfirmRegisterForm, \
      SendConfirmationForm, PasswordlessLoginForm, ForgotPasswordForm, ResetPasswordForm, \
      ChangePasswordForm, TextField, PasswordField, email_required, email_validator, valid_user_email
  from flask_security.utils import capture_reset_password_requests, md5, string_types
  
  from utils import authenticate, init_app_with_options, populate_data
  
  
  @pytest.mark.recoverable()
  def test_async_email_task(app, client):
      app.mail_sent = False
  
      @app.security.send_mail_task
      def send_email(msg):
          app.mail_sent = True
  
      client.post('/reset', data=dict(email='matt@lp.com'))
      assert app.mail_sent is True
  
  
  def test_register_blueprint_flag(app, sqlalchemy_datastore):
      app.security = Security(app, datastore=Security, register_blueprint=False)
      client = app.test_client()
      response = client.get('/login')
      assert response.status_code == 404
  
  
  @pytest.mark.registerable()
  @pytest.mark.recoverable()
  @pytest.mark.changeable()
  def test_basic_custom_forms(app, sqlalchemy_datastore):
      class MyLoginForm(LoginForm):
          email = TextField('My Login Email Address Field')
  
      class MyRegisterForm(RegisterForm):
          email = TextField('My Register Email Address Field')
  
      class MyForgotPasswordForm(ForgotPasswordForm):
          email = TextField('My Forgot Email Address Field',
                            validators=[email_required, email_validator, valid_user_email])
  
      class MyResetPasswordForm(ResetPasswordForm):
          password = TextField('My Reset Password Field')
  
      class MyChangePasswordForm(ChangePasswordForm):
          password = PasswordField('My Change Password Field')
  
      app.security = Security(app,
                              datastore=sqlalchemy_datastore,
                              login_form=MyLoginForm,
                              register_form=MyRegisterForm,
                              forgot_password_form=MyForgotPasswordForm,
                              reset_password_form=MyResetPasswordForm,
                              change_password_form=MyChangePasswordForm)
  
      populate_data(app)
      client = app.test_client()
  
      response = client.get('/login')
      assert b'My Login Email Address Field' in response.data
  
      response = client.get('/register')
      assert b'My Register Email Address Field' in response.data
  
      response = client.get('/reset')
      assert b'My Forgot Email Address Field' in response.data
  
      with capture_reset_password_requests() as requests:
          response = client.post('/reset', data=dict(email='matt@lp.com'))
  
      token = requests[0]['token']
      response = client.get('/reset/' + token)
      assert b'My Reset Password Field' in response.data
  
      authenticate(client)
  
      response = client.get('/change')
      assert b'My Change Password Field' in response.data
  
  
  @pytest.mark.registerable()
  @pytest.mark.confirmable()
  def test_confirmable_custom_form(app, sqlalchemy_datastore):
      app.config['SECURITY_REGISTERABLE'] = True
      app.config['SECURITY_CONFIRMABLE'] = True
  
      class MyRegisterForm(ConfirmRegisterForm):
          email = TextField('My Register Email Address Field')
  
      class MySendConfirmationForm(SendConfirmationForm):
          email = TextField('My Send Confirmation Email Address Field')
  
      app.security = Security(app,
                              datastore=sqlalchemy_datastore,
                              send_confirmation_form=MySendConfirmationForm,
                              confirm_register_form=MyRegisterForm)
  
      client = app.test_client()
  
      response = client.get('/register')
      assert b'My Register Email Address Field' in response.data
  
      response = client.get('/confirm')
      assert b'My Send Confirmation Email Address Field' in response.data
  
  
  def test_passwordless_custom_form(app, sqlalchemy_datastore):
      app.config['SECURITY_PASSWORDLESS'] = True
  
      class MyPasswordlessLoginForm(PasswordlessLoginForm):
          email = TextField('My Passwordless Email Address Field')
  
      app.security = Security(app,
                              datastore=sqlalchemy_datastore,
                              passwordless_login_form=MyPasswordlessLoginForm)
  
      client = app.test_client()
  
      response = client.get('/login')
      assert b'My Passwordless Email Address Field' in response.data
  
  
  def test_addition_identity_attributes(app, sqlalchemy_datastore):
      init_app_with_options(app, sqlalchemy_datastore, **{
          'SECURITY_USER_IDENTITY_ATTRIBUTES': ('email', 'username')
      })
      client = app.test_client()
      response = authenticate(client, email='matt', follow_redirects=True)
      assert b'Hello matt@lp.com' in response.data
  
  
  def test_flash_messages_off(app, sqlalchemy_datastore, get_message):
      init_app_with_options(app, sqlalchemy_datastore, **{
          'SECURITY_FLASH_MESSAGES': False
      })
      client = app.test_client()
      response = client.get('/profile')
      assert get_message('LOGIN') not in response.data
  
  
  def test_invalid_hash_scheme(app, sqlalchemy_datastore, get_message):
      with pytest.raises(ValueError):
          init_app_with_options(app, sqlalchemy_datastore, **{
              'SECURITY_PASSWORD_HASH': 'bogus'
          })
  
  
  def test_change_hash_type(app, sqlalchemy_datastore):
      init_app_with_options(app, sqlalchemy_datastore, **{
          'SECURITY_PASSWORD_SCHEMES': ['bcrypt', 'plaintext']
      })
  
      app.config['SECURITY_PASSWORD_HASH'] = 'bcrypt'
      app.config['SECURITY_PASSWORD_SALT'] = 'salty'
  
      app.security = Security(app, datastore=sqlalchemy_datastore, register_blueprint=False)
  
      client = app.test_client()
  
      response = client.post('/login', data=dict(email='matt@lp.com', password='password'))
      assert response.status_code == 302
  
      response = client.get('/logout')
  
      response = client.post('/login', data=dict(email='matt@lp.com', password='password'))
      assert response.status_code == 302
  
  
  def test_md5():
      data = md5(b'hello')
      assert isinstance(data, string_types)
      data = md5(u'hellö')
      assert isinstance(data, string_types)
  
  
  @pytest.mark.settings(password_salt=u'öööööööööööööööööööööööööööööööööö',
                        password_hash='bcrypt')
  def test_password_unicode_password_salt(client):
      response = authenticate(client)
      assert response.status_code == 302
      response = authenticate(client, follow_redirects=True)
      assert b'Hello matt@lp.com' in response.data
  