2022-06-17 11:16:23 -07:00
|
|
|
from time import monotonic
|
|
|
|
|
|
|
|
|
|
import botocore
|
|
|
|
|
import phonenumbers
|
2023-02-28 16:50:00 -05:00
|
|
|
from boto3 import client
|
2022-06-17 11:16:23 -07:00
|
|
|
|
|
|
|
|
from app.clients.sms import SmsClient
|
2023-02-28 16:50:00 -05:00
|
|
|
from app.cloudfoundry_config import cloud_config
|
2022-06-17 11:16:23 -07:00
|
|
|
|
|
|
|
|
|
|
|
|
|
class AwsSnsClient(SmsClient):
|
|
|
|
|
"""
|
|
|
|
|
AwsSns sms client
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
def init_app(self, current_app, statsd_client, *args, **kwargs):
|
2023-02-28 16:50:00 -05:00
|
|
|
self._client = client(
|
|
|
|
|
"sns",
|
|
|
|
|
region_name=cloud_config.sns_region,
|
|
|
|
|
aws_access_key_id=cloud_config.sns_access_key,
|
|
|
|
|
aws_secret_access_key=cloud_config.sns_secret_key
|
|
|
|
|
)
|
2022-06-17 11:16:23 -07:00
|
|
|
super(SmsClient, self).__init__(*args, **kwargs)
|
|
|
|
|
self.current_app = current_app
|
|
|
|
|
self.statsd_client = statsd_client
|
2022-10-14 14:45:27 +00:00
|
|
|
|
2022-06-17 11:16:23 -07:00
|
|
|
@property
|
|
|
|
|
def name(self):
|
|
|
|
|
return 'sns'
|
|
|
|
|
|
2022-06-25 13:05:10 -07:00
|
|
|
def get_name(self):
|
2023-02-28 16:50:00 -05:00
|
|
|
return self.name
|
2022-06-25 13:05:10 -07:00
|
|
|
|
2022-06-17 11:16:23 -07:00
|
|
|
def send_sms(self, to, content, reference, sender=None, international=False):
|
|
|
|
|
matched = False
|
|
|
|
|
|
|
|
|
|
for match in phonenumbers.PhoneNumberMatcher(to, "US"):
|
|
|
|
|
matched = True
|
|
|
|
|
to = phonenumbers.format_number(match.number, phonenumbers.PhoneNumberFormat.E164)
|
|
|
|
|
|
|
|
|
|
# See documentation
|
|
|
|
|
# https://docs.aws.amazon.com/sns/latest/dg/sms_publish-to-phone.html#sms_publish_sdk
|
|
|
|
|
attributes = {
|
|
|
|
|
"AWS.SNS.SMS.SMSType": {
|
|
|
|
|
"DataType": "String",
|
|
|
|
|
"StringValue": "Transactional",
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-02-28 16:50:00 -05:00
|
|
|
if sender:
|
2022-06-17 11:16:23 -07:00
|
|
|
attributes["AWS.MM.SMS.OriginationNumber"] = {
|
|
|
|
|
"DataType": "String",
|
|
|
|
|
"StringValue": sender,
|
|
|
|
|
}
|
2023-02-28 16:50:00 -05:00
|
|
|
else:
|
2022-06-17 11:16:23 -07:00
|
|
|
attributes["AWS.MM.SMS.OriginationNumber"] = {
|
|
|
|
|
"DataType": "String",
|
|
|
|
|
"StringValue": self.current_app.config["AWS_US_TOLL_FREE_NUMBER"],
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
start_time = monotonic()
|
2023-02-28 16:50:00 -05:00
|
|
|
response = self._client.publish(PhoneNumber=to, Message=content, MessageAttributes=attributes)
|
2022-06-17 11:16:23 -07:00
|
|
|
except botocore.exceptions.ClientError as e:
|
|
|
|
|
self.statsd_client.incr("clients.sns.error")
|
|
|
|
|
raise str(e)
|
|
|
|
|
except Exception as e:
|
|
|
|
|
self.statsd_client.incr("clients.sns.error")
|
|
|
|
|
raise str(e)
|
|
|
|
|
finally:
|
|
|
|
|
elapsed_time = monotonic() - start_time
|
|
|
|
|
self.current_app.logger.info("AWS SNS request finished in {}".format(elapsed_time))
|
|
|
|
|
self.statsd_client.timing("clients.sns.request-time", elapsed_time)
|
|
|
|
|
self.statsd_client.incr("clients.sns.success")
|
|
|
|
|
return response["MessageId"]
|
|
|
|
|
|
|
|
|
|
if not matched:
|
|
|
|
|
self.statsd_client.incr("clients.sns.error")
|
|
|
|
|
self.current_app.logger.error("No valid numbers found in {}".format(to))
|
|
|
|
|
raise ValueError("No valid numbers found for SMS delivery")
|