iro/anbieter/smstrade.py
changeset 1 18918fbc397c
child 9 4c5f1cf088f6
equal deleted inserted replaced
0:a3b6e531f0d2 1:18918fbc397c
       
     1 # -*- coding: utf-8 -*-
       
     2 #Copyright (C) 2009  Georg Bischoff
       
     3 
       
     4 #This program is free software; you can redistribute it and/or modify it under the terms
       
     5 #of the GNU General Public License as published by the Free Software Foundation;
       
     6 #either version 3 of the License, or any later version.
       
     7 #This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
       
     8 #without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
       
     9 #See the GNU General Public License for more details.
       
    10 
       
    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/>.
       
    13 
       
    14 
       
    15 from anbieter import anbieter
       
    16 from telnumber import telnumber, NotATelNumber
       
    17 import ConfigParser
       
    18 import xmlrpclib
       
    19 import base64
       
    20 
       
    21 class smstrade(anbieter):
       
    22 	"""
       
    23 	s. auch http://kundencenter.smstrade.de/sites/smstrade.de.kundencenter/__pdf/SMS-Gateway_HTTP_API_v2.pdf
       
    24 	"""
       
    25 	section="smstrade"
       
    26 	url="https://gateway.smstrade.de"
       
    27 	def __init__(self):       
       
    28 		self.domain = "smstrade.de" # website of the sms service
       
    29 		self.gateway = "gateway.smstrade.de" # gateway where the request will be sent
       
    30 		self.gatewayPort = 80 # port of the gateway
       
    31 		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
       
    33 
       
    34 		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
       
    36 		self.senderRe = r"^.{0,11}|[0-9]{0,15}" # RegEx for the sender-input-field
       
    37 
       
    38 		self.routes = ("basicplus", "economy", "gold", "direct") # possible routes that can be used
       
    39 		self.routesWithSourceIdentifier = ("gold", "direct") # routes where a sender can be defined
       
    40 
       
    41 # statusCodes that the sms service returns on requests
       
    42 		self.statusCodes = {10 : "Empfaengernummer nicht korrekt",
       
    43 			20 : "Absenderkennung nicht korrekt",
       
    44 			30 : "Nachrichtentext nicht korrekt",
       
    45 			31 : "Messagetyp nicht korrekt",
       
    46 			40 : "SMS Route nicht korrekt",
       
    47 			50 : "Identifikation fehlgeschlagen",
       
    48 			60 : "nicht genuegend Guthaben",
       
    49 			70 : "Netz wird von Route nicht abgedeckt",
       
    50 			71 : "Feature nicht ueber diese Route moeglich",
       
    51 			80 : "Uebergabe an SMS-C fehlgeschlagen",
       
    52 			90 : "Versand nicht moeglich",
       
    53 			100 : "SMS wurde versendet",
       
    54 			999 : "SMS wird zeitversetzt verschickt"}
       
    55 
       
    56 		self.parameters = {} # don't write anything into this dict! Don't delete it!                   
       
    57 
       
    58 	def read_basic_config(self,filename):
       
    59 		"""Read basic options from the config file"""
       
    60 		cp = ConfigParser.ConfigParser()
       
    61 		cp.read([filename])
       
    62 		self.key=cp.get(self.section, 'key')
       
    63 		self.route=cp.get(self.section, 'route')
       
    64 		self.from_=cp.get(self.section, 'from')
       
    65 		self.debug=cp.get(self.section, 'debug')
       
    66 
       
    67 def sendSMS(self,sms,recipients):
       
    68 	"""send SMS with $sms to $recipients"""
       
    69 	sended = []
       
    70 	key = self.key
       
    71 	route = unicode(self.route)
       
    72 	message = unicode(sms.content.toPlainText())
       
    73 	from_ = unicode(self.from_)
       
    74 	timestamp = None
       
    75 	for recipient in recipients:
       
    76 		try:
       
    77 			tel = telnumber(recipient)                
       
    78 			if tel in sended:                                                                           #only send message once per recipient
       
    79 				continue
       
    80 			sended.append(tel)	
       
    81 			to = unicode((tel.number)).strip()						                
       
    82 			smsSendStatus = self.__sendSms( 
       
    83 						key, route, to, message, from_, timestamp)									            
       
    84 		except (NotATelNumber,NoValidStatusCode,InternetConnectionError):
       
    85 			self.updateStatus(failed=recipient)
       
    86 
       
    87 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.    
       
    89 	The function has to return a unicode formated string that will represent the answer of the sms service
       
    90 	to the request."""
       
    91 	self.parameters["key"] = key        
       
    92 	self.parameters["route"] = route
       
    93 	self.parameters["to"] = to
       
    94 	self.parameters["message"] = message
       
    95 	self.parameters["debug"] = self.debug				
       
    96 	
       
    97 	if from_ is not None:
       
    98 		self.parameters["from"] = from_
       
    99 	else:
       
   100 		if "from" in self.parameters.keys():
       
   101 			del(self.parameters["from"])
       
   102 	
       
   103 	if timestamp is not None:
       
   104 		self.parameters["senddate"] = unicode(timestamp)
       
   105 	else:
       
   106 		if "senddate" in self.parameters.keys():
       
   107 			del(self.parameters["senddate"])
       
   108 
       
   109 	self.parameters["concat_sms"] = "1" if len(message) > 160 else "0"
       
   110 
       
   111 	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",
       
   113 		"Accept": "text/plain"}
       
   114 	conn = httplib.HTTPConnection("%s:%i" % (self.gateway, self.gatewayPort))
       
   115 	try:
       
   116 		conn.request(self.method, self.script, params, headers)
       
   117 		response = conn.getresponse()
       
   118 
       
   119 		data = response.read()
       
   120 	except socket.gaierror:
       
   121 		raise InternetConnectionError("%s:%i" % (self.gateway, self.gatewayPort))
       
   122 	else:
       
   123 		conn.close()
       
   124 
       
   125 	try:
       
   126 		return self.statusCodes[int(data)]
       
   127 	except ValueError:
       
   128 		# this happens if the sms will be send delayed
       
   129 		return self.statusCodes[999]
       
   130 
       
   131 def updateStatus(self, arranged=None, failed=None):
       
   132 	"""is a function that is called, if a new SMS/FAX was send
       
   133 	-arranged is non None, if SMS/FAX was sended successfully
       
   134 	-failed is non None, if SMS/FAX sending failed
       
   135 	the content will be the recipent"""
       
   136 	pass
       
   137 
       
   138 class InternetConnectionError(Exception):
       
   139 	def __init__(self, url):
       
   140 		self.url = url
       
   141 
       
   142 	def __str__(self):
       
   143 		return "InternetConnectionError: It is not possible to open 'http://%s'. Please check your connection to the Internet!" % self.url