Exemplo n.º 1
0
    def do(self):
        token = self.request.get('token')
        new_password = self.request.get('new_password')

        # Check the token
        user = self.api.check_reset_password_token(token)

        if user is None:
            return {'success': True, 'data': 'invalid_token'}

        # Change the user's password.
        user.hashed_password = util.hash_password(new_password)
        user.put()

        # Clear existing tokens.
        self.api.clear_reset_password_tokens(user.id)

        # Alert the user that their password has been changed.
        mandrill.send(
            to_address=user.login_email,
            subject=config.change_password_subject,
            body=config.change_password_body,
        )

        logging.info('api_handlers.ResetPasswordHandler')
        logging.info('sending an email to: {}'.format(user.login_email))

        return {'success': True, 'data': 'changed'}
Exemplo n.º 2
0
    def post(self):
        body = json.loads(self.request.body)

        if 'organization' in body:
            organization = body['organization']
        else:
            organization = 'N/A'

        message = u"""
Message from {} <{}>:

Organization: {}

Message:

{}

____

-- Sent via Contact Form --
""".format(body['name'], body['email'], organization, body['message'])

        # Send a message to the PERTS staff via @contact.
        mandrill.send(
            to_address='',
            subject='Inquiry from PERTS.net',
            body=mandrill.render_markdown(message),
        )

        logging.info('api_handlers.SendContactEmailHandler')
        logging.info('sending an email to: ')

        return {'success': True, 'data': ''}
Exemplo n.º 3
0
    def get(self):
        md_id = self.request.get('md_id')
        md_email = self.request.get('md_email')

        mandrill.send(
            to_address=config.from_server_email_address,
            subject="Please Re-subscribe!",
            body=("&#128007; Heyo,<br><br>Someone requested they be "
                  "re-subscribed to the MSK mailing list. We have to do this "
                  "manually. Here's their info.<br><br><b>Email:</b> {}<br>"
                  "<b>ID:</b> {}<br><br>Thanks!!".format(md_email, md_id)),
        )

        self.write('resubscribe.html', )
Exemplo n.º 4
0
    def send(self, emails):
        to_addresses = []
        for email in emails:
            if self.we_are_spamming(email):
                # Do not send
                # This user has already recieved very recent emails

                # Debugging info
                logging.error("We are spamming {}:\n{}".format(
                    email.to_address, email.to_dict()))
            elif email.to_address in to_addresses:
                # Do not send
                # We don't send multiple emails to an address per 'send'

                # Debugging info
                logging.error("We are spamming {}:\n{}".format(
                    email.to_address, email.to_dict()))
            else:
                # Not spam! Let's send it
                to_addresses.append(email.to_address)

                # Debugging info
                logging.info(u"sending email: {}".format(email.to_dict()))
                logging.info(u"to: {}".format(email.to_address))
                logging.info(u"subject: {}".format(email.subject))

                if email.body:
                    logging.info(u"body:\n{}".format(email.body))
                    mandrill.send(
                        to_address=email.to_address,
                        subject=email.subject,
                        body=email.body,
                        template_data=email.template_data,
                    )

                elif email.template:
                    logging.info(u"template: {}".format(email.template))
                    mandrill.send(
                        to_address=email.to_address,
                        subject=email.subject,
                        template=email.template,
                        template_data=email.template_data,
                    )

                email.was_sent = True
                logging.info("""Sent successfully!""")

            # Note that we are attempting to send so that we don't keep attempting.
            email.was_attempted = True
            email.put()
Exemplo n.º 5
0
    def check_status_update(self, **kwargs):
        """Checks the status of an updated page to determine if the creator
        should be notified of approval or rejection.
        """
        new_status = kwargs.get('status', None)
        now_reviewed = new_status in ('approved', 'rejected')
        changing = self.status != new_status
        if not now_reviewed or not changing:
            return

        authors = User.get_by_id(self.authors) or []
        for author in authors:
            short_name = author.first_name or ''
            full_name = author.full_name
            if new_status == 'approved':
                # Send acceptance message
                # @todo: add name to subject line
                mandrill.send(
                    to_address=author.email,
                    subject="Your page upload is approved!",
                    template="accepted_notification.html",
                    template_data={
                        'short_name': short_name,
                        'full_name': full_name,
                        'entity_name': self.title,
                        'entity_url': '/pages/' + self.short_uid,
                        'domain':
                        'https://{}'.format(os.environ['HOSTING_DOMAIN']),
                        'year': datetime.date.today().year,
                    },
                )

            else:
                # Send rejection message
                mandrill.send(
                    to_address=author.email,
                    subject="We couldn't approve your page...",
                    template="rejected_notification.html",
                    template_data={
                        'short_name': short_name,
                        'full_name': full_name,
                        'entity_name': self.title,
                        'entity_url': '/pages/' + self.short_uid,
                        'edit_url': '/pages/edit/' + self.short_uid,
                        'domain':
                        'https://{}'.format(os.environ['HOSTING_DOMAIN']),
                        'year': datetime.date.today().year,
                    },
                )
Exemplo n.º 6
0
    def mail_log(self):
        body = self.body + self.get_recent_log()
        subject = self.subject + self.get_error_summary()
        # Ignore the normal email queueing / spam-prevention system because the
        # addressees are devs, and they can customize the deluge themselves.
        for to in self.to_addresses:
            # We want to send this immediately, not in batches.
            mandrill.send(
                to_address=to,
                subject=subject,
                body=body,
            )

        self.last_email = self.now
        return (subject, body)
Exemplo n.º 7
0
    def set_password(self, new_password):
        """May raise util.BadPassword."""
        logging.info("Setting new password {} for user {}.".format(
            new_password, self))

        self.hashed_password = util.hash_password(new_password)

        # Alert the user that their password has been changed.
        mandrill.send(
            to_address=self.email,
            subject="Your Mindset Kit password has been changed.",
            template="change_password.html",
        )

        logging.info('User.set_password queueing an email to: {}'.format(
            self.email))
Exemplo n.º 8
0
    def post(self):
        address = self.request.get('address')
        private_key = self.request.get('private_key')
        metric = self.request.get('metric')

        if address and private_key and metric:
            private_key.encode('ascii')  # handle unicode properly
            public_key = util.Keys().get_public(private_key)
            root = "http://survey.perts.net"
            take_link = root + '/take/' + metric + '?public_key=' + public_key
            results_link = root + '/results/' + private_key
            message = self.render_str('email.html',
                                      address=address,
                                      take_link=take_link,
                                      results_link=results_link,
                                      metric=metric)

            result = mandrill.send(
                to_address=address,
                subject="Mindset Meter Study Links",
                body=message,
            )
            if result:
                logging.info('Email sent to ' + address +
                             ' with the message ' + message)
            self.write_json({'ok': True})

        else:
            message = "address, private_key, and metric are necessary to email a user"
            logging.error(message)
            self.write_json({'error': message})
Exemplo n.º 9
0
    def create(klass, **kwargs):
        feedback = super(klass, klass).create(**kwargs)

        # Email interested parties about new feedback :)
        mandrill.send(to_address=config.feedback_recipients,
                subject="Mindset Kit Feedback!",
                template="feedback_notification.html",
                template_data={'feedback': feedback,
                               'domain': os.environ['HOSTING_DOMAIN']},
            )

        logging.info('model.Feedback queueing an email to: {}'
                     .format(config.feedback_recipients))
        

        return feedback
Exemplo n.º 10
0
    def set_password(self, new_password):
        """May raise BadPassword."""
        logging.info("Setting new password {} for user {}.".format(
            new_password, self))

        self.hashed_password = self.hash_password(new_password)

        # Alert the user that their password has been changed.
        mandrill.send(
            to_address=self.email,
            subject="Your BELE Library password has been changed.",
            template="change_password.html",
            template_data={
                'domain': 'https://{}'.format(os.environ['HOSTING_DOMAIN']),
                'year': datetime.date.today().year,
            },
        )
Exemplo n.º 11
0
    def post(self):
        params = self.get_params()
        logging.info(
            "Sending reflection email to user with params: {}".format(params))
        current_date = datetime.date.today().strftime("%B %d, %Y")

        # Send rejection message
        mandrill.send(
            to_address=params['to_address'],
            subject=
            "Belonging for Educators - What does belonging look like in my classroom?",
            template="reflection_email.html",
            template_data={
                'questions': params['questions'],
                'reflection': params['reflection'],
                'response_date': current_date,
                'domain': os.environ['HOSTING_DOMAIN']
            },
        )
Exemplo n.º 12
0
    def check_status_update(self, **kwargs):
        """Checks the status of an updated practice to determine if the creator
        should be notified of approval or rejection

        Only triggered if pending set from True to False (prevents duplicates)
        """
        if (self.pending is True and kwargs.get('pending') is False):

            creator = self.get_parent_user()
            short_name = creator.first_name if creator.first_name else ''
            full_name = creator.full_name
            if (self.listed is False and kwargs.get('listed') is True):
                # Send acceptance message
                # @todo: add name to subject line
                mandrill.send(
                    to_address=creator.email,
                    subject="Your practice upload is approved!",
                    template="accepted_notification.html",
                    template_data={
                        'short_name': short_name,
                        'full_name': full_name,
                        'practice_name': self.name,
                        'practice_url': '/practices/' + self.short_uid,
                        'domain': os.environ['HOSTING_DOMAIN']
                    },
                )

            else:
                # Send rejection message
                mandrill.send(
                    to_address=creator.email,
                    subject="We couldn't approve your practice...",
                    template="rejected_notification.html",
                    template_data={
                        'short_name': short_name,
                        'full_name': full_name,
                        'practice_name': self.name,
                        'practice_url': '/practices/' + self.short_uid,
                        'edit_url': '/practices/edit/' + self.short_uid,
                        'domain': os.environ['HOSTING_DOMAIN']
                    },
                )
Exemplo n.º 13
0
    def send_reminders(self):
        """Check for teachers that need reminders and add them to the email
        queue.
        See id_model@Reminder for details.
        """

        # already sent?
        # check if today's reminders have already been sent
        # if so, return.
        today = Reminder.get_pst_date()
        already_queued = self.api.get('Reminder',
                                      {'pst_date': today.isoformat()})
        if already_queued:
            return {'message': 'Reminders already queued to email'}

        # get reminders
        reminders = self.get_reminders_by_date(today.isoformat())

        # send a summary to perts admins
        self._send_reminder_summary(reminders)

        # queue emails
        for r in reminders:

            to = r['to_address'] or config.to_dev_team_email_address

            mandrill.send(
                to_address=to,
                subject=r['subject'],
                body=r['body'],
            )

        # save as already sent
        todays_reminder = Reminder.create(pst_date=today.isoformat())
        todays_reminder.put()

        return {
            'message': 'Reminders sent',
            'reminders': reminders,
            'date': today.isoformat()
        }
Exemplo n.º 14
0
    def create(klass, **kwargs):
        """Sends email to interested parties.
        """
        practice = super(klass, klass).create(**kwargs)

        # Email interested parties that a practice has been uploaded.
        mandrill.send(
            to_address=config.practice_upload_recipients,
            subject="Practice Uploaded to Mindset Kit!",
            template="practice_upload_notification.html",
            template_data={
                'user': practice.get_parent_user(),
                'practice': practice,
                'domain': os.environ['HOSTING_DOMAIN']
            },
        )

        logging.info('model.Practice queueing an email to: {}'.format(
            config.practice_upload_recipients))

        return practice
Exemplo n.º 15
0
    def _send_reminder_summary(self, reminders):
        # send summary to perts team
        body = """

To whom it may concern,

Lots of reminders today (or not)! The full list of emails is below.

Recreationally Yours,<br />
Yellowstone

----

{}
""".format(''.join([self._reminder_summary(r) for r in reminders]))

        mandrill.send(
            to_address=config.reminder_summary_recipients,
            subject="{} Reminder Emails sent today".format(len(reminders)),
            body=mandrill.render_markdown(body),
        )
Exemplo n.º 16
0
    def post(self):
        # Reply to is optional
        reply_to = self.request.get('reply_to')
        logging.error('reply to is : {}'.format(reply_to))
        message = self.request.get('message')
        to_address = config.from_server_email_address

        message = self.render_str(
            'email_feedback.html',
            reply_to=reply_to,
            message=message,
        )

        mandrill.send(
            to_address=to_address,
            subject="Feedback on the mindset meter",
            body=message,
        )

        logging.info('Feedback Email sent to ' + to_address +
                     ' with the message ' + message)
        self.write_json({'ok': True})
Exemplo n.º 17
0
    def do(self):
        new_password = self.request.get('new_password') or None
        auth_response = self.authenticate(
            auth_type='direct',
            username=self.request.get('username'),
            password=self.request.get('current_password'))
        if auth_response is False or auth_response is None:
            return {'success': True, 'data': 'invalid_credentials'}
        user = auth_response
        user.hashed_password = util.hash_password(new_password)
        user.put()

        # Alert the user that their password has been changed.
        mandrill.send(to_address=user.login_email,
                      subject=config.change_password_subject,
                      body=mandrill.render_markdown(
                          config.change_password_body))

        logging.info('api_handlers.ChangePasswordHandler')
        logging.info('sending an email to: {}'.format(user.login_email))

        return {'success': True, 'data': 'changed'}
Exemplo n.º 18
0
    def get(self):
        # ensure this email address belongs to a known user
        email = self.request.get('email').lower()

        # Look up users by auth_id because that's how they log in;
        # there are other kinds of auth type ('google', 'facebook') that we
        # wouldn't want returned.
        user = User.query(User.auth_id == 'own:' + email).get()

        if user:
            # then this email address is valid; proceed with send

            # deactivate any existing reset tokens
            ResetPasswordToken.clear_all_tokens_for_user(user)

            # create a new token for them
            new_token = ResetPasswordToken.create(user_id=user.uid)
            new_token.put()

            mandrill.send(
                to_address=email,
                subject="Password reset requested.",
                template="forgot_password.html",
                template_data={
                    'token': new_token.token(),
                    'domain': os.environ['HOSTING_DOMAIN']
                },
            )

            logging.info(
                'ForgotPassword queueing an email to: {}'.format(email))

            self.write('sent')

        else:
            logging.info(
                'ForgotPassword invalid email address: {}'.format(email))
            self.write('not_sent')
Exemplo n.º 19
0
    def do(self):
        # ensure this email address belongs to a known user
        email = self.request.get('email').lower()

        # Look up users by auth_id because that's how they log in;
        # there are other kinds of auth type ('google', 'public') that we
        # wouldn't want returned.
        result = self.internal_api.get('user', {'auth_id': 'direct_' + email})

        if len(result) is 1 and result[0].is_test is False:
            # then this email address is valid; proceed with send
            user = result[0]

            # deactivate any existing reset tokens
            self.api.clear_reset_password_tokens(user.id)

            # create a new token for them
            new_token = ResetPasswordToken.create(user=user.id)
            new_token.put()

            # and email them about it
            link = '/reset_password/' + new_token.token()
            mandrill.send(
                to_address=email,
                subject=config.forgot_password_subject,
                body=mandrill.render_markdown(
                    config.forgot_password_body.format(link)),
            )

            logging.info(
                'ForgotPasswordHandler sending an email to: {}'.format(email))

            return {'success': True, 'data': 'sent'}
        else:
            logging.info(
                'ForgotPasswordHandler invalid email: {}'.format(email))
            return {'success': True, 'data': 'not_sent'}
Exemplo n.º 20
0
    def register(self,
                 auth_type,
                 first_name=None,
                 last_name=None,
                 email=None,
                 password=None,
                 facebook_access_token=None,
                 should_subscribe=True):
        """Logs in users and registers them if they're new.

        Returns:
          User entity                 registration successful
          'credentials_missing'       looked for credentials but didn't find
                                      any of the appropriate kind.
          'email_exists:[auth_type]'  a user with that email already exists,
                                      with the specified auth type. In rare
                                      cases, we may know the email exists
                                      already, but not be able to query
                                      for it (gotta love eventual consistency),
                                      in which case the auth type will be
                                      'unknown'.
        """
        if auth_type not in config.auth_types:
            raise Exception("Bad auth_type: {}.".format(auth_type))
        if auth_type == 'own':
            if None in [email, password]:
                return 'credentials_missing'
            creation_kwargs = {
                'first_name': first_name,
                'last_name': last_name,
                'email': email,
                'auth_id': User.get_auth_id(auth_type, email),
                'hashed_password': util.hash_password(password),
            }

        # These are the third party identity providers we currently know
        # how to handle. See util_handlers.BaseHandler.get_third_party_auth().
        elif auth_type in ['google', 'facebook']:
            creation_kwargs, error = self.get_third_party_auth(
                auth_type, facebook_access_token)
            if error:
                return error
            elif not creation_kwargs:
                return 'credentials_missing'

        # Make it easy for devs to become admins.
        if auth_type == 'google' and app_engine_users.is_current_user_admin():
            creation_kwargs['is_admin'] = True

        # Pass through subscription parameter
        # Currently defaults true (planning to change later)
        creation_kwargs['should_subscribe'] = should_subscribe

        email = creation_kwargs['email']

        # Try to register the user. If a user with the same email already
        # exists, we'll get a DuplicateUser exception.
        try:
            user = User.create(**creation_kwargs)
        except DuplicateUser:
            # Attempt to retrieve the user entity which already exists.
            user = User.query(User.email == email).get()
            logging.info('Exception case with UserRegister')
            return 'email_exists:' + (user.auth_type if user else 'unknown')

        logging.info("BaseHandler created user: {}".format(user))

        # Registration succeeded; set them up.
        user.put()

        self.log_in(user)

        short_name = user.first_name if user.first_name else ''
        if user.first_name and user.last_name:
            full_name = user.first_name + ' ' + user.last_name
        else:
            full_name = user.username

        # Send them an email to confirm that they have registered.
        mandrill.send(
            to_address=email,
            subject="Welcome to Mindset Kit",
            template="signup_confirmation.html",
            template_data={
                'short_name': short_name,
                'full_name': full_name,
                'user': user,
                'domain': os.environ['HOSTING_DOMAIN']
            },
        )

        logging.info(u'BaseHandler.register()')
        logging.info(u"Sending an email to: {}.".format(email))

        return user
Exemplo n.º 21
0
    def do(self):
        params = util.get_request_dictionary(self.request)

        # Check that the requested program allows public registration.
        program = self.internal_api.get_from_path('program', params['program'])
        program_config = Program.get_app_configuration(program.abbreviation)
        if not getattr(program_config, 'public_registration', False):
            user = self.get_current_user()
            logging.error("User {} attempted public registration on program "
                          "{}, but it isn't allowed.".format(
                              user, program.abbreviation))

        # Create a school admin based on the user's information.
        # They get the special auth_type 'public', preventing them from
        # appearing in sign-in queries or reset-password queries.
        # However, the user entity will still hold data and be associated with
        # the created schools.
        params['user']['user_type'] = 'school_admin'
        params['user']['auth_id'] = 'public_' + params['user']['login_email']
        school_admin = self.internal_api.create('user', params['user'])

        # If the school already exists, use the id to find the right cohort.
        if 'existing_school_id' in params:
            s_id = params['existing_school_id']
            cohort_list = self.internal_api.get('cohort',
                                                {'assc_school_list': s_id})
            if len(cohort_list) is not 1:
                raise Exception("Problem with public registration: found {} "
                                "cohorts for school {}".format(
                                    len(cohort_list), s_id))
            cohort = cohort_list[0]
            school = None
            classroom = None
            activities = None

        # Otherwise, create a school, cohort, and classroom based on the
        # provided data.
        else:
            school = self.internal_api.create('school', params['new_school'])
            cohort = self.internal_api.create(
                'cohort', {
                    'name': params['new_school']['name'],
                    'school': school.id,
                    'program': program.id,
                    'promised_students': params['promised_students'],
                })
            classroom = self.internal_api.create(
                'classroom', {
                    'name': 'All Students',
                    'program': program.id,
                    'cohort': cohort.id,
                    'user': school_admin.id,
                })
            activities = self.internal_api.init_activities(
                'student',
                school_admin.id,
                program.id,
                cohort_id=cohort.id,
                classroom_id=classroom.id)

        # Whether the cohort is new or exisiting, make the new user owner of it
        self.internal_api.associate('set_owner', school_admin, cohort)

        # Send an email to the user with all the information they need to
        # participate.
        mandrill.send(to_address=school_admin.login_email,
                      subject=program_config.registration_email_subject,
                      body=mandrill.render_markdown(
                          program_config.registration_email_body),
                      template_data={
                          'email': school_admin.login_email,
                          'cohort_id': cohort.id
                      })

        logging.info('api_handlers.CreatePublicSchoolHandler')
        logging.info('sending an email to: {}'.format(
            school_admin.login_email))

        return {
            'success': True,
            'data': {
                'user':
                school_admin.to_dict(),
                'program':
                program.to_dict(),
                'school':
                school.to_dict() if school else None,
                'cohort':
                cohort.to_dict(),
                'classroom':
                classroom.to_dict() if classroom else None,
                'activities':
                ([a.to_dict() for a in activities] if activities else None),
            }
        }
Exemplo n.º 22
0
    def create(klass, **kwargs):
        if ('practice_id' not in kwargs) and ('lesson_id' not in kwargs) and (
                'page_id' not in kwargs):
            raise Exception(
                'Must specify a practice, lesson, or page when '
                'creating a comment. Received kwargs: {}'.format(kwargs))
        comment = super(klass, klass).create(**kwargs)

        # For email notifications
        content_url = '/'
        content = None

        if comment.page_id:
            page = Page.get_by_id(comment.page_id)
            if page is not None:
                page.num_comments += 1
                page.put()

                # For email
                content = page
                content_url = '/pages/{}'.format(page.short_uid)

                # Send email to creator
                author_ids = page.authors
                commenter = comment.get_parent_user()
                authors = User.get_by_id(author_ids) or []

                for author in authors:

                    # logic to not email yourself...
                    if author != commenter.email:

                        short_name = author.first_name or ''
                        full_name = author.full_name
                        commenter_image_url = commenter.profile_image

                        # Uses Email model to queue email and prevent spam
                        email = Email.create(
                            to_address=author.email,
                            subject=
                            "Someone commented on your BELE Library upload",
                            template="comment_creator_notification.html",
                            template_data={
                                'short_name':
                                short_name,
                                'full_name':
                                full_name,
                                'commenter_name':
                                commenter.full_name,
                                'commenter_image_url':
                                commenter_image_url,
                                'content_name':
                                content.title,
                                'comment_body':
                                comment.body,
                                'content_url':
                                content_url,
                                'domain':
                                'https://{}'.format(
                                    os.environ['HOSTING_DOMAIN']),
                                'year':
                                datetime.date.today().year,
                            },
                        )

                        email.put()

                    # Send email to any users @replied to
                    usernames = re.search('\@(\w+)', comment.body)

                    if usernames is not None:
                        username = usernames.group(0).split('@')[1]

                        # Fetch user from username and send email message
                        replied_to = User.query(
                            User.username == username).fetch(1)
                        if replied_to:
                            replied_to = replied_to[0]

                            short_name = replied_to.first_name or ''
                            full_name = replied_to.full_name
                            commenter_image_url = commenter.profile_image

                            # Uses Email model to queue email and prevent spam
                            email = Email.create(
                                to_address=replied_to.email,
                                subject=
                                "Someone replied to you on BELE Library",
                                template="comment_reply_notification.html",
                                template_data={
                                    'short_name':
                                    short_name,
                                    'full_name':
                                    full_name,
                                    'commenter_name':
                                    commenter.full_name,
                                    'commenter_image_url':
                                    commenter_image_url,
                                    'content_name':
                                    content.title,
                                    'comment_body':
                                    comment.body,
                                    'content_url':
                                    content_url,
                                    'domain':
                                    'https://{}'.format(
                                        os.environ['HOSTING_DOMAIN']),
                                    'year':
                                    datetime.date.today().year,
                                },
                            )

                            email.put()

        # Email interested team members that a comment has been created
        mandrill.send(
            to_address=config.comment_recipients,
            subject="New Comment on BELE Library!",
            template="comment_notification.html",
            template_data={
                'comment': comment,
                'user': comment.get_parent_user(),
                'content_name': content.title,
                'content_url': content_url,
                'domain': 'https://{}'.format(os.environ['HOSTING_DOMAIN'])
            },
        )

        logging.info('model.Comment queueing an email to: {}'.format(
            config.comment_recipients))

        return comment
Exemplo n.º 23
0
    def register(self, program_id, auth_type, username=None, password=None, cohort_id=None):
        """Logs in users and registers them if they're new.

        Raises exceptions when the system appears to be broken (e.g. redundant
        users).

        Returns tuple(
            user - mixed, False when given non-sensical data by users (e.g.
                registering an existing email under a new auth type) or
                matching user entity,
            user_is_new - bool, True if user was newly registered
        )

        """
        user_is_new = False

        if auth_type not in config.allowed_auth_types:
            raise Exception("Bad auth_type: {}.".format(auth_type))
        if auth_type == 'direct':
            if None in [username, password]:
                raise Exception("Credentials incomplete.")
            creation_kwargs = {
                'login_email': username,
                'auth_id': 'direct_' + username,
                'plaintext_password': password,  # it WILL be hashed later
            }

        # These are the third party identity providers we currently know
        # how to handle. See util_handlers.BaseHandler.get_third_party_auth().
        elif auth_type in ['google']:
            # may raise CredentialsMissing
            creation_kwargs = self.get_third_party_auth(auth_type)

        # Check that the user hasn't already registered in two ways.

        # 1) If the email matches but the auth type is different, we reject
        #    the request to register so the UI can warn the user.
        email_match_params = {'login_email': creation_kwargs['login_email']}
        email_matches = self.internal_api.get('user', email_match_params)
        for user in email_matches:
            if user.auth_type() != auth_type:
                user = False
                return (user, user_is_new)

        # 2) If the auth_id matches, they tried to register when they should
        #    have logged in. Just log them in.
        auth_match_params = {'auth_id': creation_kwargs['auth_id']}
        auth_matches = self.internal_api.get('user', auth_match_params)
        if len(auth_matches) == 1:
            # they already have an account
            user = auth_matches[0]

        # This user hasn't already registered. Register them.
        elif len(auth_matches) == 0:
            user_is_new = True

            # Having collected the user's information, build a user object.
            creation_kwargs['user_type'] = 'teacher'
            # Include the program id as an initial relationship (see
            # config.optional_associations).
            creation_kwargs['program'] = program_id
            user = self.api.create('user', creation_kwargs)

            # Refresh the api with the user's new privileges.
            self.api = Api(user)
            # Send them an email to confirm that they have registered.
            # The email text is hard coded in the program app.
            program = self.api.get_from_path('program', program_id)
            program_conf = Program.get_app_configuration(program.abbreviation)
            mandrill.send(
                to_address=creation_kwargs['login_email'],
                subject=program_conf.registration_email_subject,
                body=mandrill.render_markdown(
                    program_conf.registration_email_body),
                template_data={'email': creation_kwargs['login_email'],
                               'cohort_id': cohort_id}
            )

            logging.info('url_handlers.BaseHandler.register()')
            logging.info('sending an email to: {}'
                         .format(creation_kwargs['login_email']))

        # There's a big problem.
        else:
            logging.error("Two matching users! {}".format(auth_match_params))
            # Sort the users by modified time, so we take the most recently
            # modified one.
            auth_matches = sorted(
                auth_matches, key=lambda u: u.modified, reverse=True)
            user = auth_matches[0]

        # Sign in the user.
        self.session['user'] = user.id

        return (user, user_is_new)