def __init__(self, hostname, shared_access_key_name, shared_access_key): def get_token(): expiry = int(time.time() + default_sas_expiry) sas = base64.b64decode(shared_access_key) string_to_sign = (hostname + "\n" + str(expiry)).encode("utf-8") signed_hmac_sha256 = hmac.HMAC(sas, string_to_sign, hashlib.sha256) signature = urllib.parse.quote(base64.b64encode(signed_hmac_sha256.digest())) return AccessToken( "SharedAccessSignature sr={}&sig={}&se={}&skn={}".format( hostname, signature, expiry, shared_access_key_name ), expiry, ) auth = uamqp.authentication.JWTTokenAuth( audience="https://" + hostname, uri="https://" + hostname, get_token=get_token, token_type=b"servicebus.windows.net:sastoken", ) auth.update_token() self.amqp_client = uamqp.SendClient( target="amqps://" + hostname + "/messages/devicebound", auth=auth, keep_alive_interval=120, )
def __init__(self, hostname, shared_access_key_name, shared_access_key): self.endpoint = self._build_amqp_endpoint( hostname, shared_access_key_name, shared_access_key ) operation = "/messages/devicebound" target = "amqps://" + self.endpoint + operation self.amqp_client = uamqp.SendClient(target)
def test_event_hubs_send_large_message_after_socket_lost(live_eventhub_config): uri = "sb://{}/{}".format(live_eventhub_config['hostname'], live_eventhub_config['event_hub']) sas_auth = authentication.SASTokenAuth.from_shared_access_key( uri, live_eventhub_config['key_name'], live_eventhub_config['access_key']) target = "amqps://{}/{}".format(live_eventhub_config['hostname'], live_eventhub_config['event_hub']) send_client = uamqp.SendClient(target, auth=sas_auth, debug=True) try: send_client.open() while not send_client.client_ready(): send_client.do_work() # the connection idle timeout setting on the EH service is 240s, after 240s no activity # on the connection, the service would send detach to the client, the underlying socket on the client # is still able to work to receive the frame. # HOWEVER, after no activity on the client socket > 300s, the underlying socket would get completely lost: # the socket reports "Failure: sending socket failed 10054" on windows # or "Failure: sending socket failed. errno=104" on linux which indicates the socket is lost time.sleep(350) with pytest.raises(uamqp.errors.AMQPConnectionError): send_client.send_message(uamqp.message.Message(b't' * 1024 * 700)) finally: send_client.close()
def test_event_hubs_client_send_sync(live_eventhub_config): annotations = {b"x-opt-partition-key": b"PartitionKeyInfo"} uri = "sb://{}/{}".format(live_eventhub_config['hostname'], live_eventhub_config['event_hub']) sas_auth = authentication.SASTokenAuth.from_shared_access_key( uri, live_eventhub_config['key_name'], live_eventhub_config['access_key']) target = "amqps://{}/{}".format(live_eventhub_config['hostname'], live_eventhub_config['event_hub']) send_client = uamqp.SendClient(target, auth=sas_auth, debug=False) for _ in range(10): header = uamqp.message.MessageHeader() header.durable = True assert header.get_header_obj() props = uamqp.message.MessageProperties(message_id=b"message id", subject="test_subject") assert props.get_properties_obj() msg_content = b"hello world" message = uamqp.Message(msg_content, properties=props, header=header, application_properties=annotations, annotations=annotations) assert message.get_message_encoded_size() == 151 assert message.encode_message( ) == b'\x00Sp\xc0\x06\x05A@@@C\x00Sr\xc1(\x02\xa1\x13x-opt-partition-key\xa1\x10PartitionKeyInfo\x00Ss\xc0\x1d\x04\xa1\nmessage id@@\xa1\x0ctest_subject\x00St\xc1(\x02\xa1\x13x-opt-partition-key\xa1\x10PartitionKeyInfo\x00Su\xa0\x0bhello world' send_client.queue_message(message) results = send_client.send_all_messages(close_on_done=False) assert not [ m for m in results if m == uamqp.constants.MessageState.SendFailed ] send_client.close()
def connect(self, service_connection_string): self.config = connection_string_to_dictionary(service_connection_string) self.endpoint = _build_iothub_amqp_endpoint(self.config) operation = "/messages/devicebound" target = "amqps://" + self.endpoint + operation logger.info("Target: {}".format(target)) self.send_client = uamqp.SendClient(target, debug=True)
def send_c2d_message(target, device_id, data, properties=None, correlation_id=None, ack=None): app_props = {} if properties: app_props.update(properties) app_props['iothub-ack'] = (ack if ack else 'none') msg_props = uamqp.message.MessageProperties() msg_props.to = '/devices/{}/messages/devicebound'.format(device_id) msg_id = str(uuid4()) msg_props.message_id = msg_id if correlation_id: msg_props.correlation_id = correlation_id msg_content = str.encode(data) message = uamqp.Message(msg_content, properties=msg_props, application_properties=app_props) operation = '/messages/devicebound' endpoint = _build_iothub_amqp_endpoint_from_target(target) endpoint = endpoint + operation client = uamqp.SendClient('amqps://' + endpoint, debug=DEBUG) client.queue_message(message) result = client.send_all_messages() errors = [m for m in result if m == uamqp.constants.MessageState.SendFailed] return msg_id, errors
def test_rabbitmq_client_send_sync(rabbit_mq_config): pytest.skip("Not working yet") uri = "amqp://{}/{}/".format(rabbit_mq_config['hostname'], rabbit_mq_config['path']) sas_auth = uamqp.authentication.SASLAnonymous(hostname=rabbit_mq_config['hostname'], port=5672) send_client = uamqp.SendClient(uri, auth=sas_auth, debug=True) try: message = uamqp.Message("content") send_client.queue_message(message) results = send_client.send_all_messages(close_on_done=False) assert not [m for m in results if m == uamqp.constants.MessageState.SendFailed] finally: send_client.close()
def test_event_hubs_client_send_multiple_sync(live_eventhub_config): annotations = {b"x-opt-partition-key": b"PartitionKeyInfo"} uri = "sb://{}/{}".format(live_eventhub_config['hostname'], live_eventhub_config['event_hub']) sas_auth = authentication.SASTokenAuth.from_shared_access_key( uri, live_eventhub_config['key_name'], live_eventhub_config['access_key']) assert not sas_auth.consumed target = "amqps://{}/{}".format(live_eventhub_config['hostname'], live_eventhub_config['event_hub']) send_client = uamqp.SendClient(target, auth=sas_auth, debug=False) messages = [] for _ in range(10): header = uamqp.message.MessageHeader() header.durable = True header.delivery_count = 5 header.time_to_live = 500000 header.first_acquirer = True header.priority = 3 assert header.get_header_obj() props = uamqp.message.MessageProperties( message_id=b"message id", user_id="user_id", to="to", subject="test", reply_to="reply_to", correlation_id="correlation_id", content_type="content_type", content_encoding="content_encoding", creation_time=12345, absolute_expiry_time=12345, group_id="group_id", group_sequence=1234, reply_to_group_id="reply_to_group_id") assert props.get_properties_obj() msg_content = b"hello world" message = uamqp.Message(msg_content, properties=props, header=header, application_properties=annotations, annotations=annotations) messages.append(message) send_client.queue_message(*messages) assert len(send_client.pending_messages) == 10 results = send_client.send_all_messages() assert len(results) == 10 assert not [ m for m in results if m == uamqp.constants.MessageState.SendFailed ] assert sas_auth.consumed assert send_client.pending_messages == []
def test_event_hubs_single_send_sync(live_eventhub_config): annotations={b"x-opt-partition-key": b"PartitionKeyInfo"} msg_content = b"hello world" uri = "sb://{}/{}".format(live_eventhub_config['hostname'], live_eventhub_config['event_hub']) sas_auth = authentication.SASTokenAuth.from_shared_access_key( uri, live_eventhub_config['key_name'], live_eventhub_config['access_key']) target = "amqps://{}/{}".format(live_eventhub_config['hostname'], live_eventhub_config['event_hub']) send_client = uamqp.SendClient(target, auth=sas_auth, debug=False) for _ in range(10): message = uamqp.Message(msg_content, application_properties=annotations, annotations=annotations) send_client.send_message(message) send_client.close()
def test_event_hubs_send_override_token_refresh_window(live_eventhub_config): uri = "sb://{}/{}".format(live_eventhub_config['hostname'], live_eventhub_config['event_hub']) target = "amqps://{}/{}/Partitions/0".format( live_eventhub_config['hostname'], live_eventhub_config['event_hub']) token = [None] def get_token(): return _AccessToken(token[0], expiry) jwt_auth = authentication.JWTTokenAuth( uri, uri, get_token, refresh_window=300 # set refresh window to be 5 mins ) send_client = uamqp.SendClient(target, auth=jwt_auth, debug=False) # use token of which the valid remaining time < refresh window expiry = int(time.time()) + (60 * 4 + 30) # 4.5 minutes token[0] = utils.create_sas_token( live_eventhub_config['key_name'].encode(), live_eventhub_config['access_key'].encode(), uri.encode(), expiry=timedelta(minutes=4, seconds=30)) for _ in range(3): message = uamqp.message.Message(body='Hello World') send_client.send_message(message) auth_status = constants.CBSAuthStatus(jwt_auth._cbs_auth.get_status()) assert auth_status == constants.CBSAuthStatus.RefreshRequired # update token, the valid remaining time > refresh window expiry = int(time.time()) + (60 * 5 + 30) # 5.5 minutes token[0] = utils.create_sas_token( live_eventhub_config['key_name'].encode(), live_eventhub_config['access_key'].encode(), uri.encode(), expiry=timedelta(minutes=5, seconds=30)) for _ in range(3): message = uamqp.message.Message(body='Hello World') send_client.send_message(message) auth_status = constants.CBSAuthStatus(jwt_auth._cbs_auth.get_status()) assert auth_status == constants.CBSAuthStatus.Ok send_client.close()
def __init__( self, hostname, token_credential, token_scope="https://iothubs.azure.net/.default" ): def get_token(): result = token_credential.get_token(token_scope) return AccessToken("Bearer " + result.token, result.expires_on) auth = uamqp.authentication.JWTTokenAuth( audience=token_scope, uri="https://" + hostname, get_token=get_token, token_type=b"bearer", ) auth.update_token() target = "amqps://" + hostname + "/messages/devicebound" self.amqp_client = uamqp.SendClient(target=target, auth=auth, keep_alive_interval=120)
def send_multiple_message(live_eventhub_config, msg_count): def data_generator(): for i in range(msg_count): msg_content = "Hello world {}".format(i).encode('utf-8') yield msg_content uri = "sb://{}/{}".format(live_eventhub_config['hostname'], live_eventhub_config['event_hub']) sas_auth = authentication.SASTokenAuth.from_shared_access_key( uri, live_eventhub_config['key_name'], live_eventhub_config['access_key']) target = "amqps://{}/{}/Partitions/{}".format(live_eventhub_config['hostname'], live_eventhub_config['event_hub'], live_eventhub_config['partition']) send_client = uamqp.SendClient(target, auth=sas_auth, debug=False) message_batch = uamqp.message.BatchMessage(data_generator()) send_client.queue_message(message_batch) results = send_client.send_all_messages(close_on_done=False) assert not [m for m in results if m == uamqp.constants.MessageState.SendFailed] send_client.close()
def test_event_hubs_idempotent_producer(live_eventhub_config): uri = "sb://{}/{}".format(live_eventhub_config['hostname'], live_eventhub_config['event_hub']) sas_auth = authentication.SASTokenAuth.from_shared_access_key( uri, live_eventhub_config['key_name'], live_eventhub_config['access_key']) target = "amqps://{}/{}/Partitions/0".format( live_eventhub_config['hostname'], live_eventhub_config['event_hub']) symbol_array = [ uamqp_types.AMQPSymbol(b"com.microsoft:idempotent-producer") ] desired_capabilities = utils.data_factory( uamqp_types.AMQPArray(symbol_array)) link_properties = { uamqp_types.AMQPSymbol(b"com.microsoft:timeout"): uamqp_types.AMQPLong(int(60 * 1000)) } def on_attach(attach_source, attach_target, properties, error): if str(attach_target) == target: on_attach.owner_level = properties.get( b"com.microsoft:producer-epoch") on_attach.producer_group_id = properties.get( b"com.microsoft:producer-id") on_attach.starting_sequence_number = properties.get( b"com.microsoft:producer-sequence-number") send_client = uamqp.SendClient(target, auth=sas_auth, desired_capabilities=desired_capabilities, link_properties=link_properties, on_attach=on_attach, debug=True) send_client.open() while not send_client.client_ready(): time.sleep(0.05) assert on_attach.owner_level is not None assert on_attach.producer_group_id is not None assert on_attach.starting_sequence_number is not None send_client.close()
def test_iot_hub_send(live_iothub_config): msg_content = b"hello world" app_properties = {"test_prop_1": "value", "test_prop_2": "X"} msg_props = uamqp.message.MessageProperties() msg_props.to = '/devices/{}/messages/devicebound'.format(live_iothub_config['device']) msg_props.message_id = str(uuid4()) message = uamqp.Message(msg_content, properties=msg_props, application_properties=app_properties) operation = '/messages/devicebound' endpoint = _build_iothub_amqp_endpoint_from_target(live_iothub_config) target = 'amqps://' + endpoint + operation log.info("Target: {}".format(target)) send_client = uamqp.SendClient(target, debug=True) send_client.queue_message(message) results = send_client.send_all_messages() assert not [m for m in results if m == uamqp.constants.MessageState.SendFailed] log.info("Message sent.")
def test_event_hubs_send_timeout_sync(live_eventhub_config): def _hack_client_run(cls): """MessageSender Link is now open - perform message send on all pending messages. Will return True if operation successful and client can remain open for further work. :rtype: bool """ # pylint: disable=protected-access time.sleep(6) cls.message_handler.work() cls._waiting_messages = 0 cls._pending_messages = cls._filter_pending() if cls._backoff and not cls._waiting_messages: log.info("Client told to backoff - sleeping for %r seconds", cls._backoff) cls._connection.sleep(cls._backoff) cls._backoff = 0 cls._connection.work() return True uri = "sb://{}/{}".format(live_eventhub_config['hostname'], live_eventhub_config['event_hub']) sas_auth = authentication.SASTokenAuth.from_shared_access_key( uri, live_eventhub_config['key_name'], live_eventhub_config['access_key']) target = "amqps://{}/{}/Partitions/0".format( live_eventhub_config['hostname'], live_eventhub_config['event_hub']) send_client = uamqp.SendClient(target, auth=sas_auth, debug=False, msg_timeout=5000) send_client._client_run = types.MethodType(_hack_client_run, send_client) send_client.open() with pytest.raises(uamqp.errors.ClientMessageError): send_client.send_message(uamqp.message.Message(body='Hello World')) send_client.close()
def event_hubs_send_different_amqp_body_type_sync(live_eventhub_config): uri = "sb://{}/{}".format(live_eventhub_config['hostname'], live_eventhub_config['event_hub']) sas_auth = authentication.SASTokenAuth.from_shared_access_key( uri, live_eventhub_config['key_name'], live_eventhub_config['access_key']) target = "amqps://{}/{}/Partitions/0".format(live_eventhub_config['hostname'], live_eventhub_config['event_hub']) send_client = uamqp.SendClient(target, auth=sas_auth, debug=False) data_body_1 = [b'data1', b'data2'] data_body_message_1 = uamqp.message.Message(body=data_body_1) data_body_message_1.application_properties = {'body_type': 'data_body_1'} send_client.queue_message(data_body_message_1) data_body_2 = b'data1' data_body_message_2 = uamqp.message.Message(body=data_body_2, body_type=MessageBodyType.Data) data_body_message_2.application_properties = {'body_type': 'data_body_2'} send_client.queue_message(data_body_message_2) value_body_1 = [b'data1', -1.23, True, {b'key': b'value'}, [1, False, 1.23, b'4']] value_body_message_1 = uamqp.message.Message(body=value_body_1) value_body_message_1.application_properties = {'body_type': 'value_body_1'} send_client.queue_message(value_body_message_1) value_body_2 = {b'key1': {b'sub_key': b'sub_value'}, b'key2': b'value', 3: -1.23} value_body_message_2 = uamqp.message.Message(body=value_body_2, body_type=MessageBodyType.Value) value_body_message_2.application_properties = {'body_type': 'value_body_2'} send_client.queue_message(value_body_message_2) sequence_body_1 = [b'data1', -1.23, True, {b'key': b'value'}, [b'a', 1.23, True]] sequence_body_message_1 = uamqp.message.Message(body=sequence_body_1, body_type=MessageBodyType.Sequence) sequence_body_message_1.application_properties = {'body_type': 'sequence_body_1'} send_client.queue_message(sequence_body_message_1) sequence_body_2 = [[1, 2, 3], [b'aa', b'bb', b'cc'], [True, False, True], [{b'key1': b'value'}, {b'key2': 123}]] sequence_body_message_2 = uamqp.message.Message(body=sequence_body_2, body_type=MessageBodyType.Sequence) sequence_body_message_2.application_properties = {'body_type': 'sequence_body_2'} send_client.queue_message(sequence_body_message_2) results = send_client.send_all_messages(close_on_done=False) assert not [m for m in results if m == uamqp.constants.MessageState.SendFailed] sas_auth = authentication.SASTokenAuth.from_shared_access_key( uri, live_eventhub_config['key_name'], live_eventhub_config['access_key']) source = "amqps://{}/{}/ConsumerGroups/{}/Partitions/{}".format( live_eventhub_config['hostname'], live_eventhub_config['event_hub'], live_eventhub_config['consumer_group'], 0) result_dic = {} receive_client = uamqp.ReceiveClient(source, auth=sas_auth, timeout=5000, debug=False, prefetch=10) gen = receive_client.receive_messages_iter() for message in gen: if message.application_properties and message.application_properties.get(b'body_type'): if message.application_properties.get(b'body_type') == b'data_body_1': check_list = [data for data in message.get_data()] assert isinstance(message._body, DataBody) assert check_list == data_body_1 result_dic['data_body_1'] = 1 elif message.application_properties.get(b'body_type') == b'data_body_2': check_list = [data for data in message.get_data()] assert isinstance(message._body, DataBody) assert check_list == [data_body_2] result_dic['data_body_2'] = 1 elif message.application_properties.get(b'body_type') == b'value_body_1': assert message.get_data() == value_body_1 assert isinstance(message._body, ValueBody) result_dic['value_body_1'] = 1 elif message.application_properties.get(b'body_type') == b'value_body_2': assert message.get_data() == value_body_2 assert isinstance(message._body, ValueBody) result_dic['value_body_2'] = 1 elif message.application_properties.get(b'body_type') == b'sequence_body_1': check_list = [data for data in message.get_data()] assert check_list == [sequence_body_1] assert isinstance(message._body, SequenceBody) result_dic['sequence_body_1'] = 1 elif message.application_properties.get(b'body_type') == b'sequence_body_2': check_list = [data for data in message.get_data()] assert check_list == sequence_body_2 assert isinstance(message._body, SequenceBody) result_dic['sequence_body_2'] = 1 log.info(message.annotations.get(b'x-opt-sequence-number')) log.info(str(message)) send_client.close() receive_client.close() assert len(result_dic) == 6
def test_event_hubs_send_event_with_amqp_attributes_sync(live_eventhub_config): def data_generator(): for i in range(2): msg = uamqp.message.Message(body='Data') # header is only used on received msg, not set on messages being sent msg.application_properties = {'msg_type': 'rich_batch'} msg.properties = uamqp.message.MessageProperties(message_id='richid', user_id=b'!@qwe\0?123') msg.footer = {'footerkey':'footervalue'} msg.delivery_annotations = {'deliveryannkey':'deliveryannvalue'} msg.annotations = {'annkey':'annvalue'} yield msg uri = "sb://{}/{}".format(live_eventhub_config['hostname'], live_eventhub_config['event_hub']) sas_auth = authentication.SASTokenAuth.from_shared_access_key( uri, live_eventhub_config['key_name'], live_eventhub_config['access_key']) target = "amqps://{}/{}/Partitions/0".format(live_eventhub_config['hostname'], live_eventhub_config['event_hub']) send_client = uamqp.SendClient(target, auth=sas_auth, debug=False) message = uamqp.message.Message(body='Data') # header is only used on received msg, not set on messages being sent message.application_properties = {'msg_type': 'rich_single'} message.properties = uamqp.message.MessageProperties(message_id='richid') message.footer = {'footerkey':'footervalue'} message.delivery_annotations = {'deliveryannkey':'deliveryannvalue'} message.annotations = {'annkey':'annvalue'} send_client.queue_message(message) message_batch = uamqp.message.BatchMessage(data_generator()) send_client.queue_message(message_batch) results = send_client.send_all_messages(close_on_done=False) assert not [m for m in results if m == uamqp.constants.MessageState.SendFailed] rich_single_received = rich_batch_received = False uri = "sb://{}/{}".format(live_eventhub_config['hostname'], live_eventhub_config['event_hub']) sas_auth = authentication.SASTokenAuth.from_shared_access_key( uri, live_eventhub_config['key_name'], live_eventhub_config['access_key']) source = "amqps://{}/{}/ConsumerGroups/{}/Partitions/{}".format( live_eventhub_config['hostname'], live_eventhub_config['event_hub'], live_eventhub_config['consumer_group'], 0) receive_client = uamqp.ReceiveClient(source, auth=sas_auth, timeout=5000, debug=False, prefetch=10) gen = receive_client.receive_messages_iter() for message in gen: if message.application_properties and message.application_properties.get(b'msg_type'): if not rich_single_received: rich_single_received = message.application_properties.get(b'msg_type') == b'rich_single' if not rich_batch_received: rich_batch_received = message.application_properties.get(b'msg_type') == b'rich_batch' if message.application_properties.get(b'msg_type') == b'rich_single': assert message.properties.user_id is None elif message.application_properties.get(b'msg_type') == b'rich_batch': assert message.properties.user_id == b'!@qwe\0?123' assert message.properties.message_id == b'richid' assert message.delivery_annotations assert message.delivery_annotations.get(b'deliveryannkey') == b'deliveryannvalue' assert message.footer assert message.footer.get(b'footerkey') == b'footervalue' assert message.annotations assert message.annotations.get(b'annkey') == b'annvalue' log.info(message.annotations.get(b'x-opt-sequence-number')) log.info(str(message)) send_client.close() receive_client.close() assert rich_single_received assert rich_batch_received
from urllib.parse import quote_plus import perftest with open(os.path.abspath(os.path.join(os.path.dirname(__file__), '../config.json') ), 'r') as read_file: config = json.load(read_file) TOPIC_NAME = config['topic_name'] SERVICE_NAMESPACE = config['service_namespace'] KEY_NAME = config['key_name'] KEY_VALUE = config['key_value'] HOSTNAME = '{}.servicebus.windows.net'.format(SERVICE_NAMESPACE) CONN_STR = 'amqps://{}:{}@{}.servicebus.windows.net/{}'.format( KEY_NAME, quote_plus(KEY_VALUE, safe=''), SERVICE_NAMESPACE, TOPIC_NAME) sas_auth = authentication.SASTokenAuth.from_shared_access_key( CONN_STR, KEY_NAME, KEY_VALUE) target = "amqps://{}/{}".format(HOSTNAME, TOPIC_NAME) send_client = uamqp.SendClient(target, auth=sas_auth, debug=False) producer = perftest.PerfProducer(send_client, use_batch=True) producer.start() for i in range(1, 30): time.sleep(1) print("producer sent ", producer.rate.print_rate()) producer.stop()
def send_c2d_message( target, device_id, data, message_id=None, correlation_id=None, ack=None, content_type=None, user_id=None, content_encoding="utf-8", expiry_time_utc=None, properties=None, ): app_props = {} if properties: app_props.update(properties) app_props["iothub-ack"] = ack if ack else "none" msg_props = uamqp.message.MessageProperties() msg_props.to = "/devices/{}/messages/devicebound".format(device_id) target_msg_id = message_id if message_id else str(uuid4()) msg_props.message_id = target_msg_id if correlation_id: msg_props.correlation_id = correlation_id if user_id: msg_props.user_id = user_id if content_type: msg_props.content_type = content_type # Ensures valid json when content_type is application/json content_type = content_type.lower() if content_type == "application/json": data = json.dumps(process_json_arg(data, "data")) if content_encoding: msg_props.content_encoding = content_encoding if expiry_time_utc: msg_props.absolute_expiry_time = int(expiry_time_utc) msg_body = str.encode(data) message = uamqp.Message(body=msg_body, properties=msg_props, application_properties=app_props) operation = "/messages/devicebound" endpoint = AmqpBuilder.build_iothub_amqp_endpoint_from_target(target) endpoint_with_op = endpoint + operation client = uamqp.SendClient( target="amqps://" + endpoint_with_op, client_name=_get_container_id(), debug=DEBUG, ) client.queue_message(message) result = client.send_all_messages() errors = [ m for m in result if m == uamqp.constants.MessageState.SendFailed ] return target_msg_id, errors