class PersonAuthentication(PersonAuthenticationType): def __init__(self, currentTimeMillis): self.currentTimeMillis = currentTimeMillis def get_and_parse_smpp_config(self, config, attribute, _type=None, convert=False, optional=False, default_desc=None): try: value = config.get(attribute).getValue2() except: if default_desc: default_desc = " using default '{}'".format(default_desc) else: default_desc = "" if optional: raise SmppAttributeError( "SMPP missing optional configuration attribute '{}'{}". format(attribute, default_desc)) else: raise SmppAttributeError( "SMPP missing required configuration attribute '{}'". format(attribute)) if _type and issubclass(_type, Enum): try: return getattr(_type, value) except AttributeError: raise SmppAttributeError( "SMPP could not find attribute '{}' in {}".format( attribute, _type)) if convert: try: value = int(value) except AttributeError: try: value = int(value, 16) except AttributeError: raise SmppAttributeError( "SMPP could not parse value '{}' of attribute '{}'". format(value, attribute)) return value def init(self, configurationAttributes): print("SMPP Initialization") self.TIME_FORMATTER = AbsoluteTimeFormatter() self.SMPP_SERVER = None self.SMPP_PORT = None self.SYSTEM_ID = None self.PASSWORD = None # Setup some good defaults for TON, NPI and source (from) address # TON (Type of Number), NPI (Number Plan Indicator) self.SRC_ADDR_TON = TypeOfNumber.ALPHANUMERIC # Alphanumeric self.SRC_ADDR_NPI = NumberingPlanIndicator.ISDN # ISDN (E163/E164) self.SRC_ADDR = "Gluu OTP" # Don't touch these unless you know what your doing, we don't handle number reformatting for # any other type than international. self.DST_ADDR_TON = TypeOfNumber.INTERNATIONAL # International self.DST_ADDR_NPI = NumberingPlanIndicator.ISDN # ISDN (E163/E164) # Priority flag and data_coding bits self.PRIORITY_FLAG = 3 # Very Urgent (ANSI-136), Emergency (IS-95) self.DATA_CODING_ALPHABET = Alphabet.ALPHA_DEFAULT # SMS default alphabet self.DATA_CODING_MESSAGE_CLASS = MessageClass.CLASS1 # EM (Mobile Equipment (mobile memory), normal message # Required server settings try: self.SMPP_SERVER = self.get_and_parse_smpp_config( configurationAttributes, "smpp_server") except SmppAttributeError as e: print(e) try: self.SMPP_PORT = self.get_and_parse_smpp_config( configurationAttributes, "smpp_port", convert=True) except SmppAttributeError as e: print(e) if None in (self.SMPP_SERVER, self.SMPP_PORT): print( "SMPP smpp_server and smpp_port is empty, will not enable SMPP service" ) return False # Optional system_id and password for bind auth try: self.SYSTEM_ID = self.get_and_parse_smpp_config( configurationAttributes, "system_id", optional=True) except SmppAttributeError as e: print(e) try: self.PASSWORD = self.get_and_parse_smpp_config( configurationAttributes, "password", optional=True) except SmppAttributeError as e: print(e) if None in (self.SYSTEM_ID, self.PASSWORD): print("SMPP Authentication disabled") # From number and to number settings try: self.SRC_ADDR_TON = self.get_and_parse_smpp_config( configurationAttributes, "source_addr_ton", _type=TypeOfNumber, optional=True, default_desc=self.SRC_ADDR_TON) except SmppAttributeError as e: print(e) try: self.SRC_ADDR_NPI = self.get_and_parse_smpp_config( configurationAttributes, "source_addr_npi", _type=NumberingPlanIndicator, optional=True, default_desc=self.SRC_ADDR_NPI) except SmppAttributeError as e: print(e) try: self.SRC_ADDR = self.get_and_parse_smpp_config( configurationAttributes, "source_addr", optional=True, default_desc=self.SRC_ADDR) except SmppAttributeError as e: print(e) try: self.DST_ADDR_TON = self.get_and_parse_smpp_config( configurationAttributes, "dest_addr_ton", _type=TypeOfNumber, optional=True, default_desc=self.DST_ADDR_TON) except SmppAttributeError as e: print(e) try: self.DST_ADDR_NPI = self.get_and_parse_smpp_config( configurationAttributes, "dest_addr_npi", _type=NumberingPlanIndicator, optional=True, default_desc=self.DST_ADDR_NPI) except SmppAttributeError as e: print(e) # Priority flag and data coding, don't touch these unless you know what your doing... try: self.PRIORITY_FLAG = self.get_and_parse_smpp_config( configurationAttributes, "priority_flag", convert=True, optional=True, default_desc="3 (Very Urgent, Emergency)") except SmppAttributeError as e: print(e) try: self.DATA_CODING_ALPHABET = self.get_and_parse_smpp_config( configurationAttributes, "data_coding_alphabet", _type=Alphabet, optional=True, default_desc=self.DATA_CODING_ALPHABET) except SmppAttributeError as e: print(e) try: self.DATA_CODING_MESSAGE_CLASS = self.get_and_parse_smpp_config( configurationAttributes, "data_coding_alphabet", _type=MessageClass, optional=True, default_desc=self.DATA_CODING_MESSAGE_CLASS) except SmppAttributeError as e: print(e) print("SMPP Initialized successfully") return True def destroy(self, configurationAttributes): print("SMPP Destroyed successfully") return True def getApiVersion(self): return 1 def isValidAuthenticationMethod(self, usageType, configurationAttributes): return True def getAlternativeAuthenticationMethod(self, usageType, configurationAttributes): return None def authenticate(self, configurationAttributes, requestParameters, step): print("SMPP Authenticate for step {}".format(step)) identity = CdiUtil.bean(Identity) authenticationService = CdiUtil.bean(AuthenticationService) user = authenticationService.getAuthenticatedUser() if step == 1: if not user: credentials = identity.getCredentials() user_name = credentials.getUsername() user_password = credentials.getPassword() if StringHelper.isNotEmptyString( user_name) and StringHelper.isNotEmptyString( user_password): authenticationService.authenticate(user_name, user_password) user = authenticationService.getAuthenticatedUser() if not user: return False numbers = self.getNumbers(user) if not numbers: return False else: # Generate Random six digit code code = random.randint(100000, 999999) identity.setWorkingParameter("randCode", code) if len(numbers) == 1: return self.sendMessage(numbers[0], str(code)) else: chopped = [number[-4:] for number in numbers] # converting to comma-separated list (identity does not remember lists) identity.setWorkingParameter("numbers", ",".join(numbers)) identity.setWorkingParameter("choppedNos", ",".join(chopped)) return True else: if not user: return False session_attributes = identity.getSessionId().getSessionAttributes() code = session_attributes.get("randCode") numbers = session_attributes.get("numbers") if step == 2 and numbers: # Means that the selection number page was used idx = ServerUtil.getFirstValue( requestParameters, "OtpSmsloginForm:indexOfNumber") if idx and code: number = numbers.split(",")[int(idx)] return self.sendMessage(number, str(code)) else: return False form_passcode = ServerUtil.getFirstValue(requestParameters, "passcode") if form_passcode and code == form_passcode: print( "SMPP authenticate. 6-digit code matches with code sent via SMS" ) return True else: facesMessages = CdiUtil.bean(FacesMessages) facesMessages.setKeepMessages() facesMessages.clear() facesMessages.add(FacesMessage.SEVERITY_ERROR, "Wrong code entered") return False def getNumbers(self, user): numbers = set() tmp = user.getAttributeValues("mobile") if tmp: for t in tmp: numbers.add(t) return list(numbers) def prepareForStep(self, configurationAttributes, requestParameters, step): print("SMPP Prepare for Step {}".format(step)) return True def getExtraParametersForStep(self, configurationAttributes, step): if step > 1: return Arrays.asList("randCode", "numbers", "choppedNos") return None def getCountAuthenticationSteps(self, configurationAttributes): if not CdiUtil.bean(Identity).getWorkingParameter("numbers"): return 2 else: return 3 def getPageForStep(self, configurationAttributes, step): print("SMPP getPageForStep called {}".format(step)) print("SMPP Numbers are {}".format( CdiUtil.bean(Identity).getWorkingParameter("numbers"))) def_page = "/casa/otp_sms.xhtml" if step == 2: if not CdiUtil.bean(Identity).getWorkingParameter("numbers"): return def_page else: return "/casa/otp_sms_prompt.xhtml" elif step == 3: return def_page return "" def logout(self, configurationAttributes, requestParameters): return True def hasEnrollments(self, configurationAttributes, user): return len(self.getNumbers(user)) > 0 def sendMessage(self, number, code): status = False session = SMPPSession() session.setTransactionTimer(10000) # We only handle international destination number reformatting. # All others may vary by configuration decisions taken on SMPP # server side which we have no clue about. if self.DST_ADDR_TON == TypeOfNumber.INTERNATIONAL and number.startswith( "+"): number = number[1:] try: print("SMPP Connecting") reference_id = session.connectAndBind( self.SMPP_SERVER, self.SMPP_PORT, BindParameter(BindType.BIND_TX, self.SYSTEM_ID, self.PASSWORD, None, self.SRC_ADDR_TON, self.SRC_ADDR_NPI, None)) print("SMPP Connected to server with system id {}".format( reference_id)) try: message_id = session.submitShortMessage( "CMT", self.SRC_ADDR_TON, self.SRC_ADDR_NPI, self.SRC_ADDR, self.DST_ADDR_TON, self.DST_ADDR_NPI, number, ESMClass(), 0, self.PRIORITY_FLAG, self.TIME_FORMATTER.format(Date()), None, RegisteredDelivery(SMSCDeliveryReceipt.DEFAULT), 0, GeneralDataCoding(self.DATA_CODING_ALPHABET, self.DATA_CODING_MESSAGE_CLASS, False), 0, code + " is your passcode to access your account") print( "SMPP Message '{}' sent to #{} with message id {}".format( code, number, message_id)) status = True except PDUException as e: print("SMPP Invalid PDU parameter: {}".format(e)) except ResponseTimeoutException as e: print("SMPP Response timeout: {}".format(e)) except InvalidResponseException as e: print("SMPP Receive invalid response: {}".format(e)) except NegativeResponseException as e: print("SMPP Receive negative response: {}".format(e)) except IOException as e: print("SMPP IO error occured: {}".format(e)) finally: session.unbindAndClose() except IOException as e: print("SMPP Failed connect and bind to host: {}".format(e)) return status
def init(self, configurationAttributes): print("SMPP Initialization") self.TIME_FORMATTER = AbsoluteTimeFormatter() self.SMPP_SERVER = None self.SMPP_PORT = None self.SYSTEM_ID = None self.PASSWORD = None # Setup some good defaults for TON, NPI and source (from) address # TON (Type of Number), NPI (Number Plan Indicator) self.SRC_ADDR_TON = TypeOfNumber.ALPHANUMERIC # Alphanumeric self.SRC_ADDR_NPI = NumberingPlanIndicator.ISDN # ISDN (E163/E164) self.SRC_ADDR = "Gluu OTP" # Don't touch these unless you know what your doing, we don't handle number reformatting for # any other type than international. self.DST_ADDR_TON = TypeOfNumber.INTERNATIONAL # International self.DST_ADDR_NPI = NumberingPlanIndicator.ISDN # ISDN (E163/E164) # Priority flag and data_coding bits self.PRIORITY_FLAG = 3 # Very Urgent (ANSI-136), Emergency (IS-95) self.DATA_CODING_ALPHABET = Alphabet.ALPHA_DEFAULT # SMS default alphabet self.DATA_CODING_MESSAGE_CLASS = MessageClass.CLASS1 # EM (Mobile Equipment (mobile memory), normal message # Required server settings try: self.SMPP_SERVER = self.get_and_parse_smpp_config( configurationAttributes, "smpp_server") except SmppAttributeError as e: print(e) try: self.SMPP_PORT = self.get_and_parse_smpp_config( configurationAttributes, "smpp_port", convert=True) except SmppAttributeError as e: print(e) if None in (self.SMPP_SERVER, self.SMPP_PORT): print( "SMPP smpp_server and smpp_port is empty, will not enable SMPP service" ) return False # Optional system_id and password for bind auth try: self.SYSTEM_ID = self.get_and_parse_smpp_config( configurationAttributes, "system_id", optional=True) except SmppAttributeError as e: print(e) try: self.PASSWORD = self.get_and_parse_smpp_config( configurationAttributes, "password", optional=True) except SmppAttributeError as e: print(e) if None in (self.SYSTEM_ID, self.PASSWORD): print("SMPP Authentication disabled") # From number and to number settings try: self.SRC_ADDR_TON = self.get_and_parse_smpp_config( configurationAttributes, "source_addr_ton", _type=TypeOfNumber, optional=True, default_desc=self.SRC_ADDR_TON) except SmppAttributeError as e: print(e) try: self.SRC_ADDR_NPI = self.get_and_parse_smpp_config( configurationAttributes, "source_addr_npi", _type=NumberingPlanIndicator, optional=True, default_desc=self.SRC_ADDR_NPI) except SmppAttributeError as e: print(e) try: self.SRC_ADDR = self.get_and_parse_smpp_config( configurationAttributes, "source_addr", optional=True, default_desc=self.SRC_ADDR) except SmppAttributeError as e: print(e) try: self.DST_ADDR_TON = self.get_and_parse_smpp_config( configurationAttributes, "dest_addr_ton", _type=TypeOfNumber, optional=True, default_desc=self.DST_ADDR_TON) except SmppAttributeError as e: print(e) try: self.DST_ADDR_NPI = self.get_and_parse_smpp_config( configurationAttributes, "dest_addr_npi", _type=NumberingPlanIndicator, optional=True, default_desc=self.DST_ADDR_NPI) except SmppAttributeError as e: print(e) # Priority flag and data coding, don't touch these unless you know what your doing... try: self.PRIORITY_FLAG = self.get_and_parse_smpp_config( configurationAttributes, "priority_flag", convert=True, optional=True, default_desc="3 (Very Urgent, Emergency)") except SmppAttributeError as e: print(e) try: self.DATA_CODING_ALPHABET = self.get_and_parse_smpp_config( configurationAttributes, "data_coding_alphabet", _type=Alphabet, optional=True, default_desc=self.DATA_CODING_ALPHABET) except SmppAttributeError as e: print(e) try: self.DATA_CODING_MESSAGE_CLASS = self.get_and_parse_smpp_config( configurationAttributes, "data_coding_alphabet", _type=MessageClass, optional=True, default_desc=self.DATA_CODING_MESSAGE_CLASS) except SmppAttributeError as e: print(e) print("SMPP Initialized successfully") return True
class PersonAuthentication(PersonAuthenticationType): def __init__(self, currentTimeMillis): self.currentTimeMillis = currentTimeMillis self.identity = CdiUtil.bean(Identity) def get_and_parse_smpp_config(self, config, attribute, _type=None, convert=False, optional=False, default_desc=None): try: value = config.get(attribute).getValue2() except: if default_desc: default_desc = " using default '{}'".format(default_desc) else: default_desc = "" if optional: raise SmppAttributeError( "SMPP missing optional configuration attribute '{}'{}". format(attribute, default_desc)) else: raise SmppAttributeError( "SMPP missing required configuration attribute '{}'". format(attribute)) if _type and issubclass(_type, Enum): try: return getattr(_type, value) except AttributeError: raise SmppAttributeError( "SMPP could not find attribute '{}' in {}".format( attribute, _type)) if convert: try: value = int(value) except AttributeError: try: value = int(value, 16) except AttributeError: raise SmppAttributeError( "SMPP could not parse value '{}' of attribute '{}'". format(value, attribute)) return value def init(self, customScript, configurationAttributes): print("SMPP Initialization") self.TIME_FORMATTER = AbsoluteTimeFormatter() self.SMPP_SERVER = None self.SMPP_PORT = None self.SYSTEM_ID = None self.PASSWORD = None # Setup some good defaults for TON, NPI and source (from) address # TON (Type of Number), NPI (Number Plan Indicator) self.SRC_ADDR_TON = TypeOfNumber.ALPHANUMERIC # Alphanumeric self.SRC_ADDR_NPI = NumberingPlanIndicator.ISDN # ISDN (E163/E164) self.SRC_ADDR = "Gluu OTP" # Don't touch these unless you know what your doing, we don't handle number reformatting for # any other type than international. self.DST_ADDR_TON = TypeOfNumber.INTERNATIONAL # International self.DST_ADDR_NPI = NumberingPlanIndicator.ISDN # ISDN (E163/E164) # Priority flag and data_coding bits self.PRIORITY_FLAG = 3 # Very Urgent (ANSI-136), Emergency (IS-95) self.DATA_CODING_ALPHABET = Alphabet.ALPHA_DEFAULT # SMS default alphabet self.DATA_CODING_MESSAGE_CLASS = MessageClass.CLASS1 # EM (Mobile Equipment (mobile memory), normal message # Required server settings try: self.SMPP_SERVER = self.get_and_parse_smpp_config( configurationAttributes, "smpp_server") except SmppAttributeError as e: print(e) try: self.SMPP_PORT = self.get_and_parse_smpp_config( configurationAttributes, "smpp_port", convert=True) except SmppAttributeError as e: print(e) if None in (self.SMPP_SERVER, self.SMPP_PORT): print( "SMPP smpp_server and smpp_port is empty, will not enable SMPP service" ) return False # Optional system_id and password for bind auth try: self.SYSTEM_ID = self.get_and_parse_smpp_config( configurationAttributes, "system_id", optional=True) except SmppAttributeError as e: print(e) try: self.PASSWORD = self.get_and_parse_smpp_config( configurationAttributes, "password", optional=True) except SmppAttributeError as e: print(e) if None in (self.SYSTEM_ID, self.PASSWORD): print("SMPP Authentication disabled") # From number and to number settings try: self.SRC_ADDR_TON = self.get_and_parse_smpp_config( configurationAttributes, "source_addr_ton", _type=TypeOfNumber, optional=True, default_desc=self.SRC_ADDR_TON) except SmppAttributeError as e: print(e) try: self.SRC_ADDR_NPI = self.get_and_parse_smpp_config( configurationAttributes, "source_addr_npi", _type=NumberingPlanIndicator, optional=True, default_desc=self.SRC_ADDR_NPI) except SmppAttributeError as e: print(e) try: self.SRC_ADDR = self.get_and_parse_smpp_config( configurationAttributes, "source_addr", optional=True, default_desc=self.SRC_ADDR) except SmppAttributeError as e: print(e) try: self.DST_ADDR_TON = self.get_and_parse_smpp_config( configurationAttributes, "dest_addr_ton", _type=TypeOfNumber, optional=True, default_desc=self.DST_ADDR_TON) except SmppAttributeError as e: print(e) try: self.DST_ADDR_NPI = self.get_and_parse_smpp_config( configurationAttributes, "dest_addr_npi", _type=NumberingPlanIndicator, optional=True, default_desc=self.DST_ADDR_NPI) except SmppAttributeError as e: print(e) # Priority flag and data coding, don't touch these unless you know what your doing... try: self.PRIORITY_FLAG = self.get_and_parse_smpp_config( configurationAttributes, "priority_flag", convert=True, optional=True, default_desc="3 (Very Urgent, Emergency)") except SmppAttributeError as e: print(e) try: self.DATA_CODING_ALPHABET = self.get_and_parse_smpp_config( configurationAttributes, "data_coding_alphabet", _type=Alphabet, optional=True, default_desc=self.DATA_CODING_ALPHABET) except SmppAttributeError as e: print(e) try: self.DATA_CODING_MESSAGE_CLASS = self.get_and_parse_smpp_config( configurationAttributes, "data_coding_alphabet", _type=MessageClass, optional=True, default_desc=self.DATA_CODING_MESSAGE_CLASS) except SmppAttributeError as e: print(e) print("SMPP Initialized successfully") return True def destroy(self, configurationAttributes): print("SMPP Destroy") print("SMPP Destroyed successfully") return True def getApiVersion(self): return 11 def getAuthenticationMethodClaims(self, requestParameters): return None def isValidAuthenticationMethod(self, usageType, configurationAttributes): return True def getAlternativeAuthenticationMethod(self, usageType, configurationAttributes): return None def authenticate(self, configurationAttributes, requestParameters, step): userService = CdiUtil.bean(UserService) authenticationService = CdiUtil.bean(AuthenticationService) facesMessages = CdiUtil.bean(FacesMessages) facesMessages.setKeepMessages() session_attributes = self.identity.getSessionId().getSessionAttributes( ) form_passcode = ServerUtil.getFirstValue(requestParameters, "passcode") print("SMPP form_response_passcode: {}".format(str(form_passcode))) if step == 1: print("SMPP Step 1 Password Authentication") credentials = self.identity.getCredentials() user_name = credentials.getUsername() user_password = credentials.getPassword() logged_in = False if StringHelper.isNotEmptyString( user_name) and StringHelper.isNotEmptyString( user_password): logged_in = authenticationService.authenticate( user_name, user_password) if not logged_in: return False # Get the Person's number and generate a code foundUser = None try: foundUser = authenticationService.getAuthenticatedUser() except: print("SMPP Error retrieving user {} from LDAP".format( user_name)) return False mobile_number = None try: isVerified = foundUser.getAttribute("phoneNumberVerified") if isVerified: mobile_number = foundUser.getAttribute("employeeNumber") if not mobile_number: mobile_number = foundUser.getAttribute("mobile") if not mobile_number: mobile_number = foundUser.getAttribute("telephoneNumber") if not mobile_number: facesMessages.add( FacesMessage.SEVERITY_ERROR, "Failed to determine mobile phone number") print("SMPP Error finding mobile number for user '{}'". format(user_name)) return False except Exception as e: facesMessages.add(FacesMessage.SEVERITY_ERROR, "Failed to determine mobile phone number") print("SMPP Error finding mobile number for {}: {}".format( user_name, e)) return False # Generate Random six digit code code = random.randint(100000, 999999) # Get code and save it in LDAP temporarily with special session entry self.identity.setWorkingParameter("code", code) self.identity.setWorkingParameter("mobile_number", mobile_number) self.identity.getSessionId().getSessionAttributes().put( "mobile_number", mobile_number) if not self.sendMessage(mobile_number, str(code)): facesMessages.add(FacesMessage.SEVERITY_ERROR, "Failed to send message to mobile phone") return False return True elif step == 2: # Retrieve the session attribute print("SMPP Step 2 SMS/OTP Authentication") code = session_attributes.get("code") print("SMPP Code: {}".format(str(code))) if code is None: print("SMPP Failed to find previously sent code") return False if form_passcode is None: print("SMPP Passcode is empty") return False if len(form_passcode) != 6: print("SMPP Passcode from response is not 6 digits: {}".format( form_passcode)) return False if form_passcode == code: print("SMPP SUCCESS! User entered the same code!") return True print("SMPP failed, user entered the wrong code! {} != {}".format( form_passcode, code)) facesMessages.add(facesMessage.SEVERITY_ERROR, "Incorrect SMS code, please try again.") return False print("SMPP ERROR: step param not found or != (1|2)") return False def prepareForStep(self, configurationAttributes, requestParameters, step): if step == 1: print("SMPP Prepare for Step 1") return True elif step == 2: print("SMPP Prepare for Step 2") return True return False def getExtraParametersForStep(self, configurationAttributes, step): if step == 2: return Arrays.asList("code") return None def getCountAuthenticationSteps(self, configurationAttributes): return 2 def getPageForStep(self, configurationAttributes, step): if step == 2: return "/auth/otp_sms/otp_sms.xhtml" return "" def getNextStep(self, configurationAttributes, requestParameters, step): return -1 def getLogoutExternalUrl(self, configurationAttributes, requestParameters): print "Get external logout URL call" return None def logout(self, configurationAttributes, requestParameters): return True def sendMessage(self, number, code): status = False session = SMPPSession() session.setTransactionTimer(10000) # We only handle international destination number reformatting. # All others may vary by configuration decisions taken on SMPP # server side which we have no clue about. if self.DST_ADDR_TON == TypeOfNumber.INTERNATIONAL and number.startswith( "+"): number = number[1:] try: print("SMPP Connecting") reference_id = session.connectAndBind( self.SMPP_SERVER, self.SMPP_PORT, BindParameter(BindType.BIND_TX, self.SYSTEM_ID, self.PASSWORD, None, self.SRC_ADDR_TON, self.SRC_ADDR_NPI, None)) print("SMPP Connected to server with system id {}".format( reference_id)) try: message_id = session.submitShortMessage( "CMT", self.SRC_ADDR_TON, self.SRC_ADDR_NPI, self.SRC_ADDR, self.DST_ADDR_TON, self.DST_ADDR_NPI, number, ESMClass(), 0, self.PRIORITY_FLAG, self.TIME_FORMATTER.format(Date()), None, RegisteredDelivery(SMSCDeliveryReceipt.DEFAULT), 0, GeneralDataCoding(self.DATA_CODING_ALPHABET, self.DATA_CODING_MESSAGE_CLASS, False), 0, code) print( "SMPP Message '{}' sent to #{} with message id {}".format( code, number, message_id)) status = True except PDUException as e: print("SMPP Invalid PDU parameter: {}".format(e)) except ResponseTimeoutException as e: print("SMPP Response timeout: {}".format(e)) except InvalidResponseException as e: print("SMPP Receive invalid response: {}".format(e)) except NegativeResponseException as e: print("SMPP Receive negative response: {}".format(e)) except IOException as e: print("SMPP IO error occured: {}".format(e)) finally: session.unbindAndClose() except IOException as e: print("SMPP Failed connect and bind to host: {}".format(e)) return status