-
-
Save MateusLeguir/7d46575036886a937c5dc72621213ae8 to your computer and use it in GitHub Desktop.
Fork of zspine/deliver_sm.py, updated to work with changes in Jasmin SMS since the original was created + fixes a rabbitmq bug. This script will take a submit_sm PDU, send an OK back to the originator whilst replaying it to jasmin as a deliver_sm, effectively converting a submit_sm to deliver_sm. Also will send back a DELIVRD DLR!
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# V0.64 | |
# Bump the above version when modifying this script / pushing to the CLI - | |
# it's a nice way to confirm that the right code is running on jasmin. | |
import pickle | |
import logging | |
import uuid | |
import pika | |
from datetime import datetime | |
from jasmin.managers.content import DeliverSmContent | |
from jasmin.routing.Routables import RoutableDeliverSm | |
from jasmin.routing.jasminApi import * | |
from jasmin.protocols.smpp.operations import DeliverSM | |
from jasmin.managers.content import DLRContentForSmpps | |
from smpp.pdu.pdu_types import RegisteredDeliveryReceipt, RegisteredDelivery | |
from smpp.pdu.pdu_types import (EsmClass, EsmClassMode, EsmClassType, EsmClassGsmFeatures, | |
MoreMessagesToSend, MessageState, AddrTon, AddrNpi) | |
RABBITMQ_URL = 'amqp://guest:guest@rabbitmq:5672/%2F' | |
logger = logging.getLogger('logging-example') | |
if len(logger.handlers) != 1: | |
hdlr = logging.FileHandler('/var/log/jasmin/submit2deliver.log') | |
formatter = logging.Formatter('%(asctime)s %(levelname)s %(message)s') | |
hdlr.setFormatter(formatter) | |
logger.addHandler(hdlr) | |
logger.setLevel(logging.DEBUG) | |
logger.debug("Received a routable from user %s", routable.user.uid) | |
submit_sm = routable.pdu | |
# The [rough] time we received the original submit_sm. Used to send back in the | |
# DLR | |
sub_date = datetime.now() | |
logger.debug("Got submit_sm: %s", submit_sm) | |
deliver_sm = DeliverSM( | |
submit_sm.seqNum, | |
service_type=submit_sm.params['service_type'], | |
source_addr_ton=submit_sm.params['source_addr_ton'], | |
source_addr_npi=submit_sm.params['source_addr_npi'], | |
source_addr=submit_sm.params['source_addr'], | |
dest_addr_ton=submit_sm.params['dest_addr_ton'], | |
dest_addr_npi=submit_sm.params['dest_addr_npi'], | |
destination_addr=submit_sm.params['destination_addr'], | |
esm_class=submit_sm.params['esm_class'], | |
protocol_id=submit_sm.params['protocol_id'], | |
priority_flag=submit_sm.params['priority_flag'], | |
registered_delivery=submit_sm.params['registered_delivery'], | |
replace_if_present_flag=submit_sm.params['replace_if_present_flag'], | |
data_coding=submit_sm.params['data_coding'], | |
short_message=submit_sm.params['short_message'], | |
sm_default_msg_id=submit_sm.params['sm_default_msg_id']) | |
logger.debug("Prepared a new deliver_sm: %s", deliver_sm) | |
# Generate a new routable deliver_sm PDU for injection | |
_routable = RoutableDeliverSm(deliver_sm, Connector(routable.user.uid)) | |
content = DeliverSmContent(_routable, routable.user.uid, pickleProtocol=pickle.HIGHEST_PROTOCOL) | |
routing_key = 'deliver.sm.%s' % routable.user.uid | |
connection = pika.BlockingConnection(pika.URLParameters(RABBITMQ_URL)) | |
channel = connection.channel() | |
# Inject the deliver_sm version of the submit_sm into rabbit | |
logger.debug('RabbitMQ channel ready, publishing now msgid %s ...', content.properties['message-id']) | |
channel.basic_publish( | |
'messaging', | |
routing_key, | |
content.body, | |
pika.BasicProperties( | |
message_id=content.properties['message-id'], | |
headers=content.properties['headers']) | |
) | |
logger.debug('Published deliver_sm to %s', routing_key) | |
# Setting the following status' will stop the Jasmin from trying to route this routable | |
logger.debug("Returning smpp_status %s http_status %s", smpp_status, http_status) | |
smpp_status = 0 | |
http_status = 200 | |
extra['message_id'] = str(uuid.uuid4()) | |
# Start DLR hacking - lifted from protocols/smpp/operations.py #232 getReceipt() | |
# Also see https://smpp.org/SMPP_v3_4_Issue1_2.pdf, `4.6.1 “DELIVER_SM” Syntax`. | |
# We are crafting a `deliver_sm` PDU here that meets the above specification for a DLR | |
# with a `DELIVRD` status | |
def get_enum(enum_type, value): | |
# not very pythonic, but imported here as I think there's some | |
# twisted async magic going on when importing this outside of the function | |
# resulting in the import not being available here. | |
from enum import Enum | |
if isinstance(value, Enum): | |
return value | |
_value = value.split('.') | |
if len(_value) == 2: | |
return getattr(enum_type, _value[1]) | |
else: | |
return getattr(enum_type, value) | |
short_message = r"id:%s submit date:%s done date:%s stat:%s err:%s" % ( | |
extra['message_id'], | |
sub_date.strftime("%y%m%d%H%M"), | |
datetime.now().strftime("%y%m%d%H%M"), | |
"DELIVRD", | |
0, | |
) | |
dlr_deliver_sm = DeliverSM( | |
source_addr=submit_sm.params['destination_addr'], | |
destination_addr=submit_sm.params['source_addr'], | |
esm_class=EsmClass(EsmClassMode.DEFAULT, EsmClassType.SMSC_DELIVERY_RECEIPT), | |
receipted_message_id=extra['message_id'], | |
short_message=short_message, | |
message_state=MessageState.DELIVERED, | |
source_addr_ton=get_enum(AddrTon, submit_sm.params['dest_addr_ton']), | |
source_addr_npi=get_enum(AddrNpi, submit_sm.params['dest_addr_npi']), | |
dest_addr_ton=get_enum(AddrTon, submit_sm.params['source_addr_ton']), | |
dest_addr_npi=get_enum(AddrNpi, submit_sm.params['source_addr_npi']), | |
) | |
# Prepare for deliver_sm injection | |
dlr_routable = RoutableDeliverSm(dlr_deliver_sm, Connector(routable.user.uid)) | |
# Use this to build your MORouter filter on. | |
dlr_routable.addTag(666) | |
dlr_content = DeliverSmContent(dlr_routable, routable.user.uid, pickleProtocol=pickle.HIGHEST_PROTOCOL) | |
routing_key = 'deliver.sm.%s' % routable.user.uid | |
channel.basic_publish( | |
'messaging', | |
routing_key, | |
dlr_content.body, | |
pika.BasicProperties( | |
message_id=dlr_content.properties['message-id'], | |
headers=dlr_content.properties['headers'])) | |
logger.debug('Published DLR deliver_sm to %s', routing_key) | |
connection.close() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment