From 20b4d1f6eea74cc5115378501ee850e77a18578e Mon Sep 17 00:00:00 2001 From: jimmoffet Date: Fri, 7 Oct 2022 17:17:57 -0700 Subject: [PATCH] save reference on outgoing SMS to be connected to inbound replies --- app/clients/sms/aws_sns.py | 20 ++++++++++---------- app/dao/services_dao.py | 11 +++++++++++ app/delivery/send_to_providers.py | 6 +++++- app/notifications/receive_notifications.py | 11 ++++++----- app/notifications/sns_handlers.py | 2 +- 5 files changed, 33 insertions(+), 17 deletions(-) diff --git a/app/clients/sms/aws_sns.py b/app/clients/sms/aws_sns.py index 96d593ec0..4cf62e17a 100644 --- a/app/clients/sms/aws_sns.py +++ b/app/clients/sms/aws_sns.py @@ -42,31 +42,31 @@ class AwsSnsClient(SmsClient): "AWS.SNS.SMS.SMSType": { "DataType": "String", "StringValue": "Transactional", + }, + "AWS.MM.SMS.OriginationNumber": { + "DataType": "String", + "StringValue": self.current_app.config["AWS_US_TOLL_FREE_NUMBER"], } } - # If sending with a long code number, we need to use another AWS region - # and specify the phone number we want to use as the origination number + # sender is managed in the UI in settings > Text message senders send_with_dedicated_phone_number = self._send_with_dedicated_phone_number(sender) + if send_with_dedicated_phone_number: client = self._long_codes_client attributes["AWS.MM.SMS.OriginationNumber"] = { "DataType": "String", "StringValue": sender, } - - # If the number is US based, we must use a US Toll Free number to send the message + country = phonenumbers.region_code_for_number(match.number) - if country == "US": - client = self._long_codes_client - attributes["AWS.MM.SMS.OriginationNumber"] = { - "DataType": "String", - "StringValue": self.current_app.config["AWS_US_TOLL_FREE_NUMBER"], - } try: start_time = monotonic() response = client.publish(PhoneNumber=to, Message=content, MessageAttributes=attributes) + self.current_app.logger.info('RESPONSE FROM AWS SNS:') + for k,v in response.items(): + self.current_app.logger.info(f'{k}: {v}') except botocore.exceptions.ClientError as e: self.statsd_client.incr("clients.sns.error") raise str(e) diff --git a/app/dao/services_dao.py b/app/dao/services_dao.py index 1f951dcb7..2821c1c6e 100644 --- a/app/dao/services_dao.py +++ b/app/dao/services_dao.py @@ -207,6 +207,17 @@ def dao_fetch_service_by_inbound_number(number): Service.id == inbound_number.service_id ).first() +def dao_fetch_service_by_reference(reference): + previous_message = Notification.query.filter( + Notification.reference == reference + ).first() + + if not previous_message: + return None + + return Service.query.filter( + Service.id == previous_message.service_id + ).first() def dao_fetch_service_by_id_with_api_keys(service_id, only_active=False): query = Service.query.filter_by( diff --git a/app/delivery/send_to_providers.py b/app/delivery/send_to_providers.py index e3e8aa6b4..6c9e9b8b8 100644 --- a/app/delivery/send_to_providers.py +++ b/app/delivery/send_to_providers.py @@ -81,7 +81,11 @@ def send_sms_to_provider(notification): 'international': notification.international, } db.session.close() # no commit needed as no changes to objects have been made above - provider.send_sms(**send_sms_kwargs) + ref = provider.send_sms(**send_sms_kwargs) + notification.reference = ref + dao_update_notification(notification) + + except Exception as e: notification.billable_units = template.fragment_count dao_update_notification(notification) diff --git a/app/notifications/receive_notifications.py b/app/notifications/receive_notifications.py index c60cc9ea8..31c74d6ea 100644 --- a/app/notifications/receive_notifications.py +++ b/app/notifications/receive_notifications.py @@ -9,7 +9,7 @@ from notifications_utils.recipients import try_validate_and_format_phone_number from app.celery import tasks from app.config import QueueNames from app.dao.inbound_sms_dao import dao_create_inbound_sms -from app.dao.services_dao import dao_fetch_service_by_inbound_number +from app.dao.services_dao import dao_fetch_service_by_reference from app.errors import InvalidRequest, register_errors from app.models import INBOUND_SMS_TYPE, SMS_TYPE, InboundSms from app.notifications.sns_handlers import sns_notification_handler @@ -52,7 +52,7 @@ def receive_sns_sms(): # TODO use standard formatting we use for all US numbers inbound_number = message['destinationNumber'].replace('+','') - service = fetch_potential_service(inbound_number, 'sns') + service = fetch_potential_service(message['previousPublishedMessageId'], 'sns') if not service: # since this is an issue with our service <-> number mapping, or no inbound_sms service permission # we should still tell SNS that we received it successfully @@ -218,12 +218,13 @@ def create_inbound_sms_object(service, content, from_number, provider_ref, date_ return inbound -def fetch_potential_service(inbound_number, provider_name): - service = dao_fetch_service_by_inbound_number(inbound_number) +def fetch_potential_service(reference, provider_name): + service = dao_fetch_service_by_reference(reference) + # service = dao_fetch_service_by_inbound_number(inbound_number) if not service: current_app.logger.warning('Inbound number "{}" from {} not associated with a service'.format( - inbound_number, provider_name + reference, provider_name )) return False diff --git a/app/notifications/sns_handlers.py b/app/notifications/sns_handlers.py index 6ef1085b5..d6368e57c 100644 --- a/app/notifications/sns_handlers.py +++ b/app/notifications/sns_handlers.py @@ -58,7 +58,7 @@ def sns_notification_handler(data, headers): current_app.logger.warning(f"Attempt to raise_for_status()SubscriptionConfirmation Type message files for response: {response.text} with error {e}") raise InvalidRequest("SES-SNS callback failed: attempt to raise_for_status()SubscriptionConfirmation Type message failed", 400) current_app.logger.info("SES-SNS auto-confirm subscription callback succeeded") - return {'subscriptionConfirmed': True} + return message, message.get('Type') # TODO remove after smoke testing on prod is implemented current_app.logger.info(f"SNS message: {message} is a valid message. Attempting to process it now.")