def exception(cls, method, uri, response, message): # noinspection PyBroadException try: error_payload = json.loads(response.content) if 'message' in error_payload: message = '{}: {}'.format(message, error_payload['message']) code = error_payload.get('code', response.status_code) return TwilioRestException(response.status_code, uri, message, code, method) except: return TwilioRestException(response.status_code, uri, message, response.status_code, method)
def exception(cls, method, uri, response, message): """ Wraps an exceptional response in a `TwilioRestException`. """ # noinspection PyBroadException try: error_payload = json.loads(response.text) if 'message' in error_payload: message = '{}: {}'.format(message, error_payload['message']) code = error_payload.get('code', response.status_code) return TwilioRestException(response.status_code, uri, message, code, method) except Exception: return TwilioRestException(response.status_code, uri, message, response.status_code, method)
def request(self, method, url, params=None, data=None, headers=None, auth=None, timeout=None, allow_redirects=False): request = Request(method, url, auth, params, data, headers) self._requests.append(request) for hologram in self._holograms: if hologram.request == request: return hologram.response message = '\nHolodeck has no hologram for: {}\n'.format(request) if self._holograms: message += 'Holograms loaded:\n' message += '\n'.join(' - {}'.format(h.request) for h in self._holograms) else: message += 'No Holograms loaded' raise TwilioRestException(404, url, message, method=method)
def test_buy_ad_phone_number_fail_number_purchase(self, mock_buy, mock_search, mock_send): mock_return = MagicMock() mock_return.phone_number = "+15552223333" mock_search.return_value = [mock_return] mock_buy.side_effect = \ MagicMock(side_effect=TwilioRestException(401, "https://error.com", "Not Authorized")) test = buy_new_phone_number("https://example.com", {"From": "sim:DExxx"}, "ADV") self.assertFalse(test) mock_send.assert_called_once_with( kwargs={ "from_": "+15556667777", "to": "+15556667777", "body": "There was an " "error purchasing " "your phone number" ": Not Authorized" })
def test_send_sms_by_twilio_failure(self, message_mock): """_send_sms_by_twilio() returns payload with `failed` status and logs an exception.""" body = "Test SMS" sms_to = "+79851686043121212" sms_from = settings.TWILIO_PHONE_NUMBER error_message = f"Unable to create record: The 'To' number {sms_to} is not a valid phone number." status = 500 uri = '/Accounts/ACXXXXXXXXXXXXXXXXX/Messages.json' message_mock.side_effect = TwilioRestException(status, uri, msg=error_message) with self.assertLogs(logger='common.services') as cm: twilio_payload = _send_sms_by_twilio(body, sms_from, sms_to) self.assertEqual(len(cm.output), 2) self.assertIn( f"Sending phone number verification message: | Body: {body} | To: {sms_to} | From {sms_from}", cm.output[0]) self.assertIn(sms_to, cm.output[1]) self.assertIn(error_message, cm.output[1]) self.assertTrue(message_mock.called) self.assertEqual(twilio_payload.status, VERIFICATION_CODE_STATUS_FAILED) self.assertIsNone(twilio_payload.sid)
def test_rest_exception(self, mock_client, mock_sentry): mock_client.return_value.messages.create.side_effect = TwilioRestException( "", "") sendSMS("+15555555555", "Body") mock_sentry.assert_called() self.assertEqual(1, len(mock_sentry.mock_calls)) expected = {"level": "error"} self.assertEqual(expected, mock_sentry.call_args[1])
def test_twilio_exception(self, mock_client): mock_client.messages.create.side_effect = TwilioRestException( status=500, uri="/", msg="Some error") resp = self._do_post({"phone_number": "415 555 1212"}) assert resp.status_code == 200 data = resp.json() assert not data["success"] assert data["errors"] == ["Message failed to send"]
def validate_ssl_certificate(self, client): """ Validate that a request to the new SSL certificate is successful :return: null on success, raise TwilioRestException if the request fails """ response = client.request('GET', 'https://api.twilio.com:8443') if response.status_code < 200 or response.status_code >= 300: raise TwilioRestException(response.status_code, 'https://api.twilio.com:8443', 'Failed to validate SSL certificate')
def test_twilio_error_400(self, send_sms): send_sms.side_effect = TwilioRestException(status=400, uri='http://localhost:8000', msg=('Account not active'), method='POST', code=20005) data = {'phone': '+919327762850'} with pytest.raises(TwilioRestException): self.request(method='POST', post_data=data)
def test_twilio_error_500(self, send_sms): send_sms.side_effect = TwilioRestException(status=500, uri='http://localhost:8000', msg=('Account not active'), method='POST', code=20005) data = {'phone': '+919327762850'} response = self.request(method='POST', post_data=data) assert response.status_code == 200 assert TWILIO_ERRORS['default'] in response.content
def test_raise_exception_when_cannot_send_a_message(create_message_mock): error_message = (f"Unable to create record: The 'To' number " "+491799999999 is not a valid phone number.") status = 500 uri = "/Accounts/ACXXXXXXXXXXXXXXXXX/Messages.json" msg = error_message create_message_mock.side_effect = TwilioRestException(status, uri, msg=error_message) with pytest.raises(TwilioRestException): to = "+491112223" from_ = "+493332221" send_message(to, from_, "Wrong message")
def test_failed_sms_error(self, mfa_settings, twilio_client): mfa_settings.TWILIO_ACCOUNT_SID = "sid" mfa_settings.TWILIO_AUTH_TOKEN = "authtoken" mfa_settings.TWILIO_SMS_POOL_SID = "0987654321" twilio_client_instance = Mock() twilio_client_instance.messages.create.side_effect = ( TwilioRestException(400, "abc")) twilio_client.return_value = twilio_client_instance with self.assertRaises(TwilioMessageError): send_mfa_code_text_message(mfa_instance=self.mfa, mfa_code=self.code)
def test_twilio_error_400(self, send_sms): send_sms.side_effect = TwilioRestException(status=400, uri='http://localhost:8000', msg=('Account not active'), method='POST', code=20005) VerificationDevice.objects.create(user=self.user, unverified_phone=self.user.phone) data = { 'phone': '+919327768250', } with pytest.raises(TwilioRestException): self.request(method='POST', post_data=data)
def test_send_message_raises_unknown_error_code(self): client = self._make_client() self.assertTrue(client.is_enabled_for_alerts) self.assertEqual(0, Event.query.count()) with mock.patch( "airq.models.clients.send_sms", side_effect=TwilioRestException("", "", code=77), ): with self.assertRaises(Exception): client.send_message("testing") client = Client.query.get(client.id) self.assertTrue(client.is_enabled_for_alerts) self.assertEqual(0, Event.query.count())
def test_send_token_with_invalid_phone(self, send_sms): send_sms.side_effect = TwilioRestException( status=400, uri='http://localhost:8000', msg=('Unable to create record: The "To" number +15555555555 is ' 'not a valid phone number.'), method='POST', code=21211) data = {'phone': '+919327762850'} response = self.request(method='POST', post_data=data) assert response.status_code == 200 assert TWILIO_ERRORS[21211] in response.content
def test_twilio_error_500(self, send_sms): send_sms.side_effect = TwilioRestException(status=500, uri='http://localhost:8000', msg=('Account not active'), method='POST', code=20005) VerificationDevice.objects.create(user=self.user, unverified_phone=self.user.phone) data = { 'phone': '+919327768250', } response = self.request(method='POST', post_data=data) assert response.status_code == 200 assert TWILIO_ERRORS['default'] in response.content
def test_send_message_raises_known_error_code(self): client = self._make_client() self.assertTrue(client.is_enabled_for_alerts) self.assertEqual(0, Event.query.count()) with mock.patch( "airq.models.clients.send_sms", side_effect=TwilioRestException( "", "", code=TwilioErrorCode.OUT_OF_REGION.value), ): client.send_message("testing") client = Client.query.get(client.id) self.assertFalse(client.is_enabled_for_alerts) self.assert_event(client.id, EventType.UNSUBSCRIBE_AUTO, zipcode=client.zipcode.zipcode)
def test_log_error_when_cannot_send_message(create_message_mock, caplog): error_message = ( "Unable to create record: The 'To' number " f"{user_phone} is not a valid phone number." ) status = 500 uri = '/Accounts/ACXXXXXXXXXXXXXXXXX/Messages.json' msg = error_message create_message_mock.side_effect = TwilioRestException(status, uri, msg=error_message) to = user_phone from_ = twilio_phone sid = api_sub.send_message(to, from_, "Wrong message") assert sid is None assert "Error:" in caplog.text assert error_message in caplog.text
def test_log_error_when_cannot_send_a_message(create_message_mock, caplog): error_message = (f"Unable to create record: The 'To' number " "+491799999999 is not a valid phone number.") status = 500 uri = "/Accounts/ACXXXXXXXXXXXXXXXXX/Messages.json" msg = error_message create_message_mock.side_effect = TwilioRestException(status, uri, msg=error_message) to = "+491112223" from_ = "+493332221" sid = send_message(to, from_, "Wrong message") assert sid is None assert "Oh no:" in caplog.text assert error_message in caplog.text
def test_signup_twilio_error_400(self, send_sms): send_sms.side_effect = TwilioRestException(status=400, uri='http://localhost:8000', msg=('Account not active'), method='POST', code=20005) data = { 'username': '******', 'email': '', 'phone': '+15555555555', 'password': '******', 'full_name': 'Sherlock Holmes' } with pytest.raises(TwilioRestException): self.request(method='POST', post_data=data) assert VerificationDevice.objects.filter( unverified_phone='+15555555555').exists() is False assert User.objects.count() == 0
def test_twilio_error_400(self, send_sms): send_sms.side_effect = TwilioRestException(status=400, uri='http://localhost:8000', msg=('Account not active'), method='POST', code=20005) data = { 'username': '******', 'phone': '+15555555555', 'password': '******', 'full_name': 'Sherlock Holmes', 'language': 'en' } with pytest.raises(TwilioRestException): self.request(method='POST', post_data=data) assert User.objects.count() == 0 assert VerificationDevice.objects.count() == 0 assert len(mail.outbox) == 0
def test_exception_is_logged_when_raised(client, mocker, backend): with override_settings(PHONE_VERIFICATION=backend): mock_send_verification = mocker.patch( "phone_verify.services.PhoneVerificationService.send_verification") mock_logger = mocker.patch("phone_verify.services.logger") backend_cls = _get_backend_cls(backend) if (backend_cls == "nexmo.NexmoBackend" or backend_cls == "nexmo.NexmoSandboxBackend"): exc = ClientError() mock_send_verification.side_effect = exc elif (backend_cls == "twilio.TwilioBackend" or backend_cls == "twilio.TwilioSandboxBackend"): exc = TwilioRestException(status=mocker.Mock(), uri=mocker.Mock()) mock_send_verification.side_effect = exc send_security_code_and_generate_session_token( phone_number="+13478379634") mock_logger.error.assert_called_once_with( f"Error in sending verification code to +13478379634: {exc}")
def test_signup_twilio_error_500(self, send_sms): send_sms.side_effect = TwilioRestException(status=500, uri='http://localhost:8000', msg=('Account not active'), method='POST', code=20005) data = { 'username': '******', 'email': '', 'phone': '+15555555555', 'password': '******', 'full_name': 'Sherlock Holmes' } response = self.request(method='POST', post_data=data) assert response.status_code == 400 assert TWILIO_ERRORS['default'] in response.content['phone'] assert VerificationDevice.objects.filter( unverified_phone='+15555555555').exists() is False assert User.objects.count() == 0
def test_deactivate(self): # make our channel of the twilio ilk self.org.connect_twilio("TEST_SID", "TEST_TOKEN", self.admin) twilio_channel = self.org.channels.all().first() twilio_channel.channel_type = "T" twilio_channel.save() # mock an authentication failure during the release process with self.settings(IS_PROD=True): with patch("temba.tests.twilio.MockTwilioClient.MockPhoneNumbers.update") as mock_numbers: mock_numbers.side_effect = TwilioRestException( 401, "http://twilio", msg="Authentication Failure", code=20003 ) # releasing shouldn't blow up on auth failures twilio_channel.release() twilio_channel.refresh_from_db() self.assertFalse(twilio_channel.is_active)
def test_twilio_error_500(self, send_sms): send_sms.side_effect = TwilioRestException(status=500, uri='http://localhost:8000', msg=('Account not active'), method='POST', code=20005) data = { 'username': '******', 'phone': '+15555555555', 'password': '******', 'full_name': 'Sherlock Holmes', 'language': 'en' } response = self.request(method='POST', post_data=data) assert response.status_code == 200 assert TWILIO_ERRORS['default'] in response.content self.request(method='POST', post_data=data) assert User.objects.count() == 0 assert VerificationDevice.objects.count() == 0 assert len(mail.outbox) == 0
def test_update_twilio_error_400(self, send_sms): self.user.email = None self.user.phone = '+12345678990' self.user.phone_verified = True self.user.save() send_sms.side_effect = TwilioRestException(status=400, uri='http://localhost:8000', msg=('Account not active'), method='POST', code=20005) data = {'phone': '+15555555555', 'username': '******'} with pytest.raises(TwilioRestException): self.request(method='PUT', post_data=data, user=self.user) assert VerificationDevice.objects.filter( unverified_phone='+15555555555').exists() is False self.user.refresh_from_db() assert self.user.username != 'imagine72' assert self.user.phone == '+12345678990' assert self.user.phone_verified is True
def test_signup_invalid_phone(self, send_sms): send_sms.side_effect = TwilioRestException( status=400, uri='http://localhost:8000', msg=('Unable to create record: The "To" number +15555555555 is ' 'not a valid phone number.'), method='POST', code=21211) data = { 'username': '******', 'email': '', 'phone': '+15555555555', 'password': '******', 'full_name': 'Sherlock Holmes' } response = self.request(method='POST', post_data=data) assert response.status_code == 400 assert TWILIO_ERRORS[21211] in response.content['phone'] assert VerificationDevice.objects.filter( unverified_phone='+15555555555').exists() is False assert User.objects.count() == 0
def test_sign_up_with_invalid_phone_number(self, send_sms): send_sms.side_effect = TwilioRestException( status=400, uri='http://localhost:8000', msg=('Unable to create record: The "To" number +15555555555 is ' 'not a valid phone number.'), method='POST', code=21211) data = { 'username': '******', 'phone': '+15555555555', 'password': '******', 'full_name': 'Sherlock Holmes', 'language': 'en' } response = self.request(method='POST', post_data=data) assert response.status_code == 200 assert TWILIO_ERRORS[21211] in response.content assert User.objects.count() == 0 assert VerificationDevice.objects.count() == 0 assert len(mail.outbox) == 0
def test_twilio_error_400(self, send_sms): send_sms.side_effect = TwilioRestException(status=400, uri='http://localhost:8000', msg=('Account not active'), method='POST', code=20005) user = UserFactory.create(password='******') post_data = { 'username': '******', 'email': user.email, 'phone': '+919327768250', 'language': 'en', 'measurement': 'metric', 'full_name': 'Sherlock Holmes', 'password': '******' } with pytest.raises(TwilioRestException): self.request(method='POST', post_data=post_data, user=user) assert VerificationDevice.objects.count() == 0 user.refresh_from_db() assert user.username != 'new_name'
def test_send_single_message_mock_twilio_exception(create_message_mock, caplog): """Ensure that incorrectly sending the SMS message through a mocked Twilio service will create logging output.""" twilio_phone_number = os.getenv(constants.environment.Twilio_Phone_Number) recipient_phone_number = os.getenv( constants.environment.Recipient_Phone_Number) error_message = f"Unable to create record: The 'To' number {twilio_phone_number} is not a valid phone number." status = 500 uri = "/Accounts/ACXXXXXXXXXXXXXXXXX/Messages.json" create_message_mock.side_effect = TwilioRestException(status, uri, msg=error_message) with pytest.raises(sms.TwilioCommunicationError): sid = sms.send_message( client, recipient_phone_number, twilio_phone_number, "Test: Sending Message Through Twilio", ) assert sid is None assert error_message in caplog.text assert constants.messages.Sms_Did_Not_Work in caplog.text