iro/anbieter/smstrade.py
branchdevel
changeset 172 adfe245c377d
parent 171 5619596a0053
child 173 912ef3e070b0
equal deleted inserted replaced
171:5619596a0053 172:adfe245c377d
     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 sipgate import  NoValidStatusCode
       
    17 from telnumber import telnumber, InvalidTel
       
    18 import ConfigParser
       
    19 import urllib, httplib
       
    20 from httplib import socket
       
    21 
       
    22 import logging
       
    23 logger=logging.getLogger("smstrade")
       
    24 
       
    25 class UnknownStatusCode(Exception):
       
    26     def __init__(self,code):
       
    27         self.code=code
       
    28 
       
    29     def __str__(self):
       
    30         return "StatusCode %i is unknown"%self.code
       
    31 
       
    32 
       
    33 class StatusCode:
       
    34      statusCodes = {10 : "Empfaengernummer nicht korrekt",
       
    35             20 : "Absenderkennung nicht korrekt",
       
    36             30 : "Nachrichtentext nicht korrekt",
       
    37             31 : "Messagetyp nicht korrekt",
       
    38             40 : "SMS Route nicht korrekt",
       
    39             50 : "Identifikation fehlgeschlagen",
       
    40             60 : "nicht genuegend Guthaben",
       
    41             70 : "Netz wird von Route nicht abgedeckt",
       
    42             71 : "Feature nicht ueber diese Route moeglich",
       
    43             80 : "Uebergabe an SMS-C fehlgeschlagen",
       
    44             90 : "Versand nicht moeglich",
       
    45             100 : "SMS wurde versendet",
       
    46             999 : "SMS wird zeitversetzt verschickt"}
       
    47 
       
    48      def __init__(self,code):
       
    49         if code in self.statusCodes.keys():
       
    50             self.code=code
       
    51         else:
       
    52             raise UnknownStatusCode(code)
       
    53      
       
    54      def __str__(self):
       
    55         try:
       
    56             return self.statusCodes[self.code]
       
    57         except IndexError:
       
    58             raise UnknownStatusCode(self.code)
       
    59 
       
    60      def __int__(self):
       
    61         if not self.code in self.statusCodes.keys():
       
    62             raise UnknownStatusCode(self.code)
       
    63         return self.code
       
    64 
       
    65 
       
    66 
       
    67 
       
    68 class smstrade(anbieter):
       
    69     """
       
    70     s. auch http://kundencenter.smstrade.de/sites/smstrade.de.kundencenter/__pdf/SMS-Gateway_HTTP_API_v2.pdf
       
    71     """
       
    72     section="smstrade"
       
    73     url="https://gateway.smstrade.de"
       
    74     def __init__(self):       
       
    75         self.domain = "smstrade.de" # website of the sms service
       
    76         self.gateway = "gateway.smstrade.de" # gateway where the request will be sent
       
    77         self.gatewayPort = 80 # port of the gateway
       
    78         self.script = "/"  # full path to the script that will handle the request
       
    79         self.method = "POST" # method that will be used. Currently only POST is supported
       
    80 
       
    81     def read_basic_config(self, filenames):
       
    82         """Read basic options from the config file"""
       
    83         cp = ConfigParser.ConfigParser()
       
    84         cp.read(filenames)
       
    85         self.key=cp.get(self.section, 'key')
       
    86         self.route=cp.get(self.section, 'route')
       
    87         self.from_=cp.get(self.section, 'from')
       
    88         self.debug=cp.get(self.section, 'debug')
       
    89 
       
    90     def sendSMS(self,sms,recipients):
       
    91         """send SMS with $sms to $recipients"""
       
    92         logger.debug('smstrade.sendSMS(%s,%s)'%(sms,  str(recipients)))
       
    93         sended = []
       
    94         route = unicode(self.route)
       
    95         message = sms.content
       
    96         timestamp = None
       
    97         for recipient in recipients:
       
    98             try:
       
    99                 tel = telnumber(recipient)                
       
   100                 if tel in sended:                                             #only send message once per recipient
       
   101                     continue
       
   102                 sended.append(tel)	
       
   103                 to ='00'+tel.land+tel.number
       
   104                 if tel.land == '49':
       
   105                     route=unicode("basic")
       
   106                 else:
       
   107                     route=unicode("economy")
       
   108                 smsSendStatus = self.__send(route, to, message, timestamp)	
       
   109                 logger.info('smstrade._send(...)=%i(%s)'%(int(smsSendStatus),str(smsSendStatus)))
       
   110                 if int(smsSendStatus) in(100, 999):
       
   111                     self.updateStatus(arranged=recipient)
       
   112                 else:
       
   113                     self.updateStatus(failed=recipient)
       
   114             except (InvalidTel,NoValidStatusCode,InternetConnectionError):
       
   115                 self.updateStatus(failed=recipient)
       
   116 
       
   117     def __send(self, route, to, message,  timestamp=None):
       
   118         """ This function is the main part of the request to the sms service.    
       
   119         The function has to return a unicode formated string that will represent the answer of the sms service
       
   120         to the request."""
       
   121         logger.debug('smstrade._send(%s,%s,%s,%s)'%( route, to, message, timestamp))
       
   122         parameters= {"key": self.key,
       
   123                 "route": route,
       
   124                 "to": to,
       
   125                 "message": message,
       
   126                 "charset":"utf-8", 
       
   127                 "debug": self.debug,
       
   128                 }
       
   129         
       
   130         if self.from_ is not None:
       
   131             parameters["from"] = self.from_
       
   132         
       
   133         if timestamp is not None:
       
   134             parameters["senddate"] = unicode(timestamp)
       
   135 
       
   136         parameters["concat_sms"] = "1" if len(message) > 160 else "0"
       
   137         params = "&".join( ["%s=%s" % (urllib.quote(k),urllib.quote(v.encode("utf-8"))) for (k, v) in parameters.items()])
       
   138         logger.debug('smstrade._send-parameters:%s\n\t->%s'%(str(parameters), str(params)) )
       
   139         headers = {"Content-type": "application/x-www-form-urlencoded",
       
   140             "Accept": "text/plain"}
       
   141         conn = httplib.HTTPConnection("%s:%i" % (self.gateway, self.gatewayPort))
       
   142         try:
       
   143             conn.request(self.method, self.script, params, headers)
       
   144             response = conn.getresponse()
       
   145             data = response.read()
       
   146         except socket.gaierror:
       
   147             raise InternetConnectionError("%s:%i" % (self.gateway, self.gatewayPort))
       
   148         finally:
       
   149             conn.close()
       
   150             
       
   151         try:
       
   152             return StatusCode(int(data))
       
   153         except UnknownStatusCode:
       
   154             # this happens if the sms will be send delayed
       
   155             return StatusCode(999)
       
   156 
       
   157     def updateStatus(self, arranged=None, failed=None):
       
   158         """is a function that is called, if a new SMS/FAX was send
       
   159         -arranged is non None, if SMS/FAX was sended successfully
       
   160         -failed is non None, if SMS/FAX sending failed
       
   161         the content will be the recipent"""
       
   162         pass
       
   163 
       
   164 class InternetConnectionError(Exception):
       
   165 	def __init__(self, url):
       
   166 		self.url = url
       
   167 
       
   168 	def __str__(self):
       
   169 		return "InternetConnectionError: It is not possible to open 'http://%s'. Please check your connection to the Internet!" % self.url