예제 #1
0
def send_user_reset_password():
    email, errors = email_data_request_schema.load(request.get_json())

    user_to_send_to = get_user_by_email(email['email'])

    if user_to_send_to.blocked:
        return jsonify({'message': 'cannot reset password: user blocked'}), 400

    template = dao_get_template_by_id(current_app.config['PASSWORD_RESET_TEMPLATE_ID'])
    service = Service.query.get(current_app.config['NOTIFY_SERVICE_ID'])
    saved_notification = persist_notification(
        template_id=template.id,
        template_version=template.version,
        recipient=email['email'],
        service=service,
        personalisation={
            'user_name': user_to_send_to.name,
            'url': _create_reset_password_url(user_to_send_to.email_address)
        },
        notification_type=template.template_type,
        api_key_id=None,
        key_type=KEY_TYPE_NORMAL,
        reply_to_text=service.get_default_reply_to_email_address()
    )

    send_notification_to_queue(saved_notification, False, queue=QueueNames.NOTIFY)

    return jsonify({}), 204
예제 #2
0
def send_support_email(user_id):
    to, errors = support_email_data_schema.load(request.get_json())
    template = dao_get_template_by_id(
        current_app.config['CONTACT_US_TEMPLATE_ID'])
    service = Service.query.get(current_app.config['NOTIFY_SERVICE_ID'])

    saved_notification = persist_notification(
        template_id=template.id,
        template_version=template.version,
        recipient=to['email'],
        service=service,
        personalisation={
            'user': to['email'],
            'message': to['message'],
            'sender_email': to["sender"] if "sender" in to else "",
            'support_type': to["support_type"] if "support_type" in to else ""
        },
        notification_type=template.template_type,
        api_key_id=None,
        key_type=KEY_TYPE_NORMAL,
        reply_to_text=service.get_default_reply_to_email_address())

    send_notification_to_queue(saved_notification,
                               False,
                               queue=QueueNames.NOTIFY)

    return jsonify({}), 204
예제 #3
0
def send_new_user_email_verification(user_id):
    # when registering, we verify all users' email addresses using this function
    user_to_send_to = get_user_by_id(user_id=user_id)

    template = dao_get_template_by_id(current_app.config['NEW_USER_EMAIL_VERIFICATION_TEMPLATE_ID'])
    service = Service.query.get(current_app.config['NOTIFY_SERVICE_ID'])

    saved_notification = persist_notification(
        template_id=template.id,
        template_version=template.version,
        recipient=user_to_send_to.email_address,
        service=service,
        personalisation={
            'name': user_to_send_to.name,
            'url': _create_verification_url(user_to_send_to)
        },
        notification_type=template.template_type,
        api_key_id=None,
        key_type=KEY_TYPE_NORMAL,
        reply_to_text=service.get_default_reply_to_email_address()
    )

    send_notification_to_queue(saved_notification, False, queue=QueueNames.NOTIFY)

    return jsonify({}), 204
예제 #4
0
def _update_alert(user_to_update, changes=None):
    service = Service.query.get(current_app.config['NOTIFY_SERVICE_ID'])
    template = dao_get_template_by_id(current_app.config['ACCOUNT_CHANGE_TEMPLATE_ID'])
    recipient = user_to_update.email_address
    reply_to = template.service.get_default_reply_to_email_address()

    change_type_en = ""
    change_type_fr = ""
    if changes:
        change_type_en = update_dct_to_str(changes, 'EN')
        change_type_fr = update_dct_to_str(changes, 'FR')

    saved_notification = persist_notification(
        template_id=template.id,
        template_version=template.version,
        recipient=recipient,
        service=service,
        personalisation={
            'base_url': Config.ADMIN_BASE_URL,
            'contact_us_url': f'{Config.ADMIN_BASE_URL}/support/ask-question-give-feedback',
            'change_type_en': change_type_en,
            'change_type_fr': change_type_fr,
        },
        notification_type=template.template_type,
        api_key_id=None,
        key_type=KEY_TYPE_NORMAL,
        reply_to_text=reply_to
    )

    send_notification_to_queue(saved_notification, False, queue=QueueNames.NOTIFY)
예제 #5
0
def send_user_confirm_new_email(user_id):
    user_to_send_to = get_user_by_id(user_id=user_id)
    email, errors = email_data_request_schema.load(request.get_json())
    if errors:
        raise InvalidRequest(message=errors, status_code=400)

    template = dao_get_template_by_id(current_app.config['CHANGE_EMAIL_CONFIRMATION_TEMPLATE_ID'])
    notify_service_id = current_app.config['NOTIFY_SERVICE_ID']

    saved_notification = persist_notification(
        template_id=template.id,
        template_version=template.version,
        recipient=email['email'],
        service_id=notify_service_id,
        personalisation={
            'name': user_to_send_to.name,
            'url': _create_confirmation_url(user=user_to_send_to, email_address=email['email']),
            'feedback_url': current_app.config['ADMIN_BASE_URL'] + '/feedback'
        },
        notification_type=EMAIL_TYPE,
        api_key_id=None,
        key_type=KEY_TYPE_NORMAL
    )

    send_notification_to_queue(saved_notification, False, queue='notify')
    return jsonify({}), 204
def post_email_notification():
    form = validate(request.get_json(), post_email_request)
    service = services_dao.dao_fetch_service_by_id(api_user.service_id)

    check_service_message_limit(api_user.key_type, service)
    service_can_send_to_recipient(form["email_address"], api_user.key_type, service)

    template, template_with_content = __validate_template(form, service, EMAIL_TYPE)
    notification = persist_notification(
        template_id=template.id,
        template_version=template.version,
        recipient=form["email_address"],
        service_id=service.id,
        personalisation=form.get("personalisation", None),
        notification_type=EMAIL_TYPE,
        api_key_id=api_user.id,
        key_type=api_user.key_type,
        reference=form.get("reference"),
    )

    send_notification_to_queue(notification, service.research_mode)

    resp = create_post_email_response_from_notification(
        notification=notification,
        content=str(template_with_content),
        subject=template_with_content.subject,
        email_from=service.email_from,
        url_root=request.url_root,
    )
    return jsonify(resp), 201
예제 #7
0
def create_invited_user(service_id):
    request_json = request.get_json()
    invited_user, errors = invited_user_schema.load(request_json)
    save_invited_user(invited_user)

    template = dao_get_template_by_id(
        current_app.config['INVITATION_EMAIL_TEMPLATE_ID'])
    service = Service.query.get(current_app.config['NOTIFY_SERVICE_ID'])

    saved_notification = persist_notification(
        template_id=template.id,
        template_version=template.version,
        recipient=invited_user.email_address,
        service=service,
        personalisation={
            'user_name':
            invited_user.from_user.name,
            'service_name':
            invited_user.service.name,
            'url':
            invited_user_url(
                invited_user.id,
                request_json.get('invite_link_host'),
            ),
        },
        notification_type=EMAIL_TYPE,
        api_key_id=None,
        key_type=KEY_TYPE_NORMAL,
        reply_to_text=invited_user.from_user.email_address)

    send_notification_to_queue(saved_notification,
                               False,
                               queue=QueueNames.NOTIFY)

    return jsonify(data=invited_user_schema.dump(invited_user).data), 201
def post_sms_notification():
    form = validate(request.get_json(), post_sms_request)
    service = services_dao.dao_fetch_service_by_id(api_user.service_id)

    check_service_message_limit(api_user.key_type, service)
    service_can_send_to_recipient(form["phone_number"], api_user.key_type, service)

    template, template_with_content = __validate_template(form, service, SMS_TYPE)

    notification = persist_notification(
        template_id=template.id,
        template_version=template.version,
        recipient=form["phone_number"],
        service_id=service.id,
        personalisation=form.get("personalisation", None),
        notification_type=SMS_TYPE,
        api_key_id=api_user.id,
        key_type=api_user.key_type,
        reference=form.get("reference"),
    )
    send_notification_to_queue(notification, service.research_mode)
    sms_sender = service.sms_sender if service.sms_sender else current_app.config.get("FROM_NUMBER")
    resp = create_post_sms_response_from_notification(
        notification, str(template_with_content), sms_sender, request.url_root
    )
    return jsonify(resp), 201
예제 #9
0
def send_notification_to_service_users(service_id,
                                       template_id,
                                       personalisation=None,
                                       include_user_fields=None):
    personalisation = personalisation or {}
    include_user_fields = include_user_fields or []
    template = dao_get_template_by_id(template_id)
    service = dao_fetch_service_by_id(service_id)
    active_users = dao_fetch_active_users_for_service(service.id)
    notify_service = dao_fetch_service_by_id(
        current_app.config['NOTIFY_SERVICE_ID'])

    for user in active_users:
        personalisation = _add_user_fields(user, personalisation,
                                           include_user_fields)
        notification = persist_notification(
            template_id=template.id,
            template_version=template.version,
            recipient=user.email_address
            if template.template_type == EMAIL_TYPE else user.mobile_number,
            service=notify_service,
            personalisation=personalisation,
            notification_type=template.template_type,
            api_key_id=None,
            key_type=KEY_TYPE_NORMAL,
            reply_to_text=notify_service.get_default_reply_to_email_address())
        send_notification_to_queue(notification,
                                   False,
                                   queue=QueueNames.NOTIFY)
예제 #10
0
def send_already_registered_email(user_id):
    to, errors = email_data_request_schema.load(request.get_json())
    template = dao_get_template_by_id(
        current_app.config['ALREADY_REGISTERED_EMAIL_TEMPLATE_ID'])
    service = Service.query.get(current_app.config['NOTIFY_SERVICE_ID'])

    saved_notification = persist_notification(
        template_id=template.id,
        template_version=template.version,
        recipient=to['email'],
        service=service,
        personalisation={
            'signin_url': current_app.config['ADMIN_BASE_URL'] + '/sign-in',
            'forgot_password_url':
            current_app.config['ADMIN_BASE_URL'] + '/forgot-password',
            'feedback_url': current_app.config['ADMIN_BASE_URL'] + '/support'
        },
        notification_type=template.template_type,
        api_key_id=None,
        key_type=KEY_TYPE_NORMAL,
        reply_to_text=service.get_default_reply_to_email_address())

    send_notification_to_queue(saved_notification,
                               False,
                               queue=QueueNames.NOTIFY)

    return jsonify({}), 204
예제 #11
0
def test_send_notification_to_queue(
    notify_db,
    notify_db_session,
    research_mode,
    requested_queue,
    notification_type,
    key_type,
    expected_queue,
    expected_task,
    mocker,
):
    mocked = mocker.patch('app.celery.{}.apply_async'.format(expected_task))
    Notification = namedtuple(
        'Notification', ['id', 'key_type', 'notification_type', 'created_at'])
    notification = Notification(
        id=uuid.uuid4(),
        key_type=key_type,
        notification_type=notification_type,
        created_at=datetime.datetime(2016, 11, 11, 16, 8, 18),
    )

    send_notification_to_queue(notification=notification,
                               research_mode=research_mode,
                               queue=requested_queue)

    mocked.assert_called_once_with([str(notification.id)],
                                   queue=expected_queue)
def test_send_notification_to_queue(
    notify_db,
    notify_db_session,
    research_mode,
    requested_queue,
    notification_type,
    key_type,
    reply_to_text,
    expected_queue,
    expected_task,
    mocker,
):
    if "." not in expected_task:
        expected_task = f"provider_tasks.{expected_task}"
    mocked = mocker.patch(f"app.celery.{expected_task}.apply_async")
    notification = Notification(
        id=uuid.uuid4(),
        key_type=key_type,
        notification_type=notification_type,
        created_at=datetime.datetime(2016, 11, 11, 16, 8, 18),
        reply_to_text=reply_to_text,
    )

    send_notification_to_queue(notification=notification,
                               research_mode=research_mode,
                               queue=requested_queue)

    mocked.assert_called_once_with([str(notification.id)],
                                   queue=expected_queue)
예제 #13
0
def send_user_sms_code(user_id):
    user_to_send_to = get_user_by_id(user_id=user_id)
    verify_code, errors = request_verify_code_schema.load(request.get_json())

    secret_code = create_secret_code()
    create_user_code(user_to_send_to, secret_code, SMS_TYPE)

    mobile = user_to_send_to.mobile_number if verify_code.get('to', None) is None else verify_code.get('to')
    sms_code_template_id = current_app.config['SMS_CODE_TEMPLATE_ID']
    sms_code_template = dao_get_template_by_id(sms_code_template_id)
    notify_service_id = current_app.config['NOTIFY_SERVICE_ID']

    saved_notification = persist_notification(
        template_id=sms_code_template_id,
        template_version=sms_code_template.version,
        recipient=mobile,
        service_id=notify_service_id,
        personalisation={'verify_code': secret_code},
        notification_type=SMS_TYPE,
        api_key_id=None,
        key_type=KEY_TYPE_NORMAL
    )
    # Assume that we never want to observe the Notify service's research mode
    # setting for this notification - we still need to be able to log into the
    # admin even if we're doing user research using this service:
    send_notification_to_queue(saved_notification, False, queue='notify')

    return jsonify({}), 204
def send_one_off_notification(service_id, post_data):
    service = dao_fetch_service_by_id(service_id)
    template = dao_get_template_by_id_and_service_id(
        template_id=post_data['template_id'],
        service_id=service_id
    )

    personalisation = post_data.get('personalisation', None)

    validate_template(template.id, personalisation, service, template.template_type)

    check_service_over_daily_message_limit(KEY_TYPE_NORMAL, service)

    validate_and_format_recipient(
        send_to=post_data['to'],
        key_type=KEY_TYPE_NORMAL,
        service=service,
        notification_type=template.template_type,
        allow_whitelisted_recipients=False,
    )

    validate_created_by(service, post_data['created_by'])

    sender_id = post_data.get('sender_id', None)
    reply_to = get_reply_to_text(
        notification_type=template.template_type,
        sender_id=sender_id,
        service=service,
        template=template
    )
    notification = persist_notification(
        template_id=template.id,
        template_version=template.version,
        template_postage=template.postage,
        recipient=post_data['to'],
        service=service,
        personalisation=personalisation,
        notification_type=template.template_type,
        api_key_id=None,
        key_type=KEY_TYPE_NORMAL,
        created_by_id=post_data['created_by'],
        reply_to_text=reply_to,
        reference=create_one_off_reference(template.template_type),
    )

    queue_name = QueueNames.PRIORITY if template.process_type == PRIORITY else None

    if template.template_type == LETTER_TYPE and service.research_mode:
        _update_notification_status(
            notification,
            NOTIFICATION_DELIVERED,
        )
    else:
        send_notification_to_queue(
            notification=notification,
            research_mode=service.research_mode,
            queue=queue_name,
        )

    return {'id': str(notification.id)}
def send_branding_request(user_id):
    to, errors = branding_request_data_schema.load(request.get_json())
    template = dao_get_template_by_id(
        current_app.config['BRANDING_REQUEST_TEMPLATE_ID'])
    service = Service.query.get(current_app.config['NOTIFY_SERVICE_ID'])

    saved_notification = persist_notification(
        template_id=template.id,
        template_version=template.version,
        recipient=to['email'],
        service=service,
        personalisation={
            'email': to['email'],
            'serviceID': to['serviceID'],
            'service_name': to['service_name'],
            'filename': to['filename']
        },
        notification_type=template.template_type,
        api_key_id=None,
        key_type=KEY_TYPE_NORMAL,
        reply_to_text=service.get_default_reply_to_email_address())
    send_notification_to_queue(saved_notification,
                               False,
                               queue=QueueNames.NOTIFY)

    return jsonify({}), 204
def replay_created_notifications():
    # if the notification has not be send after 1 hour, then try to resend.
    resend_created_notifications_older_than = (60 * 60)
    for notification_type in (EMAIL_TYPE, SMS_TYPE):
        notifications_to_resend = notifications_not_yet_sent(
            resend_created_notifications_older_than,
            notification_type
        )

        if len(notifications_to_resend) > 0:
            current_app.logger.info("Sending {} {} notifications "
                                    "to the delivery queue because the notification "
                                    "status was created.".format(len(notifications_to_resend), notification_type))

        for n in notifications_to_resend:
            send_notification_to_queue(notification=n, research_mode=n.service.research_mode)

    # if the letter has not be send after an hour, then create a zendesk ticket
    letters = letters_missing_from_sending_bucket(resend_created_notifications_older_than)

    if len(letters) > 0:
        msg = "{} letters were created over an hour ago, " \
              "but do not have an updated_at timestamp or billable units. " \
              "\n Creating app.celery.letters_pdf_tasks.create_letters tasks to upload letter to S3 " \
              "and update notifications for the following notification ids: " \
              "\n {}".format(len(letters), [x.id for x in letters])

        current_app.logger.info(msg)
        for letter in letters:
            get_pdf_for_templated_letter.apply_async([str(letter.id)], queue=QueueNames.CREATE_LETTERS_PDF)
예제 #17
0
def create_2fa_code(template_id, user_to_send_to, secret_code, recipient, personalisation):
    template = dao_get_template_by_id(template_id)

    # save the code in the VerifyCode table
    create_user_code(user_to_send_to, secret_code, template.template_type)
    reply_to = None
    if template.template_type == SMS_TYPE:
        reply_to = template.service.get_default_sms_sender()
    elif template.template_type == EMAIL_TYPE:
        reply_to = template.service.get_default_reply_to_email_address()

    saved_notification = persist_notification(
        template_id=template.id,
        template_version=template.version,
        recipient=recipient,
        service=template.service,
        personalisation=personalisation,
        notification_type=template.template_type,
        api_key_id=None,
        key_type=KEY_TYPE_NORMAL,
        reply_to_text=reply_to
    )
    # Assume that we never want to observe the Notify service's research mode
    # setting for this notification - we still need to be able to log into the
    # admin even if we're doing user research using this service:
    send_notification_to_queue(saved_notification, False, queue=QueueNames.NOTIFY)
예제 #18
0
def send_user_confirm_new_email(user_id):
    user_to_send_to = get_user_by_id(user_id=user_id)
    email, errors = email_data_request_schema.load(request.get_json())
    if errors:
        raise InvalidRequest(message=errors, status_code=400)

    template = dao_get_template_by_id(current_app.config['CHANGE_EMAIL_CONFIRMATION_TEMPLATE_ID'])
    service = Service.query.get(current_app.config['NOTIFY_SERVICE_ID'])

    saved_notification = persist_notification(
        template_id=template.id,
        template_version=template.version,
        recipient=email['email'],
        service=service,
        personalisation={
            'name': user_to_send_to.name,
            'url': _create_confirmation_url(user=user_to_send_to, email_address=email['email']),
            'feedback_url': current_app.config['ADMIN_BASE_URL'] + '/support/ask-question-give-feedback'
        },
        notification_type=template.template_type,
        api_key_id=None,
        key_type=KEY_TYPE_NORMAL,
        reply_to_text=service.get_default_reply_to_email_address()
    )

    send_notification_to_queue(saved_notification, False, queue=QueueNames.NOTIFY)
    return jsonify({}), 204
def test_send_notification_to_queue_throws_exception_deletes_notification(sample_notification, mocker):
    mocked = mocker.patch('app.celery.provider_tasks.deliver_sms.apply_async', side_effect=Boto3Error("EXPECTED"))
    with pytest.raises(SendNotificationToQueueError):
        send_notification_to_queue(sample_notification, False)
        mocked.assert_called_once_with([(str(sample_notification.id))], queue='send-sms')

    assert Notification.query.count() == 0
    assert NotificationHistory.query.count() == 0
def test_send_notification_to_queue_throws_exception_deletes_notification(sample_notification, mocker):
    mocked = mocker.patch('app.celery.provider_tasks.deliver_sms.apply_async', side_effect=Boto3Error("EXPECTED"))
    with pytest.raises(Boto3Error):
        send_notification_to_queue(sample_notification, False)
    mocked.assert_called_once_with([(str(sample_notification.id))], queue='send-sms-tasks')

    assert Notification.query.count() == 0
    assert NotificationHistory.query.count() == 0
예제 #21
0
def update_user_attribute(user_id):
    user_to_update = get_user_by_id(user_id=user_id)
    req_json = request.get_json()
    if 'updated_by' in req_json:
        updated_by = get_user_by_id(user_id=req_json.pop('updated_by'))
    else:
        updated_by = None

    update_dct, errors = user_update_schema_load_json.load(req_json)
    if errors:
        raise InvalidRequest(errors, status_code=400)

    save_user_attribute(user_to_update, update_dict=update_dct)

    service = Service.query.get(current_app.config['NOTIFY_SERVICE_ID'])

    # Alert user that account change took place
    user_alert_dct = update_dct.copy()
    user_alert_dct.pop('blocked', None)
    user_alert_dct.pop('current_session_id', None)
    if not updated_by and user_alert_dct:
        _update_alert(user_to_update, user_alert_dct)

    # Alert that team member edit user
    if updated_by:
        if 'email_address' in update_dct:
            template = dao_get_template_by_id(
                current_app.config['TEAM_MEMBER_EDIT_EMAIL_TEMPLATE_ID'])
            recipient = user_to_update.email_address
            reply_to = template.service.get_default_reply_to_email_address()
        elif 'mobile_number' in update_dct:
            template = dao_get_template_by_id(
                current_app.config['TEAM_MEMBER_EDIT_MOBILE_TEMPLATE_ID'])
            recipient = user_to_update.mobile_number
            reply_to = template.service.get_default_sms_sender()
        else:
            return jsonify(data=user_to_update.serialize()), 200

        saved_notification = persist_notification(
            template_id=template.id,
            template_version=template.version,
            recipient=recipient,
            service=service,
            personalisation={
                'name': user_to_update.name,
                'servicemanagername': updated_by.name,
                'email address': user_to_update.email_address
            },
            notification_type=template.template_type,
            api_key_id=None,
            key_type=KEY_TYPE_NORMAL,
            reply_to_text=reply_to)

        send_notification_to_queue(saved_notification,
                                   False,
                                   queue=QueueNames.NOTIFY)

    return jsonify(data=user_to_update.serialize()), 200
예제 #22
0
def save_sms(self,
             service_id,
             notification_id,
             encrypted_notification,
             sender_id=None):
    notification = encryption.decrypt(encrypted_notification)
    service = dao_fetch_service_by_id(service_id)
    template = dao_get_template_by_id(notification["template"],
                                      version=notification["template_version"])

    if sender_id:
        reply_to_text = dao_get_service_sms_senders_by_id(
            service_id, sender_id).sms_sender
    else:
        reply_to_text = template.get_reply_to_text()

    if not service_allowed_to_send_to(notification["to"], service,
                                      KEY_TYPE_NORMAL):
        current_app.logger.debug(
            "SMS {} failed as restricted service".format(notification_id))
        return

    check_service_over_daily_message_limit(KEY_TYPE_NORMAL, service)

    try:
        # this task is used by two main things... process_job and process_sms_or_email_notification
        # if the data is not present in the encrypted data then fallback on whats needed for process_job
        saved_notification = persist_notification(
            notification_id=notification.get("id", notification_id),
            template_id=notification["template"],
            template_version=notification["template_version"],
            recipient=notification["to"],
            service=service,
            personalisation=notification.get("personalisation"),
            notification_type=SMS_TYPE,
            simulated=notification.get("simulated", None),
            api_key_id=notification.get("api_key", None),
            key_type=notification.get("key_type", KEY_TYPE_NORMAL),
            created_at=datetime.utcnow(),
            job_id=notification.get("job", None),
            job_row_number=notification.get("row_number", None),
            reply_to_text=reply_to_text,
        )

        send_notification_to_queue(
            saved_notification,
            service.research_mode,
            queue=notification.get("queue") or template.queue_to_use(),
        )

        current_app.logger.debug("SMS {} created at {} for job {}".format(
            saved_notification.id,
            saved_notification.created_at,
            notification.get("job", None),
        ))

    except SQLAlchemyError as e:
        handle_exception(self, notification, notification_id, e)
예제 #23
0
def save_letter(
    self,
    service_id,
    notification_id,
    encrypted_notification,
):
    notification = encryption.decrypt(encrypted_notification)

    # we store the recipient as just the first item of the person's address
    recipient = notification["personalisation"]["addressline1"]

    service = dao_fetch_service_by_id(service_id)
    template = dao_get_template_by_id(notification["template"],
                                      version=notification["template_version"])

    check_service_over_daily_message_limit(KEY_TYPE_NORMAL, service)

    try:
        # if we don't want to actually send the letter, then start it off in SENDING so we don't pick it up
        status = NOTIFICATION_CREATED if not service.research_mode else NOTIFICATION_SENDING

        saved_notification = persist_notification(
            template_id=notification["template"],
            template_version=notification["template_version"],
            template_postage=template.postage,
            recipient=recipient,
            service=service,
            personalisation=notification["personalisation"],
            notification_type=LETTER_TYPE,
            api_key_id=notification.get("api_key", None),
            key_type=KEY_TYPE_NORMAL,
            created_at=datetime.utcnow(),
            job_id=notification["job"],
            job_row_number=notification["row_number"],
            notification_id=notification_id,
            reference=create_random_identifier(),
            reply_to_text=template.get_reply_to_text(),
            status=status,
        )

        if not service.research_mode:
            send_notification_to_queue(saved_notification,
                                       service.research_mode)
        elif current_app.config["NOTIFY_ENVIRONMENT"] in [
                "preview", "development"
        ]:
            research_mode_tasks.create_fake_letter_response_file.apply_async(
                (saved_notification.reference, ),
                queue=QueueNames.RESEARCH_MODE)
        else:
            update_notification_status_by_reference(
                saved_notification.reference, "delivered")

        current_app.logger.debug("Letter {} created at {}".format(
            saved_notification.id, saved_notification.created_at))
    except SQLAlchemyError as e:
        handle_exception(self, notification, notification_id, e)
예제 #24
0
def process_sms_or_email_notification(*,
                                      form,
                                      notification_type,
                                      api_key,
                                      template,
                                      service,
                                      reply_to_text=None):
    form_send_to = form[
        'email_address'] if notification_type == EMAIL_TYPE else form[
            'phone_number']

    send_to = validate_and_format_recipient(
        send_to=form_send_to,
        key_type=api_key.key_type,
        service=service,
        notification_type=notification_type)

    # Do not persist or send notification to the queue if it is a simulated recipient
    simulated = simulated_recipient(send_to, notification_type)

    personalisation = process_document_uploads(form.get('personalisation'),
                                               service,
                                               simulated=simulated)

    additional_email_parameters = {"importance": form.get('importance', None), "cc_address": form.get('cc_address', None)} \
        if notification_type == EMAIL_TYPE else {}

    notification = persist_notification(
        template_id=template.id,
        template_version=template.version,
        recipient=form_send_to,
        service=service,
        personalisation=personalisation,
        notification_type=notification_type,
        api_key_id=api_key.id,
        key_type=api_key.key_type,
        client_reference=form.get('reference', None),
        simulated=simulated,
        reply_to_text=reply_to_text,
        additional_email_parameters=additional_email_parameters)

    scheduled_for = form.get("scheduled_for", None)
    if scheduled_for:
        persist_scheduled_notification(notification.id, form["scheduled_for"])
    else:
        if not simulated:
            queue_name = QueueNames.PRIORITY if template.process_type == PRIORITY else None
            send_notification_to_queue(notification=notification,
                                       research_mode=service.research_mode,
                                       queue=queue_name)
        else:
            current_app.logger.debug(
                "POST simulated notification for id: {}".format(
                    notification.id))

    return notification
예제 #25
0
def send_one_off_notification(service_id, post_data):
    service = dao_fetch_service_by_id(service_id)
    template = dao_get_template_by_id_and_service_id(template_id=post_data["template_id"], service_id=service_id)

    personalisation = post_data.get("personalisation", None)

    validate_template(template.id, personalisation, service, template.template_type)

    check_service_over_daily_message_limit(KEY_TYPE_NORMAL, service)

    validate_and_format_recipient(
        send_to=post_data["to"],
        key_type=KEY_TYPE_NORMAL,
        service=service,
        notification_type=template.template_type,
        allow_safelisted_recipients=False,
    )

    validate_created_by(service, post_data["created_by"])

    sender_id = post_data.get("sender_id", None)
    reply_to = get_reply_to_text(
        notification_type=template.template_type,
        sender_id=sender_id,
        service=service,
        template=template,
    )
    notification = persist_notification(
        template_id=template.id,
        template_version=template.version,
        template_postage=template.postage,
        recipient=post_data["to"],
        service=service,
        personalisation=personalisation,
        notification_type=template.template_type,
        api_key_id=None,
        key_type=KEY_TYPE_NORMAL,
        created_by_id=post_data["created_by"],
        reply_to_text=reply_to,
        reference=create_one_off_reference(template.template_type),
    )

    if template.template_type == LETTER_TYPE and service.research_mode:
        _update_notification_status(
            notification,
            NOTIFICATION_DELIVERED,
        )
    else:
        send_notification_to_queue(
            notification=notification,
            research_mode=service.research_mode,
            queue=template.queue_to_use(),
        )

    return {"id": str(notification.id)}
예제 #26
0
def send_scheduled_notifications():
    try:
        scheduled_notifications = dao_get_scheduled_notifications()
        for notification in scheduled_notifications:
            send_notification_to_queue(notification, notification.service.research_mode)
            set_scheduled_notification_to_processed(notification.id)
        current_app.logger.info(
            "Sent {} scheduled notifications to the provider queue".format(len(scheduled_notifications)))
    except SQLAlchemyError:
        current_app.logger.exception("Failed to send scheduled notifications")
        raise
예제 #27
0
def process_sms_or_email_notification(*,
                                      form,
                                      notification_type,
                                      api_key,
                                      template,
                                      service,
                                      reply_to_text=None):
    form_send_to = form[
        'email_address'] if notification_type == EMAIL_TYPE else form[
            'phone_number']

    send_to = validate_and_format_recipient(
        send_to=form_send_to,
        key_type=api_key.key_type,
        service=service,
        notification_type=notification_type)

    # Do not persist or send notification to the queue if it is a simulated recipient
    simulated = simulated_recipient(send_to, notification_type)

    notification = persist_notification(
        template_id=template.id,
        template_version=template.version,
        recipient=form_send_to,
        service=service,
        personalisation=form.get('personalisation', None),
        notification_type=notification_type,
        api_key_id=api_key.id,
        key_type=api_key.key_type,
        client_reference=form.get('reference', None),
        simulated=simulated,
        reply_to_text=reply_to_text,
        status_callback_url=form.get('status_callback_url', None),
        status_callback_bearer_token=form.get('status_callback_bearer_token',
                                              None),
    )

    scheduled_for = form.get("scheduled_for", None)
    if scheduled_for:
        persist_scheduled_notification(notification.id, form["scheduled_for"])
    else:
        if not simulated:
            queue_name = QueueNames.PRIORITY if template.process_type == PRIORITY else None
            send_notification_to_queue(notification=notification,
                                       research_mode=service.research_mode,
                                       queue=queue_name)
        else:
            current_app.logger.debug(
                "POST simulated notification for id: {}".format(
                    notification.id))

    return notification
예제 #28
0
def update_service(service_id):
    req_json = request.get_json()
    fetched_service = dao_fetch_service_by_id(service_id)
    # Capture the status change here as Marshmallow changes this later
    service_going_live = fetched_service.restricted and not req_json.get('restricted', True)
    service_go_live_requested = 'go_live_user' in req_json
    current_data = dict(service_schema.dump(fetched_service).data.items())
    current_data.update(request.get_json())

    service = service_schema.load(current_data).data

    if 'email_branding' in req_json:
        email_branding_id = req_json['email_branding']
        service.email_branding = None if not email_branding_id else EmailBranding.query.get(email_branding_id)
    if 'letter_branding' in req_json:
        letter_branding_id = req_json['letter_branding']
        service.letter_branding = None if not letter_branding_id else LetterBranding.query.get(letter_branding_id)
    dao_update_service(service)

    if service_go_live_requested:
        template = dao_get_template_by_id(current_app.config['NOTIFY_ADMIN_OF_GO_LIVE_REQUEST_TEMPLATE_ID'])
        service_url = "{}/services/{}".format(current_app.config['ADMIN_BASE_URL'], str(service.id))
        saved_notification = persist_notification(
            template_id=template.id,
            template_version=template.version,
            recipient=get_or_build_support_email_address(),
            service=template.service,
            personalisation={
                'service_name': service.name,
                'service_dashboard_url': service_url
            },
            notification_type=EMAIL_TYPE,
            api_key_id=None,
            key_type=KEY_TYPE_NORMAL,
            reply_to_text=get_or_build_support_email_address()
        )
        send_notification_to_queue(saved_notification, research_mode=False, queue=QueueNames.NOTIFY)

    if service_going_live:
        send_notification_to_service_users(
            service_id=service_id,
            template_id=current_app.config['SERVICE_NOW_LIVE_TEMPLATE_ID'],
            personalisation={
                'service_name': current_data['name'],
                'message_limit': '{:,}'.format(current_data['message_limit'])
            },
            include_user_fields=['name']
        )

    return jsonify(data=service_schema.dump(fetched_service).data), 200
예제 #29
0
def send_letters_volume_email_to_dvla(letters_volumes, date):
    personalisation = {
        'total_volume': 0,
        'first_class_volume': 0,
        'second_class_volume': 0,
        'international_volume': 0,
        'total_sheets': 0,
        'first_class_sheets': 0,
        "second_class_sheets": 0,
        'international_sheets': 0,
        'date': date.strftime("%d %B %Y")
    }
    for item in letters_volumes:
        personalisation['total_volume'] += item.letters_count
        personalisation['total_sheets'] += item.sheets_count
        if f"{item.postage}_class_volume" in personalisation:
            personalisation[
                f"{item.postage}_class_volume"] = item.letters_count
            personalisation[f"{item.postage}_class_sheets"] = item.sheets_count
        else:
            personalisation["international_volume"] += item.letters_count
            personalisation["international_sheets"] += item.sheets_count

    template = dao_get_template_by_id(
        current_app.config['LETTERS_VOLUME_EMAIL_TEMPLATE_ID'])
    recipients = current_app.config['DVLA_EMAIL_ADDRESSES']
    reply_to = template.service.get_default_reply_to_email_address()
    service = Service.query.get(current_app.config['NOTIFY_SERVICE_ID'])

    # avoid circular imports:
    from app.notifications.process_notifications import (
        persist_notification,
        send_notification_to_queue,
    )
    for recipient in recipients:
        saved_notification = persist_notification(
            template_id=template.id,
            template_version=template.version,
            recipient=recipient,
            service=service,
            personalisation=personalisation,
            notification_type=template.template_type,
            api_key_id=None,
            key_type=KEY_TYPE_NORMAL,
            reply_to_text=reply_to)

        send_notification_to_queue(saved_notification,
                                   False,
                                   queue=QueueNames.NOTIFY)
예제 #30
0
def replay_created_notifications():
    # if the notification has not be send after 4 hours + 15 minutes, then try to resend.
    resend_created_notifications_older_than = (60 * 60 * 4) + (60 * 15)
    for notification_type in (EMAIL_TYPE, SMS_TYPE):
        notifications_to_resend = notifications_not_yet_sent(
            resend_created_notifications_older_than,
            notification_type
        )

        current_app.logger.info("Sending {} {} notifications "
                                "to the delivery queue because the notification "
                                "status was created.".format(len(notifications_to_resend), notification_type))

        for n in notifications_to_resend:
            send_notification_to_queue(notification=n, research_mode=n.service.research_mode)
예제 #31
0
    def _send_notification(template_id, recipient, personalisation):
        template = dao_get_template_by_id(template_id)

        saved_notification = persist_notification(
            template_id=template.id,
            template_version=template.version,
            recipient=recipient,
            service=notify_service,
            personalisation=personalisation,
            notification_type=template.template_type,
            api_key_id=None,
            key_type=KEY_TYPE_NORMAL,
            reply_to_text=notify_service.get_default_reply_to_email_address()
        )
        send_notification_to_queue(saved_notification, research_mode=False, queue=QueueNames.NOTIFY)
def test_send_notification_to_queue(notify_db, notify_db_session,
                                    research_mode, requested_queue, expected_queue,
                                    notification_type, key_type, mocker):
    mocked = mocker.patch('app.celery.provider_tasks.deliver_{}.apply_async'.format(notification_type))
    Notification = namedtuple('Notification', ['id', 'key_type', 'notification_type', 'created_at'])
    notification = Notification(
        id=uuid.uuid4(),
        key_type=key_type,
        notification_type=notification_type,
        created_at=datetime.datetime(2016, 11, 11, 16, 8, 18),
    )

    send_notification_to_queue(notification=notification, research_mode=research_mode, queue=requested_queue)

    mocked.assert_called_once_with([str(notification.id)], queue=expected_queue)
예제 #33
0
def save_sms(self,
             service_id,
             notification_id,
             encrypted_notification,
             sender_id=None):
    notification = encryption.decrypt(encrypted_notification)
    service = dao_fetch_service_by_id(service_id)
    template = dao_get_template_by_id(notification['template'],
                                      version=notification['template_version'])

    if sender_id:
        reply_to_text = dao_get_service_sms_senders_by_id(
            service_id, sender_id).sms_sender
    else:
        reply_to_text = template.get_reply_to_text()

    if not service_allowed_to_send_to(notification['to'], service,
                                      KEY_TYPE_NORMAL):
        current_app.logger.debug(
            "SMS {} failed as restricted service".format(notification_id))
        return

    try:
        saved_notification = persist_notification(
            template_id=notification['template'],
            template_version=notification['template_version'],
            recipient=notification['to'],
            service=service,
            personalisation=notification.get('personalisation'),
            notification_type=SMS_TYPE,
            api_key_id=None,
            key_type=KEY_TYPE_NORMAL,
            created_at=datetime.utcnow(),
            job_id=notification.get('job', None),
            job_row_number=notification.get('row_number', None),
            notification_id=notification_id,
            reply_to_text=reply_to_text)

        send_notification_to_queue(saved_notification, service.research_mode)

        current_app.logger.debug("SMS {} created at {} for job {}".format(
            saved_notification.id, saved_notification.created_at,
            notification.get('job', None)))

    except SQLAlchemyError as e:
        handle_exception(self, notification, notification_id, e)
예제 #34
0
def send_notification_to_notify_support(template_id, personalisation=None):
    personalisation = personalisation or {}
    template = dao_get_template_by_id(template_id)
    notify_service = dao_fetch_service_by_id(current_app.config['NOTIFY_SERVICE_ID'])

    validate_template(template.id, personalisation, notify_service, template.template_type)

    notification = persist_notification(
        template_id=template.id,
        template_version=template.version,
        recipient=current_app.config['NOTIFY_SUPPORT_EMAIL'],
        service=notify_service,
        personalisation=personalisation,
        notification_type=template.template_type,
        api_key_id=None,
        key_type=KEY_TYPE_NORMAL,
        reply_to_text=notify_service.get_default_reply_to_email_address()
    )
    send_notification_to_queue(notification, False, queue=QueueNames.NOTIFY)
예제 #35
0
def verify_reply_to_email_address(service_id):
    email_address, errors = email_data_request_schema.load(request.get_json())
    check_if_reply_to_address_already_in_use(service_id, email_address["email"])
    template = dao_get_template_by_id(current_app.config['REPLY_TO_EMAIL_ADDRESS_VERIFICATION_TEMPLATE_ID'])
    notify_service = Service.query.get(current_app.config['NOTIFY_SERVICE_ID'])
    saved_notification = persist_notification(
        template_id=template.id,
        template_version=template.version,
        recipient=email_address["email"],
        service=notify_service,
        personalisation='',
        notification_type=template.template_type,
        api_key_id=None,
        key_type=KEY_TYPE_NORMAL,
        reply_to_text=notify_service.get_default_reply_to_email_address()
    )

    send_notification_to_queue(saved_notification, False, queue=QueueNames.NOTIFY)

    return jsonify(data={"id": saved_notification.id}), 201
예제 #36
0
def invite_user_to_org(organisation_id):
    data = request.get_json()
    validate(data, post_create_invited_org_user_status_schema)

    invited_org_user = InvitedOrganisationUser(
        email_address=data["email_address"],
        invited_by_id=data["invited_by"],
        organisation_id=organisation_id,
    )
    save_invited_org_user(invited_org_user)

    template = dao_get_template_by_id(
        current_app.config["ORGANISATION_INVITATION_EMAIL_TEMPLATE_ID"])

    saved_notification = persist_notification(
        template_id=template.id,
        template_version=template.version,
        recipient=invited_org_user.email_address,
        service=template.service,
        personalisation={
            "user_name":
            invited_org_user.invited_by.name,
            "organisation_name":
            invited_org_user.organisation.name,
            "url":
            invited_org_user_url(
                invited_org_user.id,
                data.get("invite_link_host"),
            ),
        },
        notification_type=EMAIL_TYPE,
        api_key_id=None,
        key_type=KEY_TYPE_NORMAL,
        reply_to_text=invited_org_user.invited_by.email_address,
    )

    send_notification_to_queue(saved_notification,
                               research_mode=False,
                               queue=QueueNames.NOTIFY)

    return jsonify(data=invited_org_user.serialize()), 201
예제 #37
0
def send_user_email_verification(user_id):
    user_to_send_to = get_user_by_id(user_id=user_id)
    secret_code = create_secret_code()
    create_user_code(user_to_send_to, secret_code, 'email')

    template = dao_get_template_by_id(current_app.config['EMAIL_VERIFY_CODE_TEMPLATE_ID'])

    saved_notification = persist_notification(
        template_id=template.id,
        template_version=template.version,
        recipient=user_to_send_to.email_address,
        service_id=current_app.config['NOTIFY_SERVICE_ID'],
        personalisation={
            'name': user_to_send_to.name,
            'url': _create_verification_url(user_to_send_to, secret_code)
        },
        notification_type=EMAIL_TYPE,
        api_key_id=None,
        key_type=KEY_TYPE_NORMAL
    )

    send_notification_to_queue(saved_notification, False, queue="notify")

    return jsonify({}), 204