예제 #1
0
    def test_message_status(self):
        msgid = 'msgid'
        system_id = 'username'
        source_addr = '999'
        destination_addr = '111'
        sub_date = datetime.now()
        source_addr_ton = AddrTon.NATIONAL
        source_addr_npi = AddrNpi.ISDN
        dest_addr_ton = AddrTon.NATIONAL
        dest_addr_npi = AddrNpi.ISDN

        validStatuses = [
            'ESME_ROK', 'DELIVRD', 'EXPIRED', 'DELETED', 'UNDELIV', 'ACCEPTD',
            'UNKNOWN', 'REJECTD', 'ESME_ANYTHING'
        ]

        for status in validStatuses:
            c = DLRContentForSmpps(status, msgid, system_id, source_addr,
                                   destination_addr, sub_date, source_addr_ton,
                                   source_addr_npi, dest_addr_ton,
                                   dest_addr_npi)

            self.assertEqual(c['headers']['message_status'], status)

        self.assertRaises(InvalidParameterError, DLRContentForSmpps,
                          'anystatus', msgid, system_id, source_addr,
                          destination_addr, sub_date, source_addr_ton,
                          source_addr_npi, dest_addr_ton, dest_addr_npi)
예제 #2
0
    def test_normal_without_err(self):
        message_status = 'DELIVRD'
        msgid = 'msgid'
        system_id = 'username'
        source_addr = '999'
        destination_addr = '111'
        sub_date = datetime.now()
        source_addr_ton = AddrTon.NATIONAL
        source_addr_npi = AddrNpi.ISDN
        dest_addr_ton = AddrTon.NATIONAL
        dest_addr_npi = AddrNpi.ISDN

        c = DLRContentForSmpps(message_status, msgid, system_id, source_addr,
                               destination_addr, sub_date, source_addr_ton,
                               source_addr_npi, dest_addr_ton, dest_addr_npi)

        self.assertEqual(c.body, msgid)
        self.assertEqual(len(c['headers']), 11)
        self.assertEqual(c['headers']['try-count'], 0)
        self.assertEqual(c['headers']['message_status'], message_status)
        self.assertEqual(c['headers']['system_id'], system_id)
        self.assertEqual(c['headers']['source_addr'], source_addr)
        self.assertEqual(c['headers']['destination_addr'], destination_addr)
        self.assertEqual(c['headers']['sub_date'], str(sub_date))
        self.assertEqual(c['headers']['source_addr_ton'],
                         str(AddrTon.NATIONAL))
        self.assertEqual(c['headers']['source_addr_npi'], str(AddrNpi.ISDN))
        self.assertEqual(c['headers']['dest_addr_ton'], str(AddrTon.NATIONAL))
        self.assertEqual(c['headers']['dest_addr_npi'], str(AddrNpi.ISDN))
        # Default value of err is 99
        self.assertEqual(c['headers']['err'], 99)
예제 #3
0
    def test_normal_with_err(self):
        message_status = 'DELIVRD'
        msgid = 'msgid'
        system_id = 'username'
        source_addr = '999'
        destination_addr = '111'
        sub_date = datetime.now()
        source_addr_ton = AddrTon.NATIONAL
        source_addr_npi = AddrNpi.ISDN
        dest_addr_ton = AddrTon.NATIONAL
        dest_addr_npi = AddrNpi.ISDN
        err = 56

        c = DLRContentForSmpps(message_status,
                               msgid,
                               system_id,
                               source_addr,
                               destination_addr,
                               sub_date,
                               source_addr_ton,
                               source_addr_npi,
                               dest_addr_ton,
                               dest_addr_npi,
                               err=err)

        self.assertEqual(len(c['headers']), 11)
        self.assertEqual(c['headers']['err'], err)
예제 #4
0
    def publishDLRContentForSmppapi(self, message_status, msgid, system_id, source_addr, destination_addr,
                                    sub_date=None,
                                    source_addr_ton='UNKNOWN', source_addr_npi='UNKNOWN',
                                    dest_addr_ton='UNKNOWN', dest_addr_npi='UNKNOWN'):
        if sub_date is None:
            sub_date = datetime.datetime.now()

        content = DLRContentForSmpps(message_status, msgid, system_id, source_addr, destination_addr, sub_date,
                                     source_addr_ton, source_addr_npi, dest_addr_ton, dest_addr_npi)
        yield self.amqpBroker.publish(exchange='messaging', routing_key='dlr_thrower.smpps', content=content)
예제 #5
0
    def test_normal(self):
        message_status = 'DELIVRD'
        msgid = 'msgid'
        system_id = 'username'
        source_addr = '999'
        destination_addr = '111'

        c = DLRContentForSmpps(message_status, msgid, system_id, source_addr,
                               destination_addr)

        self.assertEquals(c.body, msgid)
        self.assertEquals(len(c['headers']), 5)
        self.assertEquals(c['headers']['try-count'], 0)
        self.assertEquals(c['headers']['message_status'], message_status)
        self.assertEquals(c['headers']['system_id'], system_id)
        self.assertEquals(c['headers']['source_addr'], source_addr)
        self.assertEquals(c['headers']['destination_addr'], destination_addr)
예제 #6
0
    def test_message_status(self):
        msgid = 'msgid'
        system_id = 'username'
        source_addr = '999'
        destination_addr = '111'

        validStatuses = [
            'ESME_ROK', 'DELIVRD', 'EXPIRED', 'DELETED', 'UNDELIV', 'ACCEPTD',
            'UNKNOWN', 'REJECTD', 'ESME_ANYTHING'
        ]

        for status in validStatuses:
            c = DLRContentForSmpps(status, msgid, system_id, source_addr,
                                   destination_addr)

            self.assertEquals(c['headers']['message_status'], status)

        self.assertRaises(InvalidParameterError, DLRContentForSmpps,
                          'anystatus', msgid, system_id, source_addr,
                          destination_addr)
예제 #7
0
파일: dlr.py 프로젝트: youyi1314/jasmin
    def deliver_sm_dlr_callback(self, message):
        msgid = message.content.properties['message-id']
        pdu_cid = message.content.properties['headers']['cid']
        pdu_dlr_id = message.content.properties['headers']['dlr_id']
        pdu_dlr_ddate = message.content.properties['headers']['dlr_ddate']
        pdu_dlr_sdate = message.content.properties['headers']['dlr_sdate']
        pdu_dlr_sub = message.content.properties['headers']['dlr_sub']
        pdu_dlr_err = message.content.properties['headers']['dlr_err']
        pdu_dlr_text = message.content.properties['headers']['dlr_text']
        pdu_dlr_dlvrd = message.content.properties['headers']['dlr_dlvrd']
        pdu_dlr_status = message.content.body

        try:
            if self.redisClient is None:
                raise RedisError('RC undefined !')
            if self.redisClient.connected != 1:
                raise RedisError('RC is offline !')

            q = yield self.redisClient.hgetall("queue-msgid:%s" % msgid)
            if len(q) != 2 or 'msgid' not in q or 'connector_type' not in q:
                raise DLRMapNotFound(
                    'Got a DLR for an unknown message id: %s (coded:%s)' %
                    (pdu_dlr_id, msgid))

            submit_sm_queue_id = q['msgid']
            connector_type = q['connector_type']

            # Get dlr and ensure it's sc (source_connector) is same as q['connector_type']
            dlr = yield self.redisClient.hgetall("dlr:%s" % submit_sm_queue_id)
            if dlr is None or len(dlr) == 0:
                raise DLRMapNotFound(
                    'Got a DLR for an unknown message id: %s (coded:%s)' %
                    (pdu_dlr_id, msgid))
            if len(dlr) > 0 and dlr['sc'] != connector_type:
                raise DLRMapError(
                    'Found a dlr for msgid:%s with diffrent sc: %s' %
                    (submit_sm_queue_id, dlr['sc']))

            if connector_type == 'httpapi':
                self.log.debug('There is a HTTP DLR request for msgid[%s] ...',
                               msgid)
                dlr_url = dlr['url']
                dlr_level = dlr['level']
                dlr_method = dlr['method']

                if dlr_level in [2, 3]:
                    self.log.debug(
                        'Got DLR information for msgid[%s], url:%s, level:%s',
                        submit_sm_queue_id, dlr_url, dlr_level)
                    # The dlr_url in DLRContentForHttpapi indicates the level
                    # of the actual delivery receipt (2) and not the
                    # requested one (maybe 2 or 3)
                    self.log.debug(
                        "Publishing DLRContentForHttpapi[%s] with routing_key[%s]",
                        submit_sm_queue_id, 'dlr_thrower.http')
                    yield self.amqpBroker.publish(
                        exchange='messaging',
                        routing_key='dlr_thrower.http',
                        content=DLRContentForHttpapi(pdu_dlr_status,
                                                     submit_sm_queue_id,
                                                     dlr_url,
                                                     dlr_level=2,
                                                     id_smsc=msgid,
                                                     sub=pdu_dlr_sub,
                                                     dlvrd=pdu_dlr_dlvrd,
                                                     subdate=pdu_dlr_sdate,
                                                     donedate=pdu_dlr_ddate,
                                                     err=pdu_dlr_err,
                                                     text=pdu_dlr_text,
                                                     method=dlr_method))

                    self.log.debug('Removing HTTP dlr map for msgid[%s]',
                                   submit_sm_queue_id)
                    yield self.redisClient.delete('dlr:%s' %
                                                  submit_sm_queue_id)
            elif connector_type == 'smppsapi':
                self.log.debug('There is a SMPPs mapping for msgid[%s] ...',
                               msgid)
                system_id = dlr['system_id']
                source_addr_ton = dlr['source_addr_ton']
                source_addr_npi = dlr['source_addr_npi']
                source_addr = str(dlr['source_addr'])
                dest_addr_ton = dlr['dest_addr_ton']
                dest_addr_npi = dlr['dest_addr_npi']
                destination_addr = str(dlr['destination_addr'])
                sub_date = dlr['sub_date']
                registered_delivery_receipt = dlr['rd_receipt']

                success_states = ['ACCEPTD', 'DELIVRD']
                final_states = [
                    'DELIVRD', 'EXPIRED', 'DELETED', 'UNDELIV', 'REJECTD'
                ]
                # Do we need to forward the receipt to the original sender ?
                if ((pdu_dlr_status in success_states
                     and registered_delivery_receipt
                     == 'SMSC_DELIVERY_RECEIPT_REQUESTED')
                        or (pdu_dlr_status not in success_states
                            and registered_delivery_receipt in [
                                'SMSC_DELIVERY_RECEIPT_REQUESTED',
                                'SMSC_DELIVERY_RECEIPT_REQUESTED_FOR_FAILURE'
                            ])):
                    self.log.debug(
                        'Got DLR information for msgid[%s], registered_deliver%s, system_id:%s',
                        submit_sm_queue_id, registered_delivery_receipt,
                        system_id)

                    self.log.debug(
                        "Publishing DLRContentForSmpps[%s] with routing_key[%s]",
                        submit_sm_queue_id, 'dlr_thrower.smpps')
                    yield self.amqpBroker.publish(
                        exchange='messaging',
                        routing_key='dlr_thrower.smpps',
                        content=DLRContentForSmpps(
                            pdu_dlr_status, submit_sm_queue_id, system_id,
                            source_addr, destination_addr, sub_date,
                            source_addr_ton, source_addr_npi, dest_addr_ton,
                            dest_addr_npi))

                    if pdu_dlr_status in final_states:
                        self.log.debug('Removing SMPPs dlr map for msgid[%s]',
                                       submit_sm_queue_id)
                        yield self.redisClient.delete('dlr:%s' %
                                                      submit_sm_queue_id)
        except DLRMapError as e:
            self.log.error('[msgid:%s] DLRMapError: %s', msgid, e)
            yield self.rejectMessage(message)
        except RedisError as e:
            if msgid in self.lookup_retrials and self.lookup_retrials[
                    msgid] < self.config.dlr_lookup_max_retries:
                self.log.error('[msgid:%s] (retrials: %s/%s) RedisError: %s',
                               msgid, self.lookup_retrials[msgid],
                               self.config.dlr_lookup_max_retries, e)
                yield self.rejectAndRequeueMessage(message)
            else:
                self.log.error('[msgid:%s] (final) RedisError: %s', msgid, e)
                yield self.rejectMessage(message)
        except DLRMapNotFound as e:
            if msgid in self.lookup_retrials and self.lookup_retrials[
                    msgid] < self.config.dlr_lookup_max_retries:
                self.log.error(
                    '[msgid:%s] (retrials: %s/%s) DLRMapNotFound: %s', msgid,
                    self.lookup_retrials[msgid],
                    self.config.dlr_lookup_max_retries, e)
                yield self.rejectAndRequeueMessage(message)
            else:
                self.log.error('[msgid:%s] (final) DLRMapNotFound: %s', msgid,
                               e)
                yield self.rejectMessage(message)
        except Exception as e:
            self.log.error('[msgid:%s] Unknown error (%s): %s', msgid, type(e),
                           e)
            yield self.rejectMessage(message)
        else:
            yield self.ackMessage(message)

            self.log.info(
                "DLR [cid:%s] [smpp-msgid:%s] [status:%s] [submit date:%s] [done date:%s] [sub/dlvrd messages:%s/%s] \
[err:%s] [content:%r]", pdu_cid, msgid, pdu_dlr_text, pdu_dlr_sdate,
                pdu_dlr_ddate, pdu_dlr_sub, pdu_dlr_dlvrd, pdu_dlr_err,
                pdu_dlr_text)
예제 #8
0
파일: dlr.py 프로젝트: youyi1314/jasmin
    def submit_sm_resp_dlr_callback(self, message):
        msgid = message.content.properties['message-id']
        dlr_status = message.content.body

        try:
            if self.redisClient is None:
                raise RedisError('RC undefined !')
            if self.redisClient.connected != 1:
                raise RedisError('RC is offline !')

            # Check for DLR request from redis 'dlr' key
            # If there's a pending delivery receipt request then serve it
            # back by publishing a DLRContentForHttpapi to the messaging exchange
            dlr = yield self.redisClient.hgetall("dlr:%s" % msgid)

            if dlr is None or len(dlr) == 0:
                raise DLRMapNotFound('No dlr map for msgid[%s]' % msgid)
            if 'sc' not in dlr or dlr['sc'] not in ['httpapi', 'smppsapi']:
                raise DLRMapError('Fetched unknown dlr: %s' % dlr)

            if dlr['sc'] == 'httpapi':
                self.log.debug('There is a HTTP DLR request for msgid[%s] ...',
                               msgid)
                dlr_url = dlr['url']
                dlr_level = dlr['level']
                dlr_method = dlr['method']
                dlr_expiry = dlr['expiry']

                if dlr['level'] in [1, 3]:
                    self.log.debug(
                        'Got DLR information for msgid[%s], url:%s, level:%s',
                        msgid, dlr_url, dlr_level)

                    # The dlr_url in DLRContentForHttpapi indicates the level
                    # of the actual delivery receipt (1) and not the requested
                    # one (maybe 1 or 3)
                    self.log.debug(
                        "Publishing DLRContentForHttpapi[%s] with routing_key[%s]",
                        msgid, 'dlr_thrower.http')
                    yield self.amqpBroker.publish(
                        exchange='messaging',
                        routing_key='dlr_thrower.http',
                        content=DLRContentForHttpapi(dlr_status,
                                                     msgid,
                                                     dlr_url,
                                                     dlr_level=1,
                                                     method=dlr_method))

                    # DLR request is removed if:
                    # - If level 1 is requested (SMSC level only)
                    # - SubmitSmResp returned an error (no more delivery will be tracked)
                    #
                    # When level 3 is requested, the DLR will be removed when
                    # receiving a deliver_sm (terminal receipt)
                    if dlr_level == 1 or dlr_status != 'ESME_ROK':
                        self.log.debug('Removing DLR request for msgid[%s]',
                                       msgid)
                        yield self.redisClient.delete("dlr:%s" % msgid)
                else:
                    self.log.debug(
                        'Terminal level receipt is requested, will not send any DLR receipt at this level.'
                    )

                if dlr_level in [2, 3] and dlr_status == 'ESME_ROK':
                    smpp_msgid = message.content.properties['headers'][
                        'smpp_msgid']
                    # Map received submit_sm_resp's message_id to the msg for later receipt handling
                    self.log.debug(
                        'Mapping smpp msgid: %s to queue msgid: %s, expiring in %s',
                        smpp_msgid, msgid, dlr_expiry)
                    hashKey = "queue-msgid:%s" % smpp_msgid
                    hashValues = {'msgid': msgid, 'connector_type': 'httpapi'}
                    yield self.redisClient.hmset(hashKey, hashValues)
                    yield self.redisClient.expire(hashKey, dlr_expiry)
            elif dlr['sc'] == 'smppsapi':
                self.log.debug('There is a SMPPs mapping for msgid[%s] ...',
                               msgid)
                system_id = dlr['system_id']
                source_addr_ton = dlr['source_addr_ton']
                source_addr_npi = dlr['source_addr_npi']
                source_addr = str(dlr['source_addr'])
                dest_addr_ton = dlr['dest_addr_ton']
                dest_addr_npi = dlr['dest_addr_npi']
                destination_addr = str(dlr['destination_addr'])
                sub_date = dlr['sub_date']
                registered_delivery_receipt = dlr['rd_receipt']
                smpps_map_expiry = dlr['expiry']

                # Do we need to forward the receipt to the original sender ?
                if ((dlr_status == 'ESME_ROK'
                     and registered_delivery_receipt in [
                         'SMSC_DELIVERY_RECEIPT_REQUESTED_FOR_FAILURE',
                         'SMSC_DELIVERY_RECEIPT_REQUESTED'
                     ]) or
                    (dlr_status != 'ESME_ROK' and registered_delivery_receipt
                     == 'SMSC_DELIVERY_RECEIPT_REQUESTED_FOR_FAILURE')):
                    self.log.debug(
                        'Got DLR information for msgid[%s], registered_deliver%s, system_id:%s',
                        msgid, registered_delivery_receipt, system_id)

                    if (dlr_status != 'ESME_ROK' or
                        (dlr_status == 'ESME_ROK' and
                         self.config.smpp_receipt_on_success_submit_sm_resp)):
                        # Send back a receipt (by throwing deliver_sm or data_sm)
                        self.log.debug(
                            "Publishing DLRContentForSmpps[%s] with routing_key[%s]",
                            msgid, 'dlr_thrower.smpps')
                        yield self.amqpBroker.publish(
                            exchange='messaging',
                            routing_key='dlr_thrower.smpps',
                            content=DLRContentForSmpps(
                                dlr_status, msgid, system_id, source_addr,
                                destination_addr, sub_date, source_addr_ton,
                                source_addr_npi, dest_addr_ton, dest_addr_npi))

                    if dlr_status == 'ESME_ROK':
                        smpp_msgid = message.content.properties['headers'][
                            'smpp_msgid']
                        # Map received submit_sm_resp's message_id to the msg for later rceipt handling
                        self.log.debug(
                            'Mapping smpp msgid: %s to queue msgid: %s, expiring in %s',
                            smpp_msgid, msgid, smpps_map_expiry)
                        hashKey = "queue-msgid:%s" % smpp_msgid
                        hashValues = {
                            'msgid': msgid,
                            'connector_type': 'smppsapi'
                        }
                        yield self.redisClient.hmset(hashKey, hashValues)
                        yield self.redisClient.expire(hashKey,
                                                      smpps_map_expiry)
        except DLRMapError as e:
            self.log.error('[msgid:%s] DLR Content: %s', msgid, e)
            yield self.rejectMessage(message)
        except RedisError as e:
            if msgid in self.lookup_retrials and self.lookup_retrials[
                    msgid] < self.config.dlr_lookup_max_retries:
                self.log.error('[msgid:%s] (retrials: %s/%s) RedisError: %s',
                               msgid, self.lookup_retrials[msgid],
                               self.config.dlr_lookup_max_retries, e)
                yield self.rejectAndRequeueMessage(message)
            else:
                self.log.error('[msgid:%s] (final) RedisError: %s', msgid, e)
                yield self.rejectMessage(message)
        except DLRMapNotFound as e:
            self.log.debug('[msgid:%s] DLRMapNotFound: %s', msgid, e)
            yield self.rejectMessage(message)
        except Exception as e:
            self.log.error('[msgid:%s] Unknown error (%s): %s', msgid, type(e),
                           e)
            yield self.rejectMessage(message)
        else:
            yield self.ackMessage(message)
예제 #9
0
    def deliver_sm_event_post_interception(self, *args, **kw):
        """This event is called whenever a deliver_sm pdu is received through a SMPPc
        It will hand the pdu to the router or a dlr thrower (depending if its a DLR or not).

        Note: this event will catch data_sm pdus as well
        """

        try:
            # Control args
            if 'smpp' not in kw or 'pdu' not in kw:
                self.log.error(
                    'deliver_sm_event_post_interception missing arguments after interception: %s', kw)
                raise InterceptorRunError(
                    'deliver_sm_event_post_interception missing arguments after interception')

            # Set defaults
            smpp = kw['smpp']
            pdu = kw['pdu']
            if 'concatenated' in kw:
                concatenated = kw['concatenated']
            else:
                concatenated = False

            # Get message_content
            if 'short_message' in pdu.params:
                message_content = pdu.params['short_message']
            elif 'message_payload' in pdu.params:
                message_content = pdu.params['message_payload']
            else:
                message_content = None

            # Post interception:
            if len(args) == 1:
                if isinstance(args[0], bool) and not args[0]:
                    smpp.factory.stats.inc('interceptor_error_count')
                    self.log.error('Failed running interception script, got a False return.')
                    raise InterceptorRunError('Failed running interception script, check log for details')
                elif isinstance(args[0], dict) and args[0]['smpp_status'] > 0:
                    smpp.factory.stats.inc('interceptor_error_count')
                    self.log.info(
                        'Interceptor script returned %s smpp_status error.', args[0]['smpp_status'])
                    raise DeliverSmInterceptionError(code=args[0]['smpp_status'])
                elif isinstance(args[0], str):
                    smpp.factory.stats.inc('interceptor_count')
                    temp_routable = pickle.loads(args[0])
                    pdu = temp_routable.pdu
                else:
                    smpp.factory.stats.inc('interceptor_error_count')
                    self.log.error(
                        'Failed running interception script, got the following return: %s', args[0])
                    raise InterceptorRunError(
                        'Failed running interception script, got the following return: %s', args[0])

            self.log.debug('Handling deliver_sm_event_post_interception event for smppc: %s',
                           self.SMPPClientFactory.config.id)

            pdu.dlr = self.SMPPOperationFactory.isDeliveryReceipt(pdu)
            content = DeliverSmContent(pdu,
                                       self.SMPPClientFactory.config.id,
                                       pickleProtocol=self.pickleProtocol,
                                       concatenated=concatenated)
            msgid = content.properties['message-id']

            if pdu.dlr is None:
                # We have a SMS-MO

                # UDH is set ?
                UDHI_INDICATOR_SET = False
                if 'esm_class' in pdu.params and hasattr(pdu.params['esm_class'], 'gsmFeatures'):
                    for gsmFeature in pdu.params['esm_class'].gsmFeatures:
                        if str(gsmFeature) == 'UDHI_INDICATOR_SET':
                            UDHI_INDICATOR_SET = True
                            break

                splitMethod = None
                # Is it a part of a long message ?
                if 'sar_msg_ref_num' in pdu.params:
                    splitMethod = 'sar'
                    total_segments = pdu.params['sar_total_segments']
                    segment_seqnum = pdu.params['sar_segment_seqnum']
                    msg_ref_num = pdu.params['sar_msg_ref_num']
                    self.log.debug('Received a part of SMS-MO [queue-msgid:%s] using SAR options: total_segments=%s, segmen_seqnum=%s, msg_ref_num=%s',
                                   msgid, total_segments, segment_seqnum, msg_ref_num)
                elif UDHI_INDICATOR_SET and message_content[:3] == '\x05\x00\x03':
                    splitMethod = 'udh'
                    total_segments = struct.unpack('!B', message_content[4])[0]
                    segment_seqnum = struct.unpack('!B', message_content[5])[0]
                    msg_ref_num = struct.unpack('!B', message_content[3])[0]
                    self.log.debug('Received a part of SMS-MO [queue-msgid:%s] using UDH options: total_segments=%s, segmen_seqnum=%s, msg_ref_num=%s',
                                   msgid, total_segments, segment_seqnum, msg_ref_num)

                if splitMethod is None:
                    # It's a simple short message or a part of a concatenated message
                    routing_key = 'deliver.sm.%s' % self.SMPPClientFactory.config.id
                    self.log.debug("Publishing DeliverSmContent[%s] with routing_key[%s]", msgid, routing_key)
                    yield self.amqpBroker.publish(exchange='messaging', routing_key=routing_key, content=content)

                    # Get values from data_sm or deliver_sm
                    priority_flag = None
                    if 'priority_flag' in pdu.params:
                        priority_flag = pdu.params['priority_flag']
                    validity_period = None
                    if 'validity_period' in pdu.params:
                        validity_period = pdu.params['validity_period']

                    self.log.info("SMS-MO [cid:%s] [queue-msgid:%s] [status:%s] [prio:%s] [validity:%s] [from:%s] [to:%s] [content:%s]",
                                  self.SMPPClientFactory.config.id,
                                  msgid,
                                  pdu.status,
                                  priority_flag,
                                  validity_period,
                                  pdu.params['source_addr'],
                                  pdu.params['destination_addr'],
                                  re.sub(r'[^\x20-\x7E]+', '.', message_content))
                else:
                    # Long message part received
                    if self.redisClient is None:
                        self.warn('No valid RC were found while receiving a part of a long DeliverSm [queue-msgid:%s], MESSAGE IS LOST !',
                                  msgid)

                    # Save it to redis
                    hashKey = "longDeliverSm:%s" % (msg_ref_num)
                    hashValues = {'pdu': pdu,
                                  'total_segments':total_segments,
                                  'msg_ref_num':msg_ref_num,
                                  'segment_seqnum':segment_seqnum}
                    yield self.redisClient.hset(
                        hashKey, segment_seqnum, pickle.dumps(hashValues, self.pickleProtocol)).addCallback(
                            self.concatDeliverSMs,
                            splitMethod,
                            total_segments,
                            msg_ref_num,
                            segment_seqnum)

                    self.log.info("DeliverSmContent[%s] is a part of a long message of %s parts, will be sent to queue after concatenation.",
                                  msgid, total_segments)

                    # Flag it as "will_be_concatenated" and publish it to router
                    routing_key = 'deliver.sm.%s' % self.SMPPClientFactory.config.id
                    self.log.debug("Publishing DeliverSmContent[%s](flagged:wbc) with routing_key[%s]",
                                   msgid, routing_key)
                    content.properties['headers']['will_be_concatenated'] = True
                    yield self.amqpBroker.publish(exchange='messaging', routing_key=routing_key, content=content)
            else:
                # This is a DLR !
                # Check for DLR request
                if self.redisClient is not None:
                    _coded_dlr_id = self.code_dlr_msgid(pdu)

                    q = yield self.redisClient.get("queue-msgid:%s" % _coded_dlr_id)
                    submit_sm_queue_id = None
                    connector_type = None
                    if q is not None:
                        q = pickle.loads(q)
                        submit_sm_queue_id = q['msgid']
                        connector_type = q['connector_type']


                    if submit_sm_queue_id is not None and connector_type == 'httpapi':
                        pickledDlr = yield self.redisClient.get("dlr:%s" % submit_sm_queue_id)

                        if pickledDlr is not None:
                            dlr = pickle.loads(pickledDlr)
                            dlr_url = dlr['url']
                            dlr_level = dlr['level']
                            dlr_method = dlr['method']

                            if dlr_level in [2, 3]:
                                self.log.debug('Got DLR information for msgid[%s], url:%s, level:%s',
                                               submit_sm_queue_id, dlr_url, dlr_level)
                                # The dlr_url in DLRContentForHttpapi indicates the level
                                # of the actual delivery receipt (2) and not the
                                # requested one (maybe 2 or 3)
                                content = DLRContentForHttpapi(pdu.dlr['stat'], submit_sm_queue_id,
                                                               dlr_url, dlr_level=2, id_smsc=_coded_dlr_id,
                                                               sub=pdu.dlr['sub'], dlvrd=pdu.dlr['dlvrd'],
                                                               subdate=pdu.dlr['sdate'],
                                                               donedate=pdu.dlr['ddate'], err=pdu.dlr['err'],
                                                               text=pdu.dlr['text'], method=dlr_method)
                                routing_key = 'dlr_thrower.http'
                                self.log.debug("Publishing DLRContentForHttpapi[%s] with routing_key[%s]",
                                               submit_sm_queue_id, routing_key)
                                yield self.amqpBroker.publish(exchange='messaging',
                                                              routing_key=routing_key,
                                                              content=content)

                                self.log.debug('Removing DLR request for msgid[%s]', submit_sm_queue_id)
                                yield self.redisClient.delete('dlr:%s' % submit_sm_queue_id)
                            else:
                                self.log.debug('SMS-C receipt is requested, will not send any DLR receipt at this level.')
                        else:
                            self.log.warn('DLR for msgid[%s] not found !',
                                          submit_sm_queue_id)
                    elif submit_sm_queue_id is not None and connector_type == 'smpps':
                        pickledSmppsMap = yield self.redisClient.get("smppsmap:%s" % submit_sm_queue_id)

                        if pickledSmppsMap is not None:
                            smpps_map = pickle.loads(pickledSmppsMap)
                            system_id = smpps_map['system_id']
                            source_addr = smpps_map['source_addr']
                            destination_addr = smpps_map['destination_addr']
                            sub_date = smpps_map['sub_date']
                            registered_delivery = smpps_map['registered_delivery']

                            success_states = ['ACCEPTD', 'DELIVRD']
                            final_states = ['DELIVRD', 'EXPIRED', 'DELETED', 'UNDELIV', 'REJECTD']
                            # Do we need to forward the receipt to the original sender ?
                            if ((pdu.dlr['stat'] in success_states and
                                    str(registered_delivery.receipt) == 'SMSC_DELIVERY_RECEIPT_REQUESTED') or
                                    (pdu.dlr['stat'] not in success_states and
                                    str(registered_delivery.receipt) in ['SMSC_DELIVERY_RECEIPT_REQUESTED',
                                                                         'SMSC_DELIVERY_RECEIPT_REQUESTED_FOR_FAILURE'])):
                                self.log.debug(
                                    'Got DLR information for msgid[%s], registered_deliver%s, system_id:%s',
                                    submit_sm_queue_id, registered_delivery, system_id)

                                content = DLRContentForSmpps(pdu.dlr['stat'], submit_sm_queue_id, system_id,
                                                             source_addr, destination_addr, sub_date)

                                routing_key = 'dlr_thrower.smpps'
                                self.log.debug("Publishing DLRContentForSmpps[%s] with routing_key[%s]",
                                               submit_sm_queue_id, routing_key)
                                yield self.amqpBroker.publish(exchange='messaging',
                                                              routing_key=routing_key,
                                                              content=content)

                                if pdu.dlr['stat'] in final_states:
                                    self.log.debug('Removing SMPPs map for msgid[%s]', submit_sm_queue_id)
                                    yield self.redisClient.delete('smppsmap:%s' % submit_sm_queue_id)
                    else:
                        self.log.warn('Got a DLR for an unknown message id: %s (coded:%s)',
                                      pdu.dlr['id'], _coded_dlr_id)
                else:
                    self.log.warn('DLR for msgid[%s] is not checked, no valid RC were found', msgid)

                self.log.info("DLR [cid:%s] [smpp-msgid:%s] [status:%s] [submit date:%s] [done date:%s] [sub/dlvrd messages:%s/%s] [err:%s] [content:%s]",
                              self.SMPPClientFactory.config.id,
                              _coded_dlr_id,
                              pdu.dlr['stat'],
                              pdu.dlr['sdate'],
                              pdu.dlr['ddate'],
                              pdu.dlr['sub'],
                              pdu.dlr['dlvrd'],
                              pdu.dlr['err'],
                              pdu.dlr['text'])
        except (InterceptorRunError, DeliverSmInterceptionError) as e:
            self.log.info("SMS-MO [cid:%s] [istatus:%s] [from:%s] [to:%s] [content:%s]",
                          self.SMPPClientFactory.config.id,
                          e.status,
                          pdu.params['source_addr'],
                          pdu.params['destination_addr'],
                          re.sub(r'[^\x20-\x7E]+', '.', message_content))

            # Known exception handling
            defer.returnValue(DataHandlerResponse(status=e.status))
        except Exception, e:
            # Unknown exception handling
            self.log.critical('Got an unknown exception: %s', e)
            defer.returnValue(DataHandlerResponse(status=CommandStatus.ESME_RUNKNOWNERR))
예제 #10
0
    def submit_sm_resp_event(self, r, amqpMessage):
        msgid = amqpMessage.content.properties['message-id']
        total_bill_amount = None
        will_be_retried = False

        if ('headers' not in amqpMessage.content.properties or
                'submit_sm_resp_bill' not in amqpMessage.content.properties['headers']):
            submit_sm_resp_bill = None
        else:
            submit_sm_resp_bill = pickle.loads(
                amqpMessage.content.properties['headers']['submit_sm_resp_bill'])

        if r.response.status == CommandStatus.ESME_ROK:
            # No more retrials !
            del self.submit_retrials[msgid]

            # Get bill information
            total_bill_amount = 0.0
            if submit_sm_resp_bill is not None and submit_sm_resp_bill.getTotalAmounts() > 0:
                total_bill_amount = submit_sm_resp_bill.getTotalAmounts()

            # UDH is set ?
            UDHI_INDICATOR_SET = False
            if hasattr(r.request.params['esm_class'], 'gsmFeatures'):
                for gsmFeature in r.request.params['esm_class'].gsmFeatures:
                    if str(gsmFeature) == 'UDHI_INDICATOR_SET':
                        UDHI_INDICATOR_SET = True
                        break

            # What type of splitting ?
            splitMethod = None
            if 'sar_msg_ref_num' in r.request.params:
                splitMethod = 'sar'
            elif UDHI_INDICATOR_SET and r.request.params['short_message'][:3] == '\x05\x00\x03':
                splitMethod = 'udh'

            # Concatenate short_message
            if splitMethod is not None:
                _pdu = r.request
                if splitMethod == 'sar':
                    short_message = _pdu.params['short_message']
                else:
                    short_message = _pdu.params['short_message'][6:]

                while hasattr(_pdu, 'nextPdu'):
                    _pdu = _pdu.nextPdu
                    if splitMethod == 'sar':
                        short_message += _pdu.params['short_message']
                    else:
                        short_message += _pdu.params['short_message'][6:]

                    # Increase bill amount for each submit_sm_resp
                    if submit_sm_resp_bill is not None and submit_sm_resp_bill.getTotalAmounts() > 0:
                        total_bill_amount += submit_sm_resp_bill.getTotalAmounts()
            else:
                short_message = r.request.params['short_message']

            self.log.info("SMS-MT [cid:%s] [queue-msgid:%s] [smpp-msgid:%s] [status:%s] [prio:%s] [dlr:%s] [validity:%s] [from:%s] [to:%s] [content:%s]",
                          self.SMPPClientFactory.config.id,
                          msgid,
                          r.response.params['message_id'],
                          r.response.status,
                          amqpMessage.content.properties['priority'],
                          r.request.params['registered_delivery'].receipt,
                          'none' if ('headers' not in amqpMessage.content.properties or
                            'expiration' not in amqpMessage.content.properties['headers'])
                            else amqpMessage.content.properties['headers']['expiration'],
                          r.request.params['source_addr'],
                          r.request.params['destination_addr'],
                          re.sub(r'[^\x20-\x7E]+', '.', short_message))
        else:
            # Message must be retried ?
            if str(r.response.status) in self.config.submit_error_retrial:
                retrial = self.config.submit_error_retrial[str(r.response.status)]

                # Still have some retrys to go ?
                if self.submit_retrials[msgid] < retrial['count']:
                    # Requeue the message for later redelivery
                    yield self.rejectAndRequeueMessage(amqpMessage, delay=retrial['delay'])
                    will_be_retried = True

            # Log the message
            self.log.info("SMS-MT [cid:%s] [queue-msgid:%s] [status:ERROR/%s] [retry:%s] [prio:%s] [dlr:%s] [validity:%s] [from:%s] [to:%s] [content:%s]",
                          self.SMPPClientFactory.config.id,
                          msgid,
                          r.response.status,
                          will_be_retried,
                          amqpMessage.content.properties['priority'],
                          r.request.params['registered_delivery'].receipt,
                          'none' if ('headers' not in amqpMessage.content.properties or
                            'expiration' not in amqpMessage.content.properties['headers'])
                            else amqpMessage.content.properties['headers']['expiration'],
                          r.request.params['source_addr'],
                          r.request.params['destination_addr'],
                          re.sub(r'[^\x20-\x7E]+', '.', r.request.params['short_message']))

        # It is a final submit_sm_resp !
        if not will_be_retried:
            # Cancel any mapped rejectTimer to this message (in case this message was rejected in the past)
            self.clearRejectTimer(msgid)
            self.log.debug("ACKing amqpMessage [%s] having routing_key [%s]", msgid, amqpMessage.routing_key)
            # ACK the message in queue, this will remove it from the queue
            yield self.ackMessage(amqpMessage)

        # Redis client is connected ?
        # Check DLR mappings and publish receipt for later throwing
        if self.redisClient is not None:
            # Check for HTTP DLR request from redis 'dlr' key
            # If there's a pending delivery receipt request then serve it
            # back by publishing a DLRContentForHttpapi to the messaging exchange
            pickledDlr = None
            pickledSmppsMap = None
            pickledDlr = yield self.redisClient.get("dlr:%s" % msgid)
            if pickledDlr is None:
                pickledSmppsMap = yield self.redisClient.get("smppsmap:%s" % msgid)

            if pickledDlr is not None:
                self.log.debug('There is a HTTP DLR request for msgid[%s] ...', msgid)

                dlr = pickle.loads(pickledDlr)
                dlr_url = dlr['url']
                dlr_level = dlr['level']
                dlr_method = dlr['method']
                dlr_expiry = dlr['expiry']

                if dlr_level in [1, 3]:
                    self.log.debug('Got DLR information for msgid[%s], url:%s, level:%s',
                                   msgid, dlr_url, dlr_level)

                    # The dlr_url in DLRContentForHttpapi indicates the level
                    # of the actual delivery receipt (1) and not the requested
                    # one (maybe 1 or 3)
                    content = DLRContentForHttpapi(str(r.response.status),
                                                   msgid, dlr_url,
                                                   dlr_level=1, method=dlr_method)
                    routing_key = 'dlr_thrower.http'
                    self.log.debug("Publishing DLRContentForHttpapi[%s] with routing_key[%s]",
                                   msgid, routing_key)
                    yield self.amqpBroker.publish(exchange='messaging',
                                                  routing_key=routing_key,
                                                  content=content)

                    # DLR request is removed if:
                    # - If level 1 is requested (SMSC level only)
                    # - SubmitSmResp returned an error (no more delivery will be tracked)
                    #
                    # When level 3 is requested, the DLR will be removed when
                    # receiving a deliver_sm (terminal receipt)
                    if dlr_level == 1 or r.response.status != CommandStatus.ESME_ROK:
                        self.log.debug('Removing DLR request for msgid[%s]', msgid)
                        yield self.redisClient.delete("dlr:%s" % msgid)
                else:
                    self.log.debug(
                        'Terminal level receipt is requested, will not send any DLR receipt at this level.')

                if dlr_level in [2, 3] and r.response.status == CommandStatus.ESME_ROK:
                    # Map received submit_sm_resp's message_id to the msg for later receipt handling
                    self.log.debug('Mapping smpp msgid: %s to queue msgid: %s, expiring in %s',
                                   r.response.params['message_id'], msgid, dlr_expiry)
                    hashKey = "queue-msgid:%s" % r.response.params['message_id'].upper().lstrip('0')
                    hashValues = {'msgid': msgid, 'connector_type': 'httpapi',}
                    yield self.redisClient.setex(hashKey,
                                                 dlr_expiry,
                                                 pickle.dumps(hashValues, self.pickleProtocol))
            elif pickledSmppsMap is not None:
                self.log.debug('There is a SMPPs mapping for msgid[%s] ...', msgid)

                smpps_map = pickle.loads(pickledSmppsMap)
                system_id = smpps_map['system_id']
                source_addr = smpps_map['source_addr']
                destination_addr = smpps_map['destination_addr']
                sub_date = smpps_map['sub_date']
                registered_delivery = smpps_map['registered_delivery']
                smpps_map_expiry = smpps_map['expiry']

                # Do we need to forward the receipt to the original sender ?
                if ((r.response.status == CommandStatus.ESME_ROK and
                        str(registered_delivery.receipt) in ['SMSC_DELIVERY_RECEIPT_REQUESTED_FOR_FAILURE',
                                                             'SMSC_DELIVERY_RECEIPT_REQUESTED']) or
                        (r.response.status != CommandStatus.ESME_ROK and
                        str(registered_delivery.receipt) == 'SMSC_DELIVERY_RECEIPT_REQUESTED_FOR_FAILURE')):
                    self.log.debug('Got DLR information for msgid[%s], registered_deliver%s, system_id:%s',
                                   msgid, registered_delivery, system_id)

                    if (r.response.status != CommandStatus.ESME_ROK
                            or (r.response.status == CommandStatus.ESME_ROK
                            and self.config.smpp_receipt_on_success_submit_sm_resp)):
                        # Send back a receipt (by throwing deliver_sm or data_sm)
                        content = DLRContentForSmpps(str(r.response.status),
                                                     msgid,
                                                     system_id,
                                                     source_addr,
                                                     destination_addr,
                                                     sub_date)

                        routing_key = 'dlr_thrower.smpps'
                        self.log.debug("Publishing DLRContentForSmpps[%s] with routing_key[%s]",
                                       msgid, routing_key)
                        yield self.amqpBroker.publish(exchange='messaging',
                                                      routing_key=routing_key,
                                                      content=content)

                    if r.response.status == CommandStatus.ESME_ROK:
                        # Map received submit_sm_resp's message_id to the msg for later rceipt handling
                        self.log.debug('Mapping smpp msgid: %s to queue msgid: %s, expiring in %s',
                                       r.response.params['message_id'], msgid, smpps_map_expiry)
                        hashKey = "queue-msgid:%s" % r.response.params['message_id'].upper().lstrip('0')
                        hashValues = {'msgid': msgid, 'connector_type': 'smpps',}
                        yield self.redisClient.setex(hashKey,
                                                     smpps_map_expiry,
                                                     pickle.dumps(hashValues, self.pickleProtocol))
        else:
            self.log.warn('No valid RC were found while checking msg[%s] !', msgid)

        # Bill will be charged by bill_request.submit_sm_resp.UID queue consumer
        if total_bill_amount > 0:
            pubQueueName = 'bill_request.submit_sm_resp.%s' % submit_sm_resp_bill.user.uid
            content = SubmitSmRespBillContent(submit_sm_resp_bill.bid,
                                              submit_sm_resp_bill.user.uid, total_bill_amount)
            self.log.debug(
                "Requesting a SubmitSmRespBillContent from a bill [bid:%s] with routing_key[%s]: %s",
                submit_sm_resp_bill.bid, pubQueueName, total_bill_amount)
            yield self.amqpBroker.publish(exchange='billing',
                                          routing_key=pubQueueName,
                                          content=content)

        if self.config.publish_submit_sm_resp:
            # Send back submit_sm_resp to submit.sm.resp.CID queue
            # There's no actual listeners on this queue, it can be used to
            # track submit_sm_resp messages from a 3rd party app
            content = SubmitSmRespContent(r.response, msgid, pickleProtocol=self.pickleProtocol)
            self.log.debug("Sending back SubmitSmRespContent[%s] with routing_key[%s]",
                           msgid, amqpMessage.content.properties['reply-to'])
            yield self.amqpBroker.publish(exchange='messaging',
                                          routing_key=amqpMessage.content.properties['reply-to'],
                                          content=content)

        if will_be_retried:
            defer.returnValue(False)
예제 #11
0
    def deliver_sm_event(self, smpp, pdu, concatenated=False):
        """This event is called whenever a deliver_sm pdu is received through a SMPPc
        It will hand the pdu to the router or a dlr thrower (depending if its a DLR or not).
        
        Note: this event will catch data_sm pdus as well
        """

        pdu.dlr = self.SMPPOperationFactory.isDeliveryReceipt(pdu)
        content = DeliverSmContent(pdu,
                                   self.SMPPClientFactory.config.id,
                                   pickleProtocol=self.pickleProtocol,
                                   concatenated=concatenated)
        msgid = content.properties['message-id']

        if pdu.dlr is None:
            # We have a SMS-MO

            # UDH is set ?
            UDHI_INDICATOR_SET = False
            if hasattr(pdu.params['esm_class'], 'gsmFeatures'):
                for gsmFeature in pdu.params['esm_class'].gsmFeatures:
                    if str(gsmFeature) == 'UDHI_INDICATOR_SET':
                        UDHI_INDICATOR_SET = True
                        break

            splitMethod = None
            # Is it a part of a long message ?
            if 'sar_msg_ref_num' in pdu.params:
                splitMethod = 'sar'
                total_segments = pdu.params['sar_total_segments']
                segment_seqnum = pdu.params['sar_segment_seqnum']
                msg_ref_num = pdu.params['sar_msg_ref_num']
                self.log.debug(
                    'Received a part of SMS-MO [queue-msgid:%s] using SAR options: total_segments=%s, segmen_seqnum=%s, msg_ref_num=%s'
                    % (msgid, total_segments, segment_seqnum, msg_ref_num))
            elif UDHI_INDICATOR_SET and pdu.params[
                    'short_message'][:3] == '\x05\x00\x03':
                splitMethod = 'udh'
                total_segments = struct.unpack(
                    '!B', pdu.params['short_message'][4])[0]
                segment_seqnum = struct.unpack(
                    '!B', pdu.params['short_message'][5])[0]
                msg_ref_num = struct.unpack('!B',
                                            pdu.params['short_message'][3])[0]
                self.log.debug(
                    'Received a part of SMS-MO [queue-msgid:%s] using UDH options: total_segments=%s, segmen_seqnum=%s, msg_ref_num=%s'
                    % (msgid, total_segments, segment_seqnum, msg_ref_num))

            if splitMethod is None:
                # It's a simple short message or a part of a concatenated message
                routing_key = 'deliver.sm.%s' % self.SMPPClientFactory.config.id
                self.log.debug(
                    "Publishing DeliverSmContent[%s] with routing_key[%s]" %
                    (msgid, routing_key))
                yield self.amqpBroker.publish(exchange='messaging',
                                              routing_key=routing_key,
                                              content=content)

                self.log.info(
                    "SMS-MO [cid:%s] [queue-msgid:%s] [status:%s] [prio:%s] [validity:%s] [from:%s] [to:%s] [content:%s]"
                    %
                    (self.SMPPClientFactory.config.id, msgid, pdu.status,
                     pdu.params['priority_flag'],
                     pdu.params['validity_period'], pdu.params['source_addr'],
                     pdu.params['destination_addr'],
                     re.sub(r'[^\x20-\x7E]+', '.',
                            pdu.params['short_message'])))
            else:
                # Long message part received
                if self.redisClient is None:
                    self.warn(
                        'No valid RC were found while receiving a part of a long DeliverSm [queue-msgid:%s], MESSAGE IS LOST !'
                        % msgid)

                # Save it to redis
                hashKey = "longDeliverSm:%s" % (msg_ref_num)
                hashValues = {
                    'pdu': pdu,
                    'total_segments': total_segments,
                    'msg_ref_num': msg_ref_num,
                    'segment_seqnum': segment_seqnum
                }
                self.redisClient.hset(
                    hashKey, segment_seqnum,
                    pickle.dumps(hashValues, self.pickleProtocol)).addCallback(
                        self.concatDeliverSMs, splitMethod, total_segments,
                        msg_ref_num, segment_seqnum)

                self.log.info(
                    "DeliverSmContent[%s] is a part of a long message of %s parts, will be sent to queue after concatenation."
                    % (msgid, total_segments))

                # Flag it as "will_be_concatenated" and publish it to router
                routing_key = 'deliver.sm.%s' % self.SMPPClientFactory.config.id
                self.log.debug(
                    "Publishing DeliverSmContent[%s](flagged:wbc) with routing_key[%s]"
                    % (msgid, routing_key))
                content.properties['headers']['will_be_concatenated'] = True
                yield self.amqpBroker.publish(exchange='messaging',
                                              routing_key=routing_key,
                                              content=content)
        else:
            # This is a DLR !
            # Check for DLR request
            if self.redisClient is not None:
                _coded_dlr_id = self.code_dlr_msgid(pdu)

                q = yield self.redisClient.get("queue-msgid:%s" %
                                               _coded_dlr_id)
                submit_sm_queue_id = None
                connector_type = None
                if q is not None:
                    q = pickle.loads(q)
                    submit_sm_queue_id = q['msgid']
                    connector_type = q['connector_type']

                if submit_sm_queue_id is not None and connector_type == 'httpapi':
                    pickledDlr = yield self.redisClient.get("dlr:%s" %
                                                            submit_sm_queue_id)

                    if pickledDlr is not None:
                        dlr = pickle.loads(pickledDlr)
                        dlr_url = dlr['url']
                        dlr_level = dlr['level']
                        dlr_method = dlr['method']

                        if dlr_level in [2, 3]:
                            self.log.debug(
                                'Got DLR information for msgid[%s], url:%s, level:%s'
                                % (submit_sm_queue_id, dlr_url, dlr_level))
                            content = DLRContentForHttpapi(
                                pdu.dlr['stat'],
                                submit_sm_queue_id,
                                dlr_url,
                                # The dlr_url in DLRContentForHttpapi indicates the level
                                # of the actual delivery receipt (2) and not the
                                # requested one (maybe 2 or 3)
                                dlr_level=2,
                                id_smsc=_coded_dlr_id,
                                sub=pdu.dlr['sub'],
                                dlvrd=pdu.dlr['dlvrd'],
                                subdate=pdu.dlr['sdate'],
                                donedate=pdu.dlr['ddate'],
                                err=pdu.dlr['err'],
                                text=pdu.dlr['text'],
                                method=dlr_method)
                            routing_key = 'dlr_thrower.http'
                            self.log.debug(
                                "Publishing DLRContentForHttpapi[%s] with routing_key[%s]"
                                % (submit_sm_queue_id, routing_key))
                            yield self.amqpBroker.publish(
                                exchange='messaging',
                                routing_key=routing_key,
                                content=content)

                            self.log.debug(
                                'Removing DLR request for msgid[%s]' %
                                submit_sm_queue_id)
                            yield self.redisClient.delete('dlr:%s' %
                                                          submit_sm_queue_id)
                        else:
                            self.log.debug(
                                'SMS-C receipt is requested, will not send any DLR receipt at this level.'
                            )
                    else:
                        self.log.warn('DLR for msgid[%s] not found !' %
                                      (submit_sm_queue_id))
                elif submit_sm_queue_id is not None and connector_type == 'smpps':
                    pickledSmppsMap = yield self.redisClient.get(
                        "smppsmap:%s" % submit_sm_queue_id)

                    if pickledSmppsMap is not None:
                        smpps_map = pickle.loads(pickledSmppsMap)
                        system_id = smpps_map['system_id']
                        source_addr = smpps_map['source_addr']
                        destination_addr = smpps_map['destination_addr']
                        sub_date = smpps_map['sub_date']
                        registered_delivery = smpps_map['registered_delivery']
                        smpps_map_expiry = smpps_map['expiry']

                        success_states = ['ACCEPTD', 'DELIVRD']
                        final_states = [
                            'DELIVRD', 'EXPIRED', 'DELETED', 'UNDELIV',
                            'REJECTD'
                        ]
                        # Do we need to forward the receipt to the original sender ?
                        if ((pdu.dlr['stat'] in success_states
                             and str(registered_delivery.receipt)
                             == 'SMSC_DELIVERY_RECEIPT_REQUESTED') or
                            (pdu.dlr['stat'] not in success_states
                             and str(registered_delivery.receipt) in [
                                 'SMSC_DELIVERY_RECEIPT_REQUESTED',
                                 'SMSC_DELIVERY_RECEIPT_REQUESTED_FOR_FAILURE'
                             ])):

                            self.log.debug(
                                'Got DLR information for msgid[%s], registered_deliver%s, system_id:%s'
                                % (submit_sm_queue_id, registered_delivery,
                                   system_id))
                            content = DLRContentForSmpps(
                                pdu.dlr['stat'], submit_sm_queue_id, system_id,
                                source_addr, destination_addr, sub_date)

                            routing_key = 'dlr_thrower.smpps'
                            self.log.debug(
                                "Publishing DLRContentForSmpps[%s] with routing_key[%s]"
                                % (submit_sm_queue_id, routing_key))
                            yield self.amqpBroker.publish(
                                exchange='messaging',
                                routing_key=routing_key,
                                content=content)

                            if pdu.dlr['stat'] in final_states:
                                self.log.debug(
                                    'Removing SMPPs map for msgid[%s]' %
                                    submit_sm_queue_id)
                                yield self.redisClient.delete(
                                    'smppsmap:%s' % submit_sm_queue_id)
                else:
                    self.log.warn(
                        'Got a DLR for an unknown message id: %s (coded:%s)' %
                        (pdu.dlr['id'], _coded_dlr_id))
            else:
                self.log.warn(
                    'DLR for msgid[%s] is not checked, no valid RC were found'
                    % msgid)

            self.log.info(
                "DLR [cid:%s] [smpp-msgid:%s] [status:%s] [submit date:%s] [done date:%s] [sub/dlvrd messages:%s/%s] [err:%s] [content:%s]"
                % (
                    self.SMPPClientFactory.config.id,
                    _coded_dlr_id,
                    pdu.dlr['stat'],
                    pdu.dlr['sdate'],
                    pdu.dlr['ddate'],
                    pdu.dlr['sub'],
                    pdu.dlr['dlvrd'],
                    pdu.dlr['err'],
                    pdu.dlr['text'],
                ))
예제 #12
0
 def publishDLRContentForSmppapi(self, message_status, msgid, system_id, source_addr, destination_addr):
     content = DLRContentForSmpps(message_status, msgid, system_id, source_addr, destination_addr)
     yield self.amqpBroker.publish(exchange='messaging', routing_key='dlr_thrower.smpps', content=content)
예제 #13
0
             http_status)

# Returning a msgid with ESME_ROK
if routable.user.uid == 'entel':
    extra['message_id'] = claim_msgid_for_uid(routable.user.uid)
else:
    extra['message_id'] = str(uuid.uuid4())

# Send back a DLR
status = 'DELIVRD'
dlr_content = DLRContentForSmpps(
    status,
    extra['message_id'],
    routable.user.uid,
    submit_sm.params['source_addr'],
    submit_sm.params['destination_addr'],
    datetime.now(),
    str(submit_sm.params['dest_addr_ton']),
    str(submit_sm.params['dest_addr_npi']),
    str(submit_sm.params['source_addr_ton']),
    str(submit_sm.params['source_addr_npi']),
)

# Publish DLR
routing_key = 'dlr_thrower.smpps'
channel.basic_publish(
    'messaging', routing_key, dlr_content.body,
    pika.BasicProperties(message_id=dlr_content.properties['message-id'],
                         headers=dlr_content.properties['headers']))
logger.info("Published DLRContentForSmpps[%s] to [%s], having status = %s",
            extra['message_id'], routing_key, status)