def get_reply_to_text(notification_type, form, template, form_field=None): reply_to = None if notification_type == EMAIL_TYPE: service_email_reply_to_id = form.get(form_field or "email_reply_to_id") reply_to = ( check_service_email_reply_to_id( str(authenticated_service.id), service_email_reply_to_id, notification_type, ) or template.get_reply_to_text() ) elif notification_type == SMS_TYPE: service_sms_sender_id = form.get(form_field or "sms_sender_id") sms_sender_id = check_service_sms_sender_id(str(authenticated_service.id), service_sms_sender_id, notification_type) if sms_sender_id: reply_to = try_validate_and_format_phone_number(sms_sender_id) else: reply_to = template.get_reply_to_text() elif notification_type == LETTER_TYPE: reply_to = template.get_reply_to_text() return reply_to
def dao_get_notifications_by_recipient_or_reference( service_id, search_term, notification_type=None, statuses=None, page=1, page_size=None, ): if notification_type == SMS_TYPE: normalised = try_validate_and_format_phone_number(search_term) for character in {'(', ')', ' ', '-'}: normalised = normalised.replace(character, '') normalised = normalised.lstrip('+0') elif notification_type == EMAIL_TYPE: try: normalised = validate_and_format_email_address(search_term) except InvalidEmailError: normalised = search_term.lower() elif notification_type in {LETTER_TYPE, None}: # For letters, we store the address without spaces, so we need # to removes spaces from the search term to match. We also do # this when a notification type isn’t provided (this will # happen if a user doesn’t have permission to see the dashboard) # because email addresses and phone numbers will never be stored # with spaces either. normalised = ''.join(search_term.split()).lower() else: raise TypeError( f'Notification type must be {EMAIL_TYPE}, {SMS_TYPE}, {LETTER_TYPE} or None' ) normalised = escape_special_characters(normalised) search_term = escape_special_characters(search_term) filters = [ Notification.service_id == service_id, or_( Notification.normalised_to.like("%{}%".format(normalised)), Notification.client_reference.ilike("%{}%".format(search_term)), ), Notification.key_type != KEY_TYPE_TEST, ] if statuses: filters.append(Notification.status.in_(statuses)) if notification_type: filters.append(Notification.notification_type == notification_type) results = db.session.query(Notification)\ .filter(*filters)\ .order_by(desc(Notification.created_at))\ .paginate(page=page, per_page=page_size) return results
def get_inbound_sms_for_service(service_id): user_number = request.args.get('user_number') if user_number: # we use this to normalise to an international phone number - but this may fail if it's an alphanumeric user_number = try_validate_and_format_phone_number(user_number, international=True) results = dao_get_inbound_sms_for_service(service_id, user_number=user_number) return jsonify(data=[row.serialize() for row in results])
def post_query_inbound_sms_for_service(service_id): form = validate(request.get_json(), get_inbound_sms_for_service_schema) if 'phone_number' in form: # we use this to normalise to an international phone number - but this may fail if it's an alphanumeric user_number = try_validate_and_format_phone_number( form['phone_number'], international=True) else: user_number = None results = dao_get_inbound_sms_for_service(service_id, form.get('limit'), user_number) return jsonify(data=[row.serialize() for row in results])
def create_inbound_sms_object(service, content, from_number, provider_ref, provider_name): user_number = try_validate_and_format_phone_number( from_number, international=True, log_msg='Invalid from_number received') inbound = InboundSms(service=service, notify_number=service.get_inbound_number(), user_number=user_number, provider_date=datetime.utcnow(), provider_reference=provider_ref, content=content, provider=provider_name) dao_create_inbound_sms(inbound) return inbound
def post_inbound_sms_for_service(service_id): form = validate(request.get_json(), get_inbound_sms_for_service_schema) user_number = form.get("phone_number") if user_number: # we use this to normalise to an international phone number - but this may fail if it's an alphanumeric user_number = try_validate_and_format_phone_number(user_number, international=True) inbound_data_retention = fetch_service_data_retention_by_notification_type( service_id, "sms") limit_days = inbound_data_retention.days_of_retention if inbound_data_retention else 7 results = dao_get_inbound_sms_for_service(service_id, user_number=user_number, limit_days=limit_days) return jsonify(data=[row.serialize() for row in results])
def get_user_number(service_id, notification_id): try: number = service_api_client.get_inbound_sms_by_id( service_id, notification_id)['user_number'] except HTTPError: notification = notification_api_client.get_notification( service_id, notification_id) number = notification['normalised_to'] # For old records normalised_to may be empty or it may be stored in the # old format (without storing the leading plus sign). If this is the # case, use the to field instead and create the E.164 format on the fly. if not number or not number.startswith('+'): number = notification['to'] return try_validate_and_format_phone_number(number)
def create_inbound_sms_keyword_object(service, content, from_number, provider_ref, date_received, provider_name): user_number = try_validate_and_format_phone_number( from_number, international=False, log_msg='Invalid from_number received' ) inbound = InboundSmsKeyword( service=service, notify_short_number=service.get_inbound_shortnumber(), user_number=user_number, provider_date=date_received, provider_reference=provider_ref, content=content, provider=provider_name ) dao_create_inbound_sms_keyword(inbound) return inbound
def create_inbound_sms_object(service: Service, content: str, notify_number: str, from_number: str, provider_ref: Union[str, None], date_received: datetime, provider_name: str) -> InboundSms: user_number = try_validate_and_format_phone_number( from_number, international=True, log_msg='Invalid from_number received') inbound = InboundSms(service=service, notify_number=notify_number, user_number=user_number, provider_date=date_received, provider_reference=provider_ref, content=content, provider=provider_name) dao_create_inbound_sms(inbound) return inbound
def create_inbound_sms_object(service, content, from_number, provider_ref, date_received, provider_name): user_number = try_validate_and_format_phone_number( from_number, international=True, log_msg=f'Invalid from_number received for service "{service.id}"') provider_date = date_received if provider_date: provider_date = format_mmg_datetime(provider_date) inbound = InboundSms(service=service, notify_number=service.get_inbound_number(), user_number=user_number, provider_date=provider_date, provider_reference=provider_ref, content=content, provider=provider_name) dao_create_inbound_sms(inbound) return inbound
def dao_get_notifications_by_to_field(service_id, search_term, notification_type=None, statuses=None): if notification_type is None: notification_type = guess_notification_type(search_term) if notification_type == SMS_TYPE: normalised = try_validate_and_format_phone_number(search_term) for character in {'(', ')', ' ', '-'}: normalised = normalised.replace(character, '') normalised = normalised.lstrip('+0') elif notification_type == EMAIL_TYPE: try: normalised = validate_and_format_email_address(search_term) except InvalidEmailError: normalised = search_term.lower() else: raise InvalidRequest("Only email and SMS can use search by recipient", 400) normalised = escape_special_characters(normalised) filters = [ Notification.service_id == service_id, Notification.normalised_to.like("%{}%".format(normalised)), Notification.key_type != KEY_TYPE_TEST, ] if statuses: filters.append(Notification.status.in_(statuses)) if notification_type: filters.append(Notification.notification_type == notification_type) results = db.session.query(Notification).filter(*filters).order_by( desc(Notification.created_at)).all() return results
def test_try_format_recipient_doesnt_throw(): assert try_validate_and_format_phone_number('ALPHANUM3R1C') == 'ALPHANUM3R1C'