def validate_and_format_recipient(send_to, key_type, service, notification_type, allow_safelisted_recipients=True): if send_to is None: raise BadRequestError(message="Recipient can't be empty") service_can_send_to_recipient(send_to, key_type, service, allow_safelisted_recipients) if notification_type == SMS_TYPE: international_phone_info = get_international_phone_info(send_to) if international_phone_info.international and INTERNATIONAL_SMS_TYPE not in [ p.permission for p in service.permissions ]: raise BadRequestError( message="Cannot send to international mobile numbers") return validate_and_format_phone_number( number=send_to, international=international_phone_info.international) elif notification_type == EMAIL_TYPE: return validate_and_format_email_address(email_address=send_to)
def _service_can_send_internationally(service, number): international_phone_info = get_international_phone_info(number) if international_phone_info.international and \ INTERNATIONAL_SMS_TYPE not in [p.permission for p in service.permissions]: raise InvalidRequest( {'to': ["Cannot send to international mobile numbers"]}, status_code=400)
def check_if_service_can_send_to_number(service, number): international_phone_info = get_international_phone_info(number) if service.permissions and isinstance(service.permissions[0], ServicePermission): permissions = [p.permission for p in service.permissions] else: permissions = service.permissions if ( # if number is international and not a crown dependency international_phone_info.international and not international_phone_info.crown_dependency ) and INTERNATIONAL_SMS_TYPE not in permissions: raise BadRequestError(message="Cannot send to international mobile numbers") else: return international_phone_info
def persist_notification(*, template_id, template_version, recipient, service, personalisation, notification_type, api_key_id, key_type, created_at=None, job_id=None, job_row_number=None, reference=None, client_reference=None, notification_id=None, simulated=False, created_by_id=None, status=NOTIFICATION_CREATED, reply_to_text=None, billable_units=None, postage=None, document_download_count=None, updated_at=None): notification_created_at = created_at or datetime.utcnow() if not notification_id: notification_id = uuid.uuid4() notification = Notification( id=notification_id, template_id=template_id, template_version=template_version, to=recipient, service_id=service.id, personalisation=personalisation, notification_type=notification_type, api_key_id=api_key_id, key_type=key_type, created_at=notification_created_at, job_id=job_id, job_row_number=job_row_number, client_reference=client_reference, reference=reference, created_by_id=created_by_id, status=status, reply_to_text=reply_to_text, billable_units=billable_units, document_download_count=document_download_count, updated_at=updated_at) if notification_type == SMS_TYPE: formatted_recipient = validate_and_format_phone_number( recipient, international=True) recipient_info = get_international_phone_info(formatted_recipient) notification.normalised_to = formatted_recipient notification.international = recipient_info.international notification.phone_prefix = recipient_info.country_prefix notification.rate_multiplier = recipient_info.billable_units elif notification_type == EMAIL_TYPE: notification.normalised_to = format_email_address(notification.to) elif notification_type == LETTER_TYPE: notification.postage = postage notification.international = postage in INTERNATIONAL_POSTAGE_TYPES notification.normalised_to = ''.join(notification.to.split()).lower() # if simulated create a Notification model to return but do not persist the Notification to the dB if not simulated: dao_create_notification(notification) # Only keep track of the daily limit for trial mode services. if service.restricted and key_type != KEY_TYPE_TEST: if redis_store.get(redis.daily_limit_cache_key(service.id)): redis_store.incr(redis.daily_limit_cache_key(service.id)) current_app.logger.info("{} {} created at {}".format( notification_type, notification_id, notification_created_at)) return notification
def test_get_international_info_raises(phone_number): with pytest.raises(InvalidPhoneError) as error: get_international_phone_info(phone_number) assert str(error.value) == 'Not a valid country prefix'
def test_get_international_info(phone_number, expected_info): assert get_international_phone_info(phone_number) == expected_info
def persist_notification(*, template_id, template_version, recipient=None, service, personalisation, notification_type, api_key_id, key_type, created_at=None, job_id=None, job_row_number=None, reference=None, client_reference=None, notification_id=None, simulated=False, created_by_id=None, status=NOTIFICATION_CREATED, reply_to_text=None, billable_units=None, postage=None, template_postage=None, recipient_identifier=None): notification_created_at = created_at or datetime.utcnow() if not notification_id: notification_id = uuid.uuid4() notification = Notification(id=notification_id, template_id=template_id, template_version=template_version, to=recipient, service_id=service.id, service=service, personalisation=personalisation, notification_type=notification_type, api_key_id=api_key_id, key_type=key_type, created_at=notification_created_at, job_id=job_id, job_row_number=job_row_number, client_reference=client_reference, reference=reference, created_by_id=created_by_id, status=status, reply_to_text=reply_to_text, billable_units=billable_units) if accept_recipient_identifiers_enabled() and recipient_identifier: _recipient_identifier = RecipientIdentifier( notification_id=notification_id, id_type=recipient_identifier['id_type'], id_value=recipient_identifier['id_value']) notification.recipient_identifiers.set(_recipient_identifier) if notification_type == SMS_TYPE and notification.to: formatted_recipient = validate_and_format_phone_number( recipient, international=True) recipient_info = get_international_phone_info(formatted_recipient) notification.normalised_to = formatted_recipient notification.international = recipient_info.international notification.phone_prefix = recipient_info.country_prefix notification.rate_multiplier = recipient_info.billable_units elif notification_type == EMAIL_TYPE and notification.to: notification.normalised_to = format_email_address(notification.to) elif notification_type == LETTER_TYPE: notification.postage = postage or template_postage # if simulated create a Notification model to return but do not persist the Notification to the dB if not simulated: dao_create_notification(notification) if key_type != KEY_TYPE_TEST: if redis_store.get(redis.daily_limit_cache_key(service.id)): redis_store.incr(redis.daily_limit_cache_key(service.id)) current_app.logger.info("{} {} created at {}".format( notification_type, notification_id, notification_created_at)) return notification
def persist_notification( *, template_id, template_version, recipient, service, personalisation, notification_type, api_key_id, key_type, created_at=None, job_id=None, job_row_number=None, reference=None, client_reference=None, notification_id=None, simulated=False, created_by_id=None, status=NOTIFICATION_CREATED, reply_to_text=None, status_callback_url=None, status_callback_bearer_token=None, ): notification_created_at = created_at or datetime.utcnow() if not notification_id: notification_id = uuid.uuid4() notification = Notification( id=notification_id, template_id=template_id, template_version=template_version, to=recipient, service_id=service.id, service=service, personalisation=personalisation, notification_type=notification_type, api_key_id=api_key_id, key_type=key_type, created_at=notification_created_at, job_id=job_id, job_row_number=job_row_number, client_reference=client_reference, reference=reference, created_by_id=created_by_id, status=status, reply_to_text=reply_to_text, status_callback_url=status_callback_url, status_callback_bearer_token=status_callback_bearer_token, ) if notification_type == SMS_TYPE: formatted_recipient = validate_and_format_phone_number_and_allow_international( recipient) recipient_info = get_international_phone_info(formatted_recipient) notification.normalised_to = formatted_recipient notification.international = recipient_info.international notification.phone_prefix = recipient_info.country_prefix notification.rate_multiplier = recipient_info.billable_units # We can't use a sender name/ID if the text is sending to an # international number. At the time of writing, this is because Telstra # won't send to an international number unless sending from the number # associated with the subscription. Additionally, Twilio can send from a # sender name/ID, however, it requires configuration and it depends on # the countries in play. if notification.international: notification.reply_to_text = None elif notification_type == EMAIL_TYPE: notification.normalised_to = format_email_address(notification.to) # if simulated create a Notification model to return but do not persist the Notification to the dB if not simulated: dao_create_notification(notification) if key_type != KEY_TYPE_TEST: if redis_store.get(redis.daily_limit_cache_key(service.id)): redis_store.incr(redis.daily_limit_cache_key(service.id)) if redis_store.get_all_from_hash( cache_key_for_service_template_counter(service.id)): redis_store.increment_hash_value( cache_key_for_service_template_counter(service.id), template_id) increment_template_usage_cache(service.id, template_id, notification_created_at) current_app.logger.info("{} {} created at {}".format( notification_type, notification_id, notification_created_at)) return notification
def test_get_international_info_raises(phone_number): with pytest.raises(InvalidPhoneError) as error: get_international_phone_info(phone_number) assert str(error.value) == 'Did not parse as region ZZ'