iro/anbieter/smstrade.py
changeset 9 4c5f1cf088f6
parent 1 18918fbc397c
child 15 c04a21066aad
equal deleted inserted replaced
8:cec27aeb7e69 9:4c5f1cf088f6
    11 #You should have received a copy of the GNU General Public License
    11 #You should have received a copy of the GNU General Public License
    12 #along with this program; if not, see <http://www.gnu.org/licenses/>.
    12 #along with this program; if not, see <http://www.gnu.org/licenses/>.
    13 
    13 
    14 
    14 
    15 from anbieter import anbieter
    15 from anbieter import anbieter
       
    16 from sipgate import  NoValidStatusCode
    16 from telnumber import telnumber, NotATelNumber
    17 from telnumber import telnumber, NotATelNumber
    17 import ConfigParser
    18 import ConfigParser
    18 import xmlrpclib
    19 import xmlrpclib
    19 import base64
    20 import base64
       
    21 import urllib, httplib
    20 
    22 
    21 class smstrade(anbieter):
    23 class smstrade(anbieter):
    22 	"""
    24     """
    23 	s. auch http://kundencenter.smstrade.de/sites/smstrade.de.kundencenter/__pdf/SMS-Gateway_HTTP_API_v2.pdf
    25     s. auch http://kundencenter.smstrade.de/sites/smstrade.de.kundencenter/__pdf/SMS-Gateway_HTTP_API_v2.pdf
    24 	"""
    26     """
    25 	section="smstrade"
    27     section="smstrade"
    26 	url="https://gateway.smstrade.de"
    28     url="https://gateway.smstrade.de"
    27 	def __init__(self):       
    29     def __init__(self):       
    28 		self.domain = "smstrade.de" # website of the sms service
    30         self.domain = "smstrade.de" # website of the sms service
    29 		self.gateway = "gateway.smstrade.de" # gateway where the request will be sent
    31         self.gateway = "gateway.smstrade.de" # gateway where the request will be sent
    30 		self.gatewayPort = 80 # port of the gateway
    32         self.gatewayPort = 80 # port of the gateway
    31 		self.script = "/"  # full path to the script that will handle the request
    33         self.script = "/"  # full path to the script that will handle the request
    32 		self.method = "POST" # method that will be used. Currently only POST is supported
    34         self.method = "POST" # method that will be used. Currently only POST is supported
    33 
    35 
    34 		self.maxMessageLength = None # maximum length of message; None if should not be set
    36         self.maxMessageLength = None # maximum length of message; None if should not be set
    35 		self.smsCanBeSendDelayed = True # True if sms can be sent delayed by the sms service. Otherwise False
    37         self.smsCanBeSendDelayed = True # True if sms can be sent delayed by the sms service. Otherwise False
    36 		self.senderRe = r"^.{0,11}|[0-9]{0,15}" # RegEx for the sender-input-field
    38         self.senderRe = r"^.{0,11}|[0-9]{0,15}" # RegEx for the sender-input-field
    37 
    39 
    38 		self.routes = ("basicplus", "economy", "gold", "direct") # possible routes that can be used
    40         self.routes = ("basicplus", "economy", "gold", "direct") # possible routes that can be used
    39 		self.routesWithSourceIdentifier = ("gold", "direct") # routes where a sender can be defined
    41         self.routesWithSourceIdentifier = ("gold", "direct") # routes where a sender can be defined
    40 
    42 
    41 # statusCodes that the sms service returns on requests
    43         # statusCodes that the sms service returns on requests
    42 		self.statusCodes = {10 : "Empfaengernummer nicht korrekt",
    44         self.statusCodes = {10 : "Empfaengernummer nicht korrekt",
    43 			20 : "Absenderkennung nicht korrekt",
    45             20 : "Absenderkennung nicht korrekt",
    44 			30 : "Nachrichtentext nicht korrekt",
    46             30 : "Nachrichtentext nicht korrekt",
    45 			31 : "Messagetyp nicht korrekt",
    47             31 : "Messagetyp nicht korrekt",
    46 			40 : "SMS Route nicht korrekt",
    48             40 : "SMS Route nicht korrekt",
    47 			50 : "Identifikation fehlgeschlagen",
    49             50 : "Identifikation fehlgeschlagen",
    48 			60 : "nicht genuegend Guthaben",
    50             60 : "nicht genuegend Guthaben",
    49 			70 : "Netz wird von Route nicht abgedeckt",
    51             70 : "Netz wird von Route nicht abgedeckt",
    50 			71 : "Feature nicht ueber diese Route moeglich",
    52             71 : "Feature nicht ueber diese Route moeglich",
    51 			80 : "Uebergabe an SMS-C fehlgeschlagen",
    53             80 : "Uebergabe an SMS-C fehlgeschlagen",
    52 			90 : "Versand nicht moeglich",
    54             90 : "Versand nicht moeglich",
    53 			100 : "SMS wurde versendet",
    55             100 : "SMS wurde versendet",
    54 			999 : "SMS wird zeitversetzt verschickt"}
    56             999 : "SMS wird zeitversetzt verschickt"}
    55 
    57 
    56 		self.parameters = {} # don't write anything into this dict! Don't delete it!                   
    58         self.parameters = {} # don't write anything into this dict! Don't delete it!                   
    57 
    59 
    58 	def read_basic_config(self,filename):
    60     def read_basic_config(self,filename):
    59 		"""Read basic options from the config file"""
    61         """Read basic options from the config file"""
    60 		cp = ConfigParser.ConfigParser()
    62         cp = ConfigParser.ConfigParser()
    61 		cp.read([filename])
    63         cp.read([filename])
    62 		self.key=cp.get(self.section, 'key')
    64         self.key=cp.get(self.section, 'key')
    63 		self.route=cp.get(self.section, 'route')
    65         self.route=cp.get(self.section, 'route')
    64 		self.from_=cp.get(self.section, 'from')
    66         self.from_=cp.get(self.section, 'from')
    65 		self.debug=cp.get(self.section, 'debug')
    67         self.debug=cp.get(self.section, 'debug')
    66 
    68 
    67 def sendSMS(self,sms,recipients):
    69     def sendSMS(self,sms,recipients):
    68 	"""send SMS with $sms to $recipients"""
    70         """send SMS with $sms to $recipients"""
    69 	sended = []
    71         sended = []
    70 	key = self.key
    72         key = self.key
    71 	route = unicode(self.route)
    73         route = unicode(self.route)
    72 	message = unicode(sms.content.toPlainText())
    74         message = unicode(sms.content)
    73 	from_ = unicode(self.from_)
    75         from_ = unicode(self.from_)
    74 	timestamp = None
    76         timestamp = None
    75 	for recipient in recipients:
    77         for recipient in recipients:
    76 		try:
    78             try:
    77 			tel = telnumber(recipient)                
    79                 tel = telnumber(recipient)                
    78 			if tel in sended:                                                                           #only send message once per recipient
    80                 if tel in sended:                                                                           #only send message once per recipient
    79 				continue
    81                     continue
    80 			sended.append(tel)	
    82                 sended.append(tel)	
    81 			to = unicode((tel.number)).strip()						                
    83                 to = unicode((tel.number)).strip()						                
    82 			smsSendStatus = self.__sendSms( 
    84                 code, smsSendStatus = self.__send(key, route, to, message, from_, timestamp)	
    83 						key, route, to, message, from_, timestamp)									            
    85                 if code in(100, 999):
    84 		except (NotATelNumber,NoValidStatusCode,InternetConnectionError):
    86                     self.updateStatus(arranged=recipient)
    85 			self.updateStatus(failed=recipient)
    87             except (NotATelNumber,NoValidStatusCode,InternetConnectionError):
       
    88                 self.updateStatus(failed=recipient)
    86 
    89 
    87 def __send(self, key, route, to, message, from_=None, timestamp=None):
    90     def __send(self, key, route, to, message, from_=None, timestamp=None):
    88 	""" This function is the main part of the request to the sms service.    
    91         """ This function is the main part of the request to the sms service.    
    89 	The function has to return a unicode formated string that will represent the answer of the sms service
    92         The function has to return a unicode formated string that will represent the answer of the sms service
    90 	to the request."""
    93         to the request."""
    91 	self.parameters["key"] = key        
    94         self.parameters["key"] = key        
    92 	self.parameters["route"] = route
    95         self.parameters["route"] = route
    93 	self.parameters["to"] = to
    96         self.parameters["to"] = to
    94 	self.parameters["message"] = message
    97         self.parameters["message"] = message
    95 	self.parameters["debug"] = self.debug				
    98         self.parameters["debug"] = self.debug				
    96 	
    99         
    97 	if from_ is not None:
   100         if from_ is not None:
    98 		self.parameters["from"] = from_
   101             self.parameters["from"] = from_
    99 	else:
   102         else:
   100 		if "from" in self.parameters.keys():
   103             if "from" in self.parameters.keys():
   101 			del(self.parameters["from"])
   104                 del(self.parameters["from"])
   102 	
   105         
   103 	if timestamp is not None:
   106         if timestamp is not None:
   104 		self.parameters["senddate"] = unicode(timestamp)
   107             self.parameters["senddate"] = unicode(timestamp)
   105 	else:
   108         else:
   106 		if "senddate" in self.parameters.keys():
   109             if "senddate" in self.parameters.keys():
   107 			del(self.parameters["senddate"])
   110                 del(self.parameters["senddate"])
   108 
   111 
   109 	self.parameters["concat_sms"] = "1" if len(message) > 160 else "0"
   112         self.parameters["concat_sms"] = "1" if len(message) > 160 else "0"
   110 
   113 
   111 	params = urllib.urlencode(dict([k, v.encode('iso-8859-1')] for k, v in self.parameters.items()))
   114         params = urllib.urlencode(dict([k, v.encode('iso-8859-1')] for k, v in self.parameters.items()))
   112 	headers = {"Content-type": "application/x-www-form-urlencoded",
   115         headers = {"Content-type": "application/x-www-form-urlencoded",
   113 		"Accept": "text/plain"}
   116             "Accept": "text/plain"}
   114 	conn = httplib.HTTPConnection("%s:%i" % (self.gateway, self.gatewayPort))
   117         conn = httplib.HTTPConnection("%s:%i" % (self.gateway, self.gatewayPort))
   115 	try:
   118         try:
   116 		conn.request(self.method, self.script, params, headers)
   119             conn.request(self.method, self.script, params, headers)
   117 		response = conn.getresponse()
   120             response = conn.getresponse()
   118 
   121 
   119 		data = response.read()
   122             data = response.read()
   120 	except socket.gaierror:
   123         except socket.gaierror:
   121 		raise InternetConnectionError("%s:%i" % (self.gateway, self.gatewayPort))
   124             raise InternetConnectionError("%s:%i" % (self.gateway, self.gatewayPort))
   122 	else:
   125         else:
   123 		conn.close()
   126             conn.close()
   124 
   127 
   125 	try:
   128         try:
   126 		return self.statusCodes[int(data)]
   129             return int(data), self.statusCodes[int(data)]
   127 	except ValueError:
   130         except ValueError:
   128 		# this happens if the sms will be send delayed
   131             # this happens if the sms will be send delayed
   129 		return self.statusCodes[999]
   132             return 999, self.statusCodes[999]
   130 
   133 
   131 def updateStatus(self, arranged=None, failed=None):
   134     def updateStatus(self, arranged=None, failed=None):
   132 	"""is a function that is called, if a new SMS/FAX was send
   135         """is a function that is called, if a new SMS/FAX was send
   133 	-arranged is non None, if SMS/FAX was sended successfully
   136         -arranged is non None, if SMS/FAX was sended successfully
   134 	-failed is non None, if SMS/FAX sending failed
   137         -failed is non None, if SMS/FAX sending failed
   135 	the content will be the recipent"""
   138         the content will be the recipent"""
   136 	pass
   139         pass
   137 
   140 
   138 class InternetConnectionError(Exception):
   141 class InternetConnectionError(Exception):
   139 	def __init__(self, url):
   142 	def __init__(self, url):
   140 		self.url = url
   143 		self.url = url
   141 
   144