def test_process_ses_results_in_complaint(sample_email_template): notification = create_notification(template=sample_email_template, reference='ref1') handle_complaint(json.loads(ses_complaint_callback()['Message'])) complaints = Complaint.query.all() assert len(complaints) == 1 assert complaints[0].notification_id == notification.id
def test_process_ses_results_in_complaint_save_complaint_with_null_complaint_type(notify_api, sample_email_template): notification = create_notification(template=sample_email_template, reference='ref1') msg = json.loads(ses_complaint_callback_with_missing_complaint_type()['Message']) handle_complaint(msg) complaints = Complaint.query.all() assert len(complaints) == 1 assert complaints[0].notification_id == notification.id assert not complaints[0].complaint_type
def test_process_ses_results_in_complaint_if_notification_does_not_exist( sample_email_template, ): notification = create_notification_history(template=sample_email_template, reference="ref1") handle_complaint(json.loads(ses_complaint_callback()["Message"])) complaints = Complaint.query.all() assert len(complaints) == 1 assert complaints[0].notification_id == notification.id
def test_handle_complaint_does_raise_exception_if_notification_not_found(notify_api): response = json.loads(ses_complaint_callback()['Message']) with pytest.raises(expected_exception=SQLAlchemyError): handle_complaint(response)
def test_handle_complaint_does_not_raise_exception_if_reference_is_missing(notify_api): response = json.loads(ses_complaint_callback_malformed_message_id()['Message']) handle_complaint(response) assert len(Complaint.query.all()) == 0
def process_ses_results(self, response): try: ses_message = json.loads(response["Message"]) notification_type = ses_message["notificationType"] if notification_type == "Complaint": _check_and_queue_complaint_callback_task( *handle_complaint(ses_message)) return True aws_response_dict = get_aws_responses(ses_message) notification_status = aws_response_dict["notification_status"] reference = ses_message["mail"]["messageId"] try: notification = notifications_dao.dao_get_notification_by_reference( reference) except NoResultFound: message_time = iso8601.parse_date( ses_message["mail"]["timestamp"]).replace(tzinfo=None) if datetime.utcnow() - message_time < timedelta(minutes=5): self.retry(queue=QueueNames.RETRY) else: current_app.logger.warning( "notification not found for reference: {} (update to {})". format(reference, notification_status)) return notifications_dao._update_notification_status( notification=notification, status=notification_status, provider_response=aws_response_dict["provider_response"], ) if not aws_response_dict["success"]: current_app.logger.info( "SES delivery failed: notification id {} and reference {} has error found. Status {}" .format(notification.id, reference, aws_response_dict["message"])) else: current_app.logger.info( "SES callback return status of {} for notification: {}".format( notification_status, notification.id)) statsd_client.incr("callback.ses.{}".format(notification_status)) if notification.sent_at: statsd_client.timing_with_dates("callback.ses.elapsed-time", datetime.utcnow(), notification.sent_at) _check_and_queue_callback_task(notification) return True except Retry: raise except Exception as e: current_app.logger.exception("Error processing SES results: {}".format( type(e))) self.retry(queue=QueueNames.RETRY)
def process_ses_results(self, response): try: ses_message = json.loads(response['Message']) notification_type = ses_message['notificationType'] bounce_message = None if notification_type == 'Bounce': notification_type, bounce_message = determine_notification_bounce_type(notification_type, ses_message) elif notification_type == 'Complaint': _check_and_queue_complaint_callback_task(*handle_complaint(ses_message)) return True aws_response_dict = get_aws_responses(notification_type) notification_status = aws_response_dict['notification_status'] reference = ses_message['mail']['messageId'] try: notification = notifications_dao.dao_get_notification_or_history_by_reference(reference=reference) except NoResultFound: message_time = iso8601.parse_date(ses_message['mail']['timestamp']).replace(tzinfo=None) if datetime.utcnow() - message_time < timedelta(minutes=5): current_app.logger.info( f"notification not found for reference: {reference} (update to {notification_status}). " f"Callback may have arrived before notification was persisted to the DB. Adding task to retry queue" ) self.retry(queue=QueueNames.RETRY) else: current_app.logger.warning( f"notification not found for reference: {reference} (update to {notification_status})" ) return if bounce_message: current_app.logger.info(f"SES bounce for notification ID {notification.id}: {bounce_message}") if notification.status not in [NOTIFICATION_SENDING, NOTIFICATION_PENDING]: notifications_dao._duplicate_update_warning( notification=notification, status=notification_status ) return else: notifications_dao.dao_update_notifications_by_reference( references=[reference], update_dict={'status': notification_status} ) statsd_client.incr('callback.ses.{}'.format(notification_status)) if notification.sent_at: statsd_client.timing_with_dates('callback.ses.elapsed-time', datetime.utcnow(), notification.sent_at) _check_and_queue_callback_task(notification) return True except Retry: raise except Exception as e: current_app.logger.exception('Error processing SES results: {}'.format(type(e))) self.retry(queue=QueueNames.RETRY)
def process_ses_results(self, response): try: ses_message = json.loads(response['Message']) notification_type = ses_message['notificationType'] if notification_type == 'Bounce': notification_type = determine_notification_bounce_type( notification_type, ses_message) elif notification_type == 'Complaint': _check_and_queue_complaint_callback_task( *handle_complaint(ses_message)) return True aws_response_dict = get_aws_responses(notification_type) notification_status = aws_response_dict['notification_status'] reference = ses_message['mail']['messageId'] try: notification = notifications_dao.dao_get_notification_by_reference( reference) except NoResultFound: message_time = iso8601.parse_date( ses_message['mail']['timestamp']).replace(tzinfo=None) if datetime.utcnow() - message_time < timedelta(minutes=5): self.retry(queue=QueueNames.RETRY) else: current_app.logger.warning( "notification not found for reference: {} (update to {})". format(reference, notification_status)) return if notification.status not in { NOTIFICATION_SENDING, NOTIFICATION_PENDING }: notifications_dao._duplicate_update_warning( notification, notification_status) return notifications_dao._update_notification_status( notification=notification, status=notification_status) if not aws_response_dict['success']: current_app.logger.info( "SES delivery failed: notification id {} and reference {} has error found. Status {}" .format(notification.id, reference, aws_response_dict['message'])) else: current_app.logger.info( 'SES callback return status of {} for notification: {}'.format( notification_status, notification.id)) statsd_client.incr('callback.ses.{}'.format(notification_status)) if notification.sent_at: statsd_client.timing_with_dates('callback.ses.elapsed-time', datetime.utcnow(), notification.sent_at) _check_and_queue_callback_task(notification) return True except Retry: raise except Exception as e: current_app.logger.exception('Error processing SES results: {}'.format( type(e))) self.retry(queue=QueueNames.RETRY)