Exemplo n.º 1
0
def test_sendEmail(app, baseMail):
    with mail.record_messages() as outbox:
        send_email(subject=baseMail['subject'],
                   sender=baseMail['sender'],
                   recipients=baseMail['recipients'],
                   cc=baseMail['cc'],
                   text_body=baseMail['text_body'],
                   html_body=baseMail['html_body'])
        assert len(outbox) == 1
        msg = outbox[0]
        assert msg.subject == 'Test'
        assert "hello world!" in msg.body
        assert "<p>hello world!<p>" in msg.html
        assert "*****@*****.**" in msg.recipients
        assert "*****@*****.**" in msg.cc
Exemplo n.º 2
0
def contactMessage():
    form = ContactMessageForm()
    form = form.initialize_fields(current_user)
    if form.validate_on_submit():
        recipients = current_app.config.get('ADMINS')
        sender = 'no-reply@' + current_app.config['MAIL_SERVER']
        subject = f"{form.category.data} / {form.subject.data}"
        text = render_template("message/email/contactMessage.txt", form=form)
        send_email(subject, sender, recipients, None, text, None)
        flash("Message sent.")
        return redirect(url_for('auth.welcome'))
    if current_user.is_authenticated and request.method == 'GET':
        form = form.initialize_values(current_user)
    return render_template('message/contact_message.html',
                           title="Contact Us",
                           form=form)
    def delete(self, id):

        appointment = Appointment.query.filter_by(appointment_id=id) \
            .first_or_404()

        csr = None if is_public_user() else CSR.find_by_username(
            g.oidc_token_info['username'])

        user: PublicUser = PublicUser.find_by_username(
            g.oidc_token_info['username']) if is_public_user() else None
        if is_public_user():
            # Check if it's a public user
            citizen = Citizen.find_citizen_by_id(appointment.citizen_id)
            if not citizen or citizen.citizen_id != appointment.citizen_id:
                abort(403)

        # Must call this prior to deleting from DB, so cannot
        # combine with repeated is_draft check below
        if not appointment.is_draft:
            SnowPlow.snowplow_appointment(None, csr, appointment,
                                          'appointment_delete')

        db.session.delete(appointment)
        db.session.commit()

        if not application.config['DISABLE_AUTO_REFRESH']:
            socketio.emit('appointment_delete', id)

        # Do not log snowplow events or send emails if it's a draft.
        if not appointment.is_draft:

            # If the appointment is public user's and if staff deletes it send email
            if csr:
                office = Office.find_by_id(appointment.office_id)

                # Send blackout email
                try:
                    pprint('Sending email for appointment cancellation')
                    send_email(
                        generate_ches_token(),
                        *get_cancel_email_contents(appointment, user, office,
                                                   office.timezone))
                except Exception as exc:
                    pprint(f'Error on token generation - {exc}')

        return {}, 204
Exemplo n.º 4
0
 def send_email_reminder(self, citizen, office_obj):
     if (citizen.notification_email):
         # code/function call to send first email notification,
         email_sent = False
         validate_check = True
         if citizen.reminder_flag and (citizen.reminder_flag == 2):
             validate_check = False
         if validate_check:
             email_sent = get_walkin_reminder_email_contents(
                 citizen, office_obj)
             if email_sent:
                 send_email(
                     request.headers['Authorization'].replace(
                         'Bearer ', ''), *email_sent)
                 flag_value = 1
                 if citizen.reminder_flag == 1:
                     flag_value = 2
                 citizen.reminder_flag = flag_value
                 citizen.notification_sent_time = datetime.utcnow()
     return citizen
Exemplo n.º 5
0
    def post(self, id):
        csr = CSR.find_by_username(g.jwt_oidc_token_info['username'])
        citizen = Citizen.query.filter_by(citizen_id=id).first()
        active_service_request = citizen.get_active_service_request()

        my_print("==> POST /citizens/" + str(citizen.citizen_id) +
                 '/add_to_queue, Ticket: ' + citizen.ticket_number)

        if active_service_request is None:
            return {"message": "Citizen has no active service requests"}

        #  Figure out what Snowplow call to make.  Default is addtoqueue
        snowplow_call = "addtoqueue"
        if len(citizen.service_reqs) != 1 or len(
                active_service_request.periods) != 1:
            active_period = active_service_request.get_active_period()
            if active_period.ps.ps_name == "Invited":
                snowplow_call = "queuefromprep"
            elif active_period.ps.ps_name == "Being Served":
                snowplow_call = "returntoqueue"
            else:
                #  TODO:  Put in a Feedback Slack/Service now call here.
                return {"message": "Invalid citizen/period state. "}

        active_service_request.add_to_queue(csr, snowplow_call)

        pending_service_state = SRState.get_state_by_name("Pending")
        active_service_request.sr_state_id = pending_service_state.sr_state_id
        # send walkin spot confirmation
        try:
            if (citizen.notification_phone or citizen.notification_email
                ) and not (citizen.reminder_flag) and not (
                    citizen.notification_sent_time):
                update_table = False
                try:
                    appointment_portal_url = application.config.get(
                        'APPOINTMENT_PORTAL_URL', '')
                    # Dynamic URL creations
                    url = ''
                    if appointment_portal_url and citizen.walkin_unique_id:
                        if appointment_portal_url.endswith('/'):
                            appointment_portal_url = appointment_portal_url[:
                                                                            -1]
                        url = "{}/{}/{}".format(appointment_portal_url,
                                                'walk-in-Q',
                                                citizen.walkin_unique_id)
                    # email
                    email_sent = False
                    if citizen.notification_email:
                        officeObj = Office.find_by_id(citizen.office_id)
                        print(
                            'Sending email for walk in spot confirmations to')
                        email_sent = get_walkin_spot_confirmation_email_contents(
                            citizen, url, officeObj)
                    # SMS
                    sms_sent = False
                    if citizen.notification_phone:
                        sms_sent = send_walkin_spot_confirmation_sms(
                            citizen, url,
                            request.headers['Authorization'].replace(
                                'Bearer ', ''))
                    if email_sent:
                        status = send_email(
                            request.headers['Authorization'].replace(
                                'Bearer ', ''), *email_sent)
                        update_table = True
                    if sms_sent:
                        update_table = True
                except Exception as exc:
                    pprint(f'Error on token generation - {exc}')
                    update_table = False
                if update_table:
                    citizen.reminder_flag = 0
                    citizen.notification_sent_time = datetime.utcnow()
        except Exception as err:
            logging.error('{}'.format(str(err)))
            pprint(err)

        db.session.add(citizen)
        db.session.commit()

        socketio.emit('update_customer_list', {}, room=csr.office.office_name)
        socketio.emit('citizen_invited', {},
                      room='sb-%s' % csr.office.office_number)
        result = self.citizen_schema.dump(citizen)
        socketio.emit('update_active_citizen',
                      result,
                      room=csr.office.office_name)

        return {
            'citizen': result,
            'errors': self.citizen_schema.validate(citizen)
        }, 200
Exemplo n.º 6
0
    def post(self):
        my_print("==> In AppointmentPost, POST /appointments/")
        json_data = request.get_json()
        if not json_data:
            return {
                "message": "No input data received for creating an appointment"
            }, 400

        # Should delete draft appointment, and free up slot, before booking.
        # Clear up a draft if one was previously created by user reserving this time.
        if json_data.get('appointment_draft_id'):
            draft_id_to_delete = int(json_data['appointment_draft_id'])
            Appointment.delete_draft([draft_id_to_delete])
            if not application.config['DISABLE_AUTO_REFRESH']:
                socketio.emit('appointment_delete', draft_id_to_delete)

        is_blackout_appt = json_data.get('blackout_flag', 'N') == 'Y'
        csr = None
        user = None
        office = None

        #  Create a citizen for later use.
        citizen = self.citizen_schema.load({}).data

        # Check if the appointment is created by public user. Can't depend on the IDP as BCeID is used by other users as well
        is_public_user_appointment = is_public_user()
        if is_public_user_appointment:
            office_id = json_data.get('office_id')
            service_id = json_data.get('service_id')
            user = PublicUser.find_by_username(g.oidc_token_info['username'])
            # Add values for contact info and notes
            json_data['contact_information'] = user.email
            telephone = f'. Phone: {user.telephone}' if user.telephone else ''
            json_data['comments'] = json_data.get('comments', '') + telephone

            citizen.user_id = user.user_id
            citizen.citizen_name = user.display_name

            office = Office.find_by_id(office_id)
            service = Service.query.get(int(service_id))

            # Validate if the same user has other appointments for same day at same office
            appointments = Appointment.find_by_username_and_office_id(
                office_id=office_id,
                user_name=g.oidc_token_info['username'],
                start_time=json_data.get('start_time'),
                timezone=office.timezone.timezone_name)
            if appointments and len(
                    appointments) >= office.max_person_appointment_per_day:
                return {
                    "code": "MAX_NO_OF_APPOINTMENTS_REACHED",
                    "message": "Maximum number of appointments reached"
                }, 400

            # Check for race condition
            start_time = parse(json_data.get('start_time'))
            end_time = parse(json_data.get('end_time'))
            if not AvailabilityService.has_available_slots(
                    office=office,
                    start_time=start_time,
                    end_time=end_time,
                    service=service):
                return {
                    "code":
                    "CONFLICT_APPOINTMENT",
                    "message":
                    "Cannot create appointment due to scheduling conflict.  Please pick another time."
                }, 400

        else:
            csr = CSR.find_by_username(g.oidc_token_info['username'])
            office_id = csr.office_id
            office = Office.find_by_id(office_id)

        citizen.office_id = office_id
        citizen.qt_xn_citizen_ind = 0
        citizen_state = CitizenState.query.filter_by(
            cs_state_name="Appointment booked").first()
        citizen.cs_id = citizen_state.cs_id
        citizen.start_time = datetime.now()
        citizen.service_count = 1

        db.session.add(citizen)
        db.session.commit()

        appointment, warning = self.appointment_schema.load(json_data)
        if is_public_user_appointment:
            appointment.citizen_name = user.display_name
            appointment.online_flag = True

        if warning:
            logging.warning("WARNING: %s", warning)
            return {"message": warning}, 422

        if appointment.office_id == office_id:
            appointment.citizen_id = citizen.citizen_id
            db.session.add(appointment)
            db.session.commit()

            # Generate CHES token
            try:
                ches_token = generate_ches_token()
            except Exception as exc:
                pprint(f'Error on token generation - {exc}')

            # If staff user is creating a blackout event then send email to all of the citizens with appointments for that period
            if is_blackout_appt:
                appointment_ids_to_delete = []
                appointments_for_the_day = Appointment.get_appointment_conflicts(
                    office_id, json_data.get('start_time'),
                    json_data.get('end_time'))
                for (cancelled_appointment, office, timezone,
                     user) in appointments_for_the_day:
                    if cancelled_appointment.appointment_id != appointment.appointment_id and not cancelled_appointment.checked_in_time:
                        appointment_ids_to_delete.append(
                            cancelled_appointment.appointment_id)

                        # Send blackout email
                        try:
                            pprint(
                                'Sending email for appointment cancellation due to blackout'
                            )
                            send_email(
                                ches_token,
                                *get_blackout_email_contents(
                                    appointment, cancelled_appointment, office,
                                    timezone, user))
                        except Exception as exc:
                            pprint(f'Error on email sending - {exc}')

                # Delete appointments
                if len(appointment_ids_to_delete) > 0:
                    Appointment.delete_appointments(appointment_ids_to_delete)

            else:
                # Send confirmation email
                try:
                    pprint('Sending email for appointment confirmation')
                    send_email(
                        ches_token,
                        *get_confirmation_email_contents(
                            appointment, office, office.timezone, user))
                except Exception as exc:
                    pprint(f'Error on email sending - {exc}')

            SnowPlow.snowplow_appointment(citizen, csr, appointment,
                                          'appointment_create')

            result = self.appointment_schema.dump(appointment)

            if not application.config['DISABLE_AUTO_REFRESH']:
                socketio.emit('appointment_create', result.data)

            return {"appointment": result.data, "errors": result.errors}, 201

        else:
            return {
                "The Appointment Office ID and CSR Office ID do not match!"
            }, 403
Exemplo n.º 7
0
    def put(self, id):
        json_data = request.get_json()

        if 'counter_id' not in json_data:
            json_data['counter_id'] = counter_id

        if not json_data:
            return {'message': 'No input data received for updating citizen'}, 400

        csr = CSR.find_by_username(g.jwt_oidc_token_info['username'])
        citizen = Citizen.query.filter_by(citizen_id=id).first()
        my_print("==> PUT /citizens/" + str(citizen.citizen_id) + '/, Ticket: ' + str(citizen.ticket_number))
        if not ((json_data.get('is_first_reminder', False) or json_data.get('is_second_reminder', False))):
            try:
                citizen = self.citizen_schema.load(json_data, instance=citizen, partial=True)
            except ValidationError as err:
                return {'message': err.messages}, 422
        else:
            try:
                office_obj = Office.find_by_id(citizen.office_id)
                if (citizen.notification_phone):
                    sms_sent = False
                    # code/function call to send sms notification,
                    sms_sent = send_walkin_reminder_sms(citizen, office_obj, request.headers['Authorization'].replace('Bearer ', ''))
                    if (json_data.get('is_first_reminder', False)):
                        if (sms_sent):
                            citizen.reminder_flag = 1
                            citizen.notification_sent_time = datetime.utcnow()
                    if (json_data.get('is_second_reminder', False)):
                        if (sms_sent):
                            citizen.reminder_flag = 2
                            citizen.notification_sent_time = datetime.utcnow()
                if (citizen.notification_email):
                    # code/function call to send first email notification,
                    email_sent = False
                    email_sent = get_walkin_reminder_email_contents(citizen, office_obj)
                    if email_sent:
                        send_email(request.headers['Authorization'].replace('Bearer ', ''), *email_sent)
                    if (json_data.get('is_first_reminder', False)):
                        if email_sent:
                            citizen.reminder_flag = 1
                            citizen.notification_sent_time = datetime.utcnow()
                    if (json_data.get('is_second_reminder', False)):
                        if email_sent:
                            citizen.reminder_flag = 2
                            citizen.notification_sent_time = datetime.utcnow()
                    
            except ValidationError as err:
                return {'message': err.messages}, 422

        db.session.add(citizen)
        db.session.commit()

        #  If this put request is the result of an appointment checkin, make a Snowplow call.
        if ('snowplow_addcitizen' in json_data) and (json_data['snowplow_addcitizen'] == True):
            SnowPlow.add_citizen(citizen, csr)

        result = self.citizen_schema.dump(citizen)
        citizen = Citizen.query.filter_by(citizen_id=citizen.citizen_id).first()
        socketio.emit('update_active_citizen', result, room=csr.office.office_name)

        return {'citizen': result,
                'errors': self.citizen_schema.validate(citizen)}, 200
Exemplo n.º 8
0
    def put(self, id):
        json_data = request.get_json()
        csr = None
        user = None

        if not json_data:
            return {
                "message": "No input data received for updating an appointment"
            }
        is_public_user_appt = is_public_user()

        # Should delete draft appointment, and free up slot, before booking.
        # Clear up a draft if one was previously created by user reserving this time.
        if json_data.get('appointment_draft_id'):
            draft_id_to_delete = int(json_data['appointment_draft_id'])
            Appointment.delete_draft([draft_id_to_delete])
            if not application.config['DISABLE_AUTO_REFRESH']:
                socketio.emit('appointment_delete', draft_id_to_delete)

        if is_public_user_appt:
            office_id = json_data.get('office_id')
            office = Office.find_by_id(office_id)
            # user = PublicUser.find_by_username(g.oidc_token_info['username'])
            # citizen = Citizen.find_citizen_by_username(g.oidc_token_info['username'], office_id)
            # Validate if the same user has other appointments for same day at same office
            appointments = Appointment.find_by_username_and_office_id(
                office_id=office_id,
                user_name=g.oidc_token_info['username'],
                start_time=json_data.get('start_time'),
                timezone=office.timezone.timezone_name,
                appointment_id=id)
            if appointments and len(
                    appointments) >= office.max_person_appointment_per_day:
                return {
                    "code": "MAX_NO_OF_APPOINTMENTS_REACHED",
                    "message": "Maximum number of appoinments reached"
                }, 400

            # Check for race condition
            start_time = parse(json_data.get('start_time'))
            end_time = parse(json_data.get('end_time'))
            service_id = json_data.get('service_id')
            service = Service.query.get(int(service_id))
            if not AvailabilityService.has_available_slots(
                    office=office,
                    start_time=start_time,
                    end_time=end_time,
                    service=service):
                return {
                    "code":
                    "CONFLICT_APPOINTMENT",
                    "message":
                    "Cannot create appointment due to scheduling conflict.  Please pick another time."
                }, 400

        else:
            csr = CSR.find_by_username(g.oidc_token_info['username'])
            office_id = csr.office_id
            office = Office.find_by_id(office_id)

        appointment = Appointment.query.filter_by(appointment_id=id) \
            .filter_by(office_id=office_id) \
            .first_or_404()

        # If appointment is not made by same user, throw error
        if is_public_user_appt:
            citizen = Citizen.find_citizen_by_id(appointment.citizen_id)
            user = PublicUser.find_by_username(g.oidc_token_info['username'])
            # Should just match based on appointment_id and other info.  Can't have proper auth yet.
            if citizen.user_id != user.user_id:
                abort(403)

        appointment, warning = self.appointment_schema.load(
            json_data, instance=appointment, partial=True)

        if warning:
            logging.warning("WARNING: %s", warning)
            return {"message": warning}, 422

        db.session.add(appointment)
        db.session.commit()

        # Send confirmation email
        try:
            pprint('Sending email for appointment update')
            send_email(
                generate_ches_token(),
                *get_confirmation_email_contents(appointment, office,
                                                 office.timezone, user))
        except Exception as exc:
            pprint(f'Error on token generation - {exc}')

        #   Make Snowplow call.
        schema = 'appointment_update'
        if "checked_in_time" in json_data:
            schema = 'appointment_checkin'

        if not appointment.is_draft:
            SnowPlow.snowplow_appointment(None, csr, appointment, schema)

        result = self.appointment_schema.dump(appointment)

        if not application.config['DISABLE_AUTO_REFRESH']:
            socketio.emit('appointment_update', result.data)

        return {"appointment": result.data, "errors": result.errors}, 200
 def async_email(subject, email, sender, body):
     send_email(subject, email, sender, body)
Exemplo n.º 10
0
 def async_email(subject, email, sender, body):
     return send_email(subject, email, sender, body)