def send(self, msg, *args, **kwargs): phone_number = clean_phone_number(msg.phone_number) config = self.config client = boto3.client('pinpoint', region_name=config.region, aws_access_key_id=config.access_key, aws_secret_access_key=config.secret_access_key) message_request = { 'Addresses': { phone_number: { 'ChannelType': 'SMS' } }, 'MessageConfiguration': { 'SMSMessage': { 'Body': msg.text, 'MessageType': MESSAGE_TYPE, 'OriginationNumber': config.reply_to_phone_number } } } try: response = client.send_messages(ApplicationId=config.project_id, MessageRequest=message_request) msg.backend_message_id = response['MessageResponse']['Result'][ phone_number]['MessageId'] except ClientError as e: msg.set_gateway_error(e.response['Error']['Message']) return
def send(self, msg, *args, **kwargs): if self.additional_params is not None: params = self.additional_params.copy() else: params = {} phone_number = msg.phone_number if self.include_plus: phone_number = clean_phone_number(phone_number) else: phone_number = strip_plus(phone_number) try: text = msg.text.encode("iso-8859-1") except UnicodeEncodeError: text = msg.text.encode("utf-8") params[self.message_param] = text params[self.number_param] = phone_number url_params = urlencode(params) try: if self.method == "GET": response = urlopen("%s?%s" % (self.url, url_params), timeout=settings.SMS_GATEWAY_TIMEOUT).read() else: response = urlopen(self.url, url_params, timeout=settings.SMS_GATEWAY_TIMEOUT).read() except Exception as e: msg = "Error sending message from backend: '{}'\n\n{}".format(self.name, str(e)) raise BackendProcessingException(msg), None, sys.exc_info()[2]
def incoming(phone_number, text, backend_api, timestamp=None, domain_scope=None, backend_message_id=None, delay=True): """ entry point for incoming sms phone_number - originating phone number text - message content backend_api - backend API ID of receiving sms backend timestamp - message received timestamp; defaults to now (UTC) domain_scope - if present, only messages from phone numbers that can be definitively linked to this domain will be processed; others will be dropped (useful to provide security when simulating incoming sms) """ # Log message in message log phone_number = clean_phone_number(phone_number) msg = SMSLog( phone_number = phone_number, direction = INCOMING, date = timestamp or datetime.utcnow(), text = text, domain_scope = domain_scope, backend_api = backend_api, backend_message_id = backend_message_id, ) if settings.SMS_QUEUE_ENABLED: msg.processed = False msg.datetime_to_process = datetime.utcnow() msg.queued_timestamp = msg.datetime_to_process msg.save() enqueue_directly(msg) else: msg.processed = True msg.save() process_incoming(msg, delay=delay) return msg
def send(self, message, delay=True, *args, **kwargs): """ Send an outbound message using the Unicel API """ phone_number = clean_phone_number(message.phone_number).replace("+", "") params = [(OutboundParams.DESTINATION, phone_number), (OutboundParams.USERNAME, self.username), (OutboundParams.PASSWORD, self.password), (OutboundParams.SENDER, self.sender)] try: text = str(message.text) # it's ascii params.append((OutboundParams.MESSAGE, text)) except UnicodeEncodeError: params.extend(UNICODE_PARAMS) encoded = message.text.encode("utf_16_be").encode("hex").upper() params.append((OutboundParams.MESSAGE, encoded)) try: data = urlopen('%s?%s' % (OUTBOUND_URLBASE, urlencode(params))).read() except Exception: data = None create_billable_for_sms(message, UnicelBackend.get_api_id(), delay=delay, response=data) return data
def send_sms(domain, contact, phone_number, text, metadata=None): """ Sends an outbound SMS. Returns false if it fails. """ if phone_number is None: return False if isinstance(phone_number, int) or isinstance(phone_number, long): phone_number = str(phone_number) phone_number = clean_phone_number(phone_number) msg = get_sms_class()( domain=domain, phone_number=phone_number, direction=OUTGOING, date=get_utcnow(), backend_id=None, location_id=get_location_id_by_contact(domain, contact), text = text ) if contact: msg.couch_recipient = contact.get_id msg.couch_recipient_doc_type = contact.doc_type add_msg_tags(msg, metadata) return queue_outgoing_sms(msg)
def send_sms(domain, id, phone_number, text): """ Sends an outbound SMS. Returns false if it fails. """ if phone_number is None: return False if isinstance(phone_number, int) or isinstance(phone_number, long): phone_number = str(phone_number) logging.debug('Sending message: %s' % text) phone_number = clean_phone_number(phone_number) msg = SMSLog(domain=domain, couch_recipient=id, couch_recipient_doc_type="CouchUser", phone_number=phone_number, direction=OUTGOING, date = datetime.utcnow(), text = text) try: api = get_backend_api(msg) try: msg.backend_api = api.API_ID except Exception: pass api.send(msg) msg.save() return True except Exception: logging.exception("Problem sending SMS to %s" % phone_number) return False
def post(self, request, *args, **kwargs): context = self.get_context_data(**kwargs) reminder = request.POST.get('reminder') phone_number = context.get('phone_number') if reminder and phone_number: phone_number = clean_phone_number(phone_number) v = VerifiedNumber.by_phone(phone_number, include_pending=True) if v and v.verified: user = v.owner if reminder == 'first_soh': first_soh_process_user(user, test=True) elif reminder == 'second_soh': now = datetime.datetime.utcnow() date = now - datetime.timedelta(days=5) second_soh_process_user(user, date, test=True) elif reminder == 'third_soh': third_soh_process_users_and_facilities([user], [user.location.sql_location], test=True) elif reminder == 'stockout': stockout_process_user(user, test=True) elif reminder == 'rrirv': rrirv_process_user(user, test=True) elif reminder == 'visit_website': visit_website_process_user(user, test=True) messages.success(request, "Reminder was sent successfully") return self.get(request, *args, **kwargs)
def send_sms(domain, contact, phone_number, text, metadata=None): """ Sends an outbound SMS. Returns false if it fails. """ if phone_number is None: return False if isinstance(phone_number, int) or isinstance(phone_number, long): phone_number = str(phone_number) phone_number = clean_phone_number(phone_number) msg = SMSLog( domain=domain, phone_number=phone_number, direction=OUTGOING, date = datetime.utcnow(), backend_id=None, text = text ) if contact: msg.couch_recipient = contact._id msg.couch_recipient_doc_type = contact.doc_type add_msg_tags(msg, metadata) def onerror(): logging.exception("Problem sending SMS to %s" % phone_number) return queue_outgoing_sms(msg, onerror=onerror)
def send(self, msg, *args, **kwargs): if self.additional_params is not None: params = self.additional_params.copy() else: params = {} phone_number = msg.phone_number if self.include_plus: phone_number = clean_phone_number(phone_number) else: phone_number = strip_plus(phone_number) try: text = msg.text.encode("iso-8859-1") except UnicodeEncodeError: text = msg.text.encode("utf-8") params[self.message_param] = text params[self.number_param] = phone_number url_params = urlencode(params) if self.method == "GET": response = urlopen("%s?%s" % (self.url, url_params), timeout=settings.SMS_GATEWAY_TIMEOUT).read() else: response = urlopen(self.url, url_params, timeout=settings.SMS_GATEWAY_TIMEOUT).read()
def create(cls, message_log, multipart_count=1): phone_number = clean_phone_number(message_log.phone_number) direction = message_log.direction domain = message_log.domain log_id = message_log.couch_id billable = cls( log_id=log_id, phone_number=phone_number, direction=direction, date_sent=message_log.date, domain=domain, ) gateway_charge_info = cls._get_gateway_fee( message_log.backend_api, message_log.backend_id, phone_number, direction, log_id, message_log.backend_message_id, domain ) billable.gateway_fee = gateway_charge_info.gateway_fee billable.gateway_fee_conversion_rate = gateway_charge_info.conversion_rate billable.direct_gateway_fee = gateway_charge_info.direct_gateway_fee billable.multipart_count = cls._get_multipart_count( message_log.backend_api, message_log.backend_id, message_log.backend_message_id, multipart_count ) billable.usage_fee = cls._get_usage_fee(domain, direction) if message_log.backend_api == SQLTestSMSBackend.get_api_id(): billable.is_valid = False billable.save() return billable
def send(self, msg, *args, **kwargs): try: text = msg.text.encode("iso-8859-1") except UnicodeEncodeError: text = msg.text.encode("utf-8") params = urlencode({ "phone_id" : str(self.phone_id), "to_number" : clean_phone_number(msg.phone_number), "content" : text, "message_type" : MESSAGE_TYPE_SMS, }) url = "https://api.telerivet.com/v1/projects/%s/messages/outgoing" % str(self.project_id) curl = pycurl.Curl() buf = StringIO.StringIO() curl.setopt(curl.URL, url) curl.setopt(curl.USERPWD, "%s:" % str(self.api_key)) curl.setopt(curl.WRITEFUNCTION, buf.write) curl.setopt(curl.POSTFIELDS, params) curl.setopt(curl.CAINFO, "%s/cacert.pem" % os.path.dirname(os.path.abspath(__file__))) curl.perform() curl.close() result = json.loads(buf.getvalue()) buf.close()
def create(cls, message_log, multipart_count=1): phone_number = clean_phone_number(message_log.phone_number) direction = message_log.direction domain = message_log.domain log_id = message_log.couch_id billable = cls( log_id=log_id, phone_number=phone_number, direction=direction, date_sent=message_log.date, domain=domain, ) gateway_charge_info = cls._get_gateway_fee( message_log.backend_api, message_log.backend_id, phone_number, direction, log_id, message_log.backend_message_id, domain) billable.gateway_fee = gateway_charge_info.gateway_fee billable.gateway_fee_conversion_rate = gateway_charge_info.conversion_rate billable.direct_gateway_fee = gateway_charge_info.direct_gateway_fee billable.multipart_count = gateway_charge_info.multipart_count or multipart_count billable.usage_fee = cls._get_usage_fee(domain, direction) if message_log.backend_api == SQLTestSMSBackend.get_api_id(): billable.is_valid = False billable.save() return billable
def send(self, msg, *args, **kwargs): if self.additional_params is not None: params = self.additional_params.copy() else: params = {} phone_number = msg.phone_number if self.include_plus: phone_number = clean_phone_number(phone_number) else: phone_number = strip_plus(phone_number) try: text = msg.text.encode("iso-8859-1") except UnicodeEncodeError: text = msg.text.encode("utf-8") params[self.message_param] = text params[self.number_param] = phone_number url_params = urlencode(params) try: if self.method == "GET": response = urlopen( "%s?%s" % (self.url, url_params), timeout=settings.SMS_GATEWAY_TIMEOUT).read() else: response = urlopen( self.url, url_params, timeout=settings.SMS_GATEWAY_TIMEOUT).read() except Exception as e: msg = "Error sending message from backend: '{}'\n\n{}".format( self.name, str(e)) raise BackendProcessingException(msg), None, sys.exc_info()[2]
def backend(self): from corehq.apps.sms.util import clean_phone_number if self.backend_id is not None and isinstance(self.backend_id, basestring) and self.backend_id.strip() != "": return MobileBackend.load_by_name(self.domain, self.backend_id) else: return MobileBackend.auto_load(clean_phone_number(self.phone_number), self.domain)
def send(self, message, delay=True, *args, **kwargs): """ Send an outbound message using the Unicel API """ phone_number = clean_phone_number(message.phone_number).replace( "+", "") params = [(OutboundParams.DESTINATION, phone_number), (OutboundParams.USERNAME, self.username), (OutboundParams.PASSWORD, self.password), (OutboundParams.SENDER, self.sender)] try: text = str(message.text) # it's ascii params.append((OutboundParams.MESSAGE, text)) except UnicodeEncodeError: params.extend(UNICODE_PARAMS) encoded = message.text.encode("utf_16_be").encode("hex").upper() params.append((OutboundParams.MESSAGE, encoded)) try: data = urlopen('%s?%s' % (OUTBOUND_URLBASE, urlencode(params)), timeout=settings.SMS_GATEWAY_TIMEOUT).read() except Exception: data = None return data
def send_sample_sms(self, data): request_token = data.get("request_token") if not self.get_cached_webhook_secret(request_token): return {"success": False, "unexpected_error": self.unexpected_error} outgoing_sms_form = TelerivetOutgoingSMSForm( {"api_key": data.get("api_key"), "project_id": data.get("project_id"), "phone_id": data.get("phone_id")} ) test_sms_form = TelerivetPhoneNumberForm({"test_phone_number": data.get("test_phone_number")}) # Be sure to call .is_valid() on both outgoing_sms_form_valid = outgoing_sms_form.is_valid() test_sms_form_valid = test_sms_form.is_valid() if not outgoing_sms_form_valid or not test_sms_form_valid: return { "success": False, "api_key_error": self.get_error_message(outgoing_sms_form, "api_key"), "project_id_error": self.get_error_message(outgoing_sms_form, "project_id"), "phone_id_error": self.get_error_message(outgoing_sms_form, "phone_id"), "test_phone_number_error": self.get_error_message(test_sms_form, "test_phone_number"), } tmp_backend = SQLTelerivetBackend() tmp_backend.set_extra_fields( api_key=outgoing_sms_form.cleaned_data.get("api_key"), project_id=outgoing_sms_form.cleaned_data.get("project_id"), phone_id=outgoing_sms_form.cleaned_data.get("phone_id"), ) sms = SMS( phone_number=clean_phone_number(test_sms_form.cleaned_data.get("test_phone_number")), text="This is a test SMS from CommCareHQ.", ) tmp_backend.send(sms) return {"success": True}
def send(message, delay=True): """ Send an outbound message using the Unicel API """ config = _config() phone_number = clean_phone_number(message.phone_number).replace("+", "") # these are shared regardless of API params = [(OutboundParams.DESTINATION, phone_number), (OutboundParams.USERNAME, config["username"]), (OutboundParams.PASSWORD, config["password"]), (OutboundParams.SENDER, config["sender"])] try: text = str(message.text) # it's ascii params.append((OutboundParams.MESSAGE, text)) except UnicodeEncodeError: params.extend(UNICODE_PARAMS) encoded = message.text.encode("utf_16_be").encode("hex").upper() params.append((OutboundParams.MESSAGE, encoded)) try: data = urlopen('%s?%s' % (OUTBOUND_URLBASE, urlencode(params))).read() except Exception: data = None message.save() create_billable_for_sms(message, API_ID, delay=delay, response=data) return data
def send_sms(domain, id, phone_number, text): """ Sends an outbound SMS. Returns false if it fails. """ if phone_number is None: return False if isinstance(phone_number, int) or isinstance(phone_number, long): phone_number = str(phone_number) logging.debug("Sending message: %s" % text) phone_number = clean_phone_number(phone_number) msg = SMSLog( domain=domain, couch_recipient=id, couch_recipient_doc_type="CouchUser", phone_number=phone_number, direction=OUTGOING, date=datetime.utcnow(), text=text, ) def onerror(): logging.exception("Problem sending SMS to %s" % phone_number) return send_message_via_backend(msg, onerror=onerror)
def backend(self): from corehq.apps.sms.util import clean_phone_number if self.backend_id is not None and isinstance( self.backend_id, basestring) and self.backend_id.strip() != "": return MobileBackend.load_by_name(self.domain, self.backend_id) else: return MobileBackend.auto_load( clean_phone_number(self.phone_number), self.domain)
def incoming(phone_number, text, backend_api, timestamp=None, domain_scope=None, delay=True): """ entry point for incoming sms phone_number - originating phone number text - message content backend_api - backend ID of receiving sms backend timestamp - message received timestamp; defaults to now (UTC) domain_scope - if present, only messages from phone numbers that can be definitively linked to this domain will be processed; others will be dropped (useful to provide security when simulating incoming sms) """ phone_number = clean_phone_number(phone_number) v = VerifiedNumber.by_phone(phone_number, include_pending=True) if domain_scope: # only process messages for phones known to be associated with this domain if v is None or v.domain != domain_scope: raise RuntimeError("attempted to simulate incoming sms from phone number not verified with this domain") # Log message in message log msg = SMSLog( phone_number=phone_number, direction=INCOMING, date=timestamp or datetime.utcnow(), text=text, backend_api=backend_api, ) if v is not None and v.verified: msg.couch_recipient_doc_type = v.owner_doc_type msg.couch_recipient = v.owner_id msg.domain = v.domain msg.save() create_billable_for_sms(msg, backend_api, delay=delay) if v is not None and v.verified: for h in settings.SMS_HANDLERS: try: handler = to_function(h) except: logging.exception("error loading sms handler: %s" % h) continue try: was_handled = handler(v, text) except: logging.exception("unhandled error in sms handler %s for message [%s]" % (h, text)) was_handled = False if was_handled: break else: if not process_sms_registration(msg): import verify verify.process_verification(phone_number, text) return msg
def send_verification(domain, user, phone_number): module = MobileBackend.auto_load(phone_number, domain).backend_module reply_phone = getattr(module, 'receive_phone_number', lambda: None)() message = OUTGOING % { 'name': user.username.split('@')[0], 'replyto': ' to %s' % util.clean_phone_number(reply_phone) if reply_phone else '', } api.send_sms(domain, user._id, phone_number, message)
def send(self, msg, orig_phone_number=None, *args, **kwargs): config = self.config to = clean_phone_number(msg.phone_number) try: self._send_text_message(config, to, msg) # TODO: Implement whatsapp template messages here except Exception: msg.set_system_error(SMS.ERROR_INVALID_DESTINATION_NUMBER) return False
def send_verification(domain, user, phone_number): backend = MobileBackend.auto_load(phone_number, domain) reply_phone = backend.reply_to_phone_number message = OUTGOING % { "name": user.username.split("@")[0], "replyto": " to %s" % util.clean_phone_number(reply_phone) if reply_phone else "", } send_sms(domain, user, phone_number, message)
def create(cls, message_log, api_response=None): phone_number = clean_phone_number(message_log.phone_number) direction = message_log.direction billable = cls( log_id=message_log._id, phone_number=phone_number, direction=direction, date_sent=message_log.date, domain=message_log.domain, ) # Fetch gateway_fee backend_api_id = message_log.backend_api backend_instance = message_log.backend_id country_code, national_number = get_country_code_and_national_number(phone_number) if backend_instance is None or _sms_backend_is_global(backend_instance): billable.gateway_fee = SmsGatewayFee.get_by_criteria( backend_api_id, direction, backend_instance=backend_instance, country_code=country_code, national_number=national_number, ) if billable.gateway_fee is not None: conversion_rate = billable.gateway_fee.currency.rate_to_default if conversion_rate != 0: billable.gateway_fee_conversion_rate = conversion_rate else: smsbillables_logging.error("Gateway fee conversion rate for currency %s is 0", billable.gateway_fee.currency.code) else: smsbillables_logging.error( "No matching gateway fee criteria for SMSLog %s" % message_log._id ) # Fetch usage_fee todo domain = message_log.domain billable.usage_fee = SmsUsageFee.get_by_criteria( direction, domain=domain ) if billable.usage_fee is None: smsbillables_logging.error("Did not find usage fee for direction %s and domain %s" % (direction, domain)) if api_response is not None: billable.api_response = api_response if backend_api_id == TestSMSBackend.get_api_id(): billable.is_valid = False billable.save() return billable
def outbound_backend(self): """appropriate outbound sms backend""" if self.backend_id: return MobileBackend.load(self.backend_id) else: return MobileBackend.auto_load( smsutil.clean_phone_number(self.phone_number), self.domain )
def send_verification(domain, user, phone_number): backend = MobileBackend.auto_load(phone_number, domain) reply_phone = backend.reply_to_phone_number with localize(user.language): message = _(OUTGOING) % { 'name': user.username.split('@')[0], 'replyto': ' to %s' % util.clean_phone_number(reply_phone) if reply_phone else '', } send_sms(domain, user, phone_number, message)
def send_sample_sms(request, domain): request_token = request.POST.get('request_token') if not TelerivetSetupView.get_cached_webhook_secret(request_token): return { 'success': False, 'unexpected_error': TelerivetSetupView.unexpected_error, } outgoing_sms_form = TelerivetOutgoingSMSForm({ 'api_key': request.POST.get('api_key'), 'project_id': request.POST.get('project_id'), 'phone_id': request.POST.get('phone_id'), }) test_sms_form = TelerivetPhoneNumberForm({ 'test_phone_number': request.POST.get('test_phone_number'), }) # Be sure to call .is_valid() on both outgoing_sms_form_valid = outgoing_sms_form.is_valid() test_sms_form_valid = test_sms_form.is_valid() if not outgoing_sms_form_valid or not test_sms_form_valid: return json_response({ 'success': False, 'api_key_error': TelerivetSetupView.get_error_message(outgoing_sms_form, 'api_key'), 'project_id_error': TelerivetSetupView.get_error_message(outgoing_sms_form, 'project_id'), 'phone_id_error': TelerivetSetupView.get_error_message(outgoing_sms_form, 'phone_id'), 'test_phone_number_error': TelerivetSetupView.get_error_message(test_sms_form, 'test_phone_number'), }) tmp_backend = SQLTelerivetBackend() tmp_backend.set_extra_fields( api_key=outgoing_sms_form.cleaned_data.get('api_key'), project_id=outgoing_sms_form.cleaned_data.get('project_id'), phone_id=outgoing_sms_form.cleaned_data.get('phone_id'), ) sms = SMS(phone_number=clean_phone_number( test_sms_form.cleaned_data.get('test_phone_number')), text="This is a test SMS from CommCareHQ.") tmp_backend.send(sms) return json_response({ 'success': True, })
def send(self, msg, *args, **kwargs): client = TwilioRestClient(self.account_sid, self.auth_token) to = msg.phone_number from_ = clean_phone_number(self.phone_number) body = msg.text message = client.sms.messages.create( body=body, to=to, from_=from_ ) msg.backend_message_id = message.sid msg.save()
def send(self, msg, delay=True, *args, **kwargs): phone_number = clean_phone_number(msg.phone_number) text = msg.text.encode("utf-8") params = urlencode({ "action" : "create", "token" : self.messaging_token, "numberToDial" : phone_number, "msg" : text, "_send_sms" : "true", }) url = "https://api.tropo.com/1.0/sessions?%s" % params response = urlopen(url, timeout=settings.SMS_GATEWAY_TIMEOUT).read() return response
def send_sms_with_backend(domain, phone_number, text, backend_id, metadata=None): phone_number = clean_phone_number(phone_number) msg = get_sms_class()( domain=domain, phone_number=phone_number, direction=OUTGOING, date=get_utcnow(), backend_id=backend_id, text=text ) add_msg_tags(msg, metadata) return queue_outgoing_sms(msg)
def send_sms_with_backend_name(domain, phone_number, text, backend_name): phone_number = clean_phone_number(phone_number) msg = SMSLog( domain=domain, phone_number=phone_number, direction=OUTGOING, date=datetime.utcnow(), text=text ) def onerror(): logging.exception("Exception while sending SMS to %s with backend name %s from domain %s" % (phone_number, backend_name, domain)) return send_message_via_backend(msg, MobileBackend.load_by_name(domain, backend_name), onerror=onerror)
def get_current_verification_event(cls, domain, contact_id, phone_number): """ Returns the latest phone verification event that is in progress for the given contact and phone number, or None if one does not exist. """ qs = cls.objects.filter( domain=domain, recipient_id=contact_id, messagingsubevent__sms__phone_number=smsutil.clean_phone_number(phone_number), content_type=cls.CONTENT_PHONE_VERIFICATION, status=cls.STATUS_IN_PROGRESS ) return qs.order_by('-date')[0] if qs.count() > 0 else None
def send(self, msg, delay=True, *args, **kwargs): phone_number = clean_phone_number(msg.phone_number) text = msg.text.encode("utf-8") data = TEMPLATE.format(affiliate_code=escape(self.affiliate_code), auth_code=escape(self.authentication_code), message=escape(text), msisdn=escape(phone_number)) url = "http://www.gvi.bms9.vine.co.za/httpInputhandler/ApplinkUpload" req = urllib2.Request(url, data) response = urllib2.urlopen(req, timeout=settings.SMS_GATEWAY_TIMEOUT) resp = response.read()
def get_backend_api(msg): """ Given a message, find which version of the api to return. """ # this is currently a very dumb method that checks for # india and routes to unicel, otherwise returning mach # The caller assumes the returned module has a send() method # that takes in a message object. phone = clean_phone_number(msg.phone_number) for code, be_module in ALTERNATIVE_BACKENDS: if phone.startswith(code): return be_module return DEFAULT_BACKEND
def send_sms_with_backend_name(domain, phone_number, text, backend_name, metadata=None): phone_number = clean_phone_number(phone_number) backend = SQLMobileBackend.load_by_name(SQLMobileBackend.SMS, domain, backend_name) msg = get_sms_class()( domain=domain, phone_number=phone_number, direction=OUTGOING, date=get_utcnow(), backend_id=backend.couch_id, text=text ) add_msg_tags(msg, metadata) return queue_outgoing_sms(msg)
def send_sms_with_backend_name(domain, phone_number, text, backend_name, metadata=None): phone_number = clean_phone_number(phone_number) backend = MobileBackend.load_by_name(domain, backend_name) msg = SMSLog( domain=domain, phone_number=phone_number, direction=OUTGOING, date=datetime.utcnow(), backend_id=backend._id, text=text ) add_msg_tags(msg, metadata) return queue_outgoing_sms(msg)
def send(self, msg, *args, **kwargs): phone_number = clean_phone_number(msg.phone_number) text = msg.text.encode('utf-8') config = self.config params = urlencode({ 'action': 'create', 'token': config.messaging_token, 'numberToDial': phone_number, 'msg': text, '_send_sms': 'true', }) url = 'https://api.tropo.com/1.0/sessions?%s' % params response = urlopen(url, timeout=settings.SMS_GATEWAY_TIMEOUT).read() return response
def send_sms_with_backend(domain, phone_number, text, backend_id, **kwargs): phone_number = clean_phone_number(phone_number) msg = SMSLog( domain=domain, phone_number=phone_number, direction=OUTGOING, date=datetime.utcnow(), text=text ) add_msg_tags(msg, **kwargs) def onerror(): logging.exception("Exception while sending SMS to %s with backend %s" % (phone_number, backend_id)) return send_message_via_backend(msg, MobileBackend.load(backend_id), onerror=onerror)
def incoming(phone_number, text, backend_api, timestamp=None, domain_scope=None, backend_message_id=None, raw_text=None, backend_id=None): """ entry point for incoming sms phone_number - originating phone number text - message content backend_api - backend API ID of receiving sms backend timestamp - message received timestamp; defaults to now (UTC) domain_scope - set the domain scope for this SMS; see SMSBase.domain_scope for details """ _py3_soft_assert(isinstance(phone_number, six.text_type), '[SMS] phone_number is type %s' % type(phone_number)) _py3_soft_assert(isinstance(text, (six.text_type, type(None))), '[SMS] text is type %s' % type(text)) _py3_soft_assert(isinstance(raw_text, (six.text_type, type(None))), '[SMS] raw_text is type %s' % type(raw_text)) # Log message in message log if text is None: text = "" phone_number = clean_phone_number(phone_number) msg = get_sms_class()( phone_number=phone_number, direction=INCOMING, date=timestamp or get_utcnow(), text=text, domain_scope=domain_scope, backend_api=backend_api, backend_id=backend_id, backend_message_id=backend_message_id, raw_text=raw_text, ) if settings.SMS_QUEUE_ENABLED: msg.processed = False msg.datetime_to_process = get_utcnow() msg.queued_timestamp = msg.datetime_to_process msg.save() enqueue_directly(msg) else: msg.processed = True msg.save() process_incoming(msg) return msg
def send(self, msg, *args, **kwargs): phone_number = clean_phone_number(msg.phone_number) text = msg.text.encode('utf-8') config = self.config data = TEMPLATE.format(affiliate_code=escape(config.affiliate_code), auth_code=escape(config.authentication_code), message=escape(text), msisdn=escape(phone_number)) url = 'http://www.gvi.bms9.vine.co.za/httpInputhandler/ApplinkUpload' req = six.moves.urllib.request.Request(url, data) response = six.moves.urllib.request.urlopen( req, timeout=settings.SMS_GATEWAY_TIMEOUT) resp = response.read()
def send(self, msg, orig_phone_number=None, *args, **kwargs): if not orig_phone_number: raise Exception("Expected orig_phone_number to be passed for all " "instances of PhoneLoadBalancingMixin") config = self.config client = Client(config.account_sid, config.auth_token) to = msg.phone_number msg.system_phone_number = orig_phone_number if toggles.WHATSAPP_MESSAGING.enabled(msg.domain) and not kwargs.get('skip_whatsapp', False): domain_obj = Domain.get_by_name(msg.domain) from_ = getattr(domain_obj, 'twilio_whatsapp_phone_number') or WHATSAPP_SANDBOX_PHONE_NUMBER from_ = clean_phone_number(from_) from_ = self.convert_to_whatsapp(from_) to = self.convert_to_whatsapp(to) messaging_service_sid = None else: from_, messaging_service_sid = self.from_or_messaging_service_sid(orig_phone_number) body = msg.text try: message = client.messages.create( body=body, to=to, from_=from_ or values.unset, messaging_service_sid=messaging_service_sid or values.unset, ) except TwilioRestException as e: if e.code == INVALID_TO_PHONE_NUMBER_ERROR_CODE: msg.set_system_error(SMS.ERROR_INVALID_DESTINATION_NUMBER) return elif e.code == WHATSAPP_LIMITATION_ERROR_CODE: notify_exception(None, f"Error with Twilio Whatsapp: {e}") kwargs['skip_whatsapp'] = True self.send(msg, orig_phone_number, *args, **kwargs) elif e.code == TO_FROM_BLACKLIST_ERROR_CODE: msg.set_gateway_error("Message From/To pair violates a gateway blacklist rule") return elif e.code == REGION_PERMISSION_ERROR_CODE: msg.set_gateway_error("Destination region not enabled for this backend.") return elif e.code == MESSAGE_BODY_REQUIRED_ERROR_CODE: msg.set_gateway_error("Message body is required.") return else: raise msg.backend_message_id = message.sid msg.save()
def incoming(phone_number, text, backend_api, timestamp=None, domain_scope=None, backend_message_id=None, delay=True, backend_attributes=None, raw_text=None): """ entry point for incoming sms phone_number - originating phone number text - message content backend_api - backend API ID of receiving sms backend timestamp - message received timestamp; defaults to now (UTC) domain_scope - if present, only messages from phone numbers that can be definitively linked to this domain will be processed; others will be dropped (useful to provide security when simulating incoming sms) """ # Log message in message log if text is None: text = "" phone_number = clean_phone_number(phone_number) msg = SMSLog( phone_number=phone_number, direction=INCOMING, date=timestamp or datetime.utcnow(), text=text, domain_scope=domain_scope, backend_api=backend_api, backend_message_id=backend_message_id, raw_text=raw_text, ) if backend_attributes: for k, v in backend_attributes.items(): setattr(msg, k, v) if settings.SMS_QUEUE_ENABLED: msg.processed = False msg.datetime_to_process = datetime.utcnow() msg.queued_timestamp = msg.datetime_to_process msg.save() enqueue_directly(msg) else: msg.processed = True msg.save() process_incoming(msg, delay=delay) return msg
def send_sms(domain, contact, phone_number, text, metadata=None, logged_subevent=None): """ Sends an outbound SMS. Returns false if it fails. """ if phone_number is None: return False if isinstance(phone_number, six.integer_types): phone_number = str(phone_number) phone_number = clean_phone_number(phone_number) msg = get_sms_class()(domain=domain, phone_number=phone_number, direction=OUTGOING, date=get_utcnow(), backend_id=None, location_id=get_location_id_by_contact( domain, contact), text=text) if contact: msg.couch_recipient = contact.get_id msg.couch_recipient_doc_type = contact.doc_type if domain and contact and is_commcarecase(contact): backend_name = contact.get_case_property('contact_backend_id') backend_name = backend_name.strip() if isinstance( backend_name, six.string_types) else '' soft_assert_type_text(backend_name) if backend_name: try: backend = SQLMobileBackend.load_by_name( SQLMobileBackend.SMS, domain, backend_name) except BadSMSConfigException as e: if logged_subevent: logged_subevent.error( MessagingEvent.ERROR_GATEWAY_NOT_FOUND, additional_error_text=six.text_type(e)) return False msg.backend_id = backend.couch_id add_msg_tags(msg, metadata) return queue_outgoing_sms(msg)
def incoming(phone_number, text, backend_api, timestamp=None, domain_scope=None, backend_message_id=None, raw_text=None, backend_id=None, media_urls=None): """ entry point for incoming sms phone_number - originating phone number text - message content backend_api - backend API ID of receiving sms backend timestamp - message received timestamp; defaults to now (UTC) domain_scope - set the domain scope for this SMS; see SMSBase.domain_scope for details media_urls - list of urls for media download. """ # Log message in message log if text is None: text = "" phone_number = clean_phone_number(phone_number) msg = get_sms_class()( phone_number=phone_number, direction=INCOMING, date=timestamp or get_utcnow(), text=text, domain_scope=domain_scope, backend_api=backend_api, backend_id=backend_id, backend_message_id=backend_message_id, raw_text=raw_text, ) if media_urls: msg.custom_metadata = {"media_urls": media_urls} if settings.SMS_QUEUE_ENABLED: msg.processed = False msg.datetime_to_process = get_utcnow() msg.queued_timestamp = msg.datetime_to_process msg.save() enqueue_directly(msg) else: msg.processed = True msg.save() process_incoming(msg) return msg
def send(self, msg, orig_phone_number=None, *args, **kwargs): config = self.config to = clean_phone_number(msg.phone_number) headers = { 'Authorization': f'App {config.auth_token}', 'Content-Type': 'application/json', 'Accept': 'application/json' } try: if config.scenario_key: self._send_omni_failover_message(config, to, msg, headers) else: self._send_sms(config, to, msg, headers) except Exception: msg.set_system_error(SMS.ERROR_INVALID_DESTINATION_NUMBER) return False
def send_sms_with_backend_name(domain, phone_number, text, backend_name, metadata=None): phone_number = clean_phone_number(phone_number) backend = MobileBackend.load_by_name(domain, backend_name) msg = SMSLog(domain=domain, phone_number=phone_number, direction=OUTGOING, date=datetime.utcnow(), backend_id=backend._id, text=text) add_msg_tags(msg, metadata) return queue_outgoing_sms(msg)
def send(self, msg, orig_phone_number=None, *args, **kwargs): config = self.config client = TurnClient(config.client_auth_token) to = clean_phone_number(msg.phone_number) try: wa_id = client.contacts.get_whatsapp_id(to) if is_whatsapp_template_message(msg.text): return self._send_template_message(client, wa_id, msg) else: return self._send_text_message(client, wa_id, msg) except WhatsAppContactNotFound: msg.set_system_error(SMS.ERROR_INVALID_DESTINATION_NUMBER) if self.config.fallback_backend_id: self._send_fallback_message(msg) return False
def create(cls, message_log, api_response=None): phone_number = clean_phone_number(message_log.phone_number) direction = message_log.direction billable = cls( log_id=message_log._id, phone_number=phone_number, direction=direction, date_sent=message_log.date, ) # Fetch gateway_fee backend_api_id = message_log.backend_api backend_instance = message_log.backend_id country_code = get_country_code(phone_number) billable.gateway_fee = SmsGatewayFee.get_by_criteria( backend_api_id, direction, backend_instance=backend_instance, country_code=country_code) if billable.gateway_fee is not None: conversion_rate = billable.gateway_fee.currency.rate_to_default if conversion_rate != 0: billable.gateway_fee_conversion_rate = conversion_rate else: smsbillables_logging.error( "Gateway fee conversion rate for currency %s is 0", billable.gateway_fee.currency.code) # Fetch usage_fee todo domain = message_log.domain billable.usage_fee = SmsUsageFee.get_by_criteria(direction, domain=domain) if billable.usage_fee is None: smsbillables_logging.error( "Did not find usage fee for direction %s and domain %s" % (direction, domain)) if api_response is not None: billable.api_response = api_response billable.save() return billable
def post(self, request, *args, **kwargs): context = self.get_context_data(**kwargs) reminder = request.POST.get('reminder') phone_number = context.get('phone_number') if reminder and phone_number: phone_number = clean_phone_number(phone_number) v = VerifiedNumber.by_phone(phone_number, include_pending=True) if v and v.verified: user = v.owner if not user: return self.get(request, *args, **kwargs) reminder_function = self.reminders.get(reminder) reminder_function(self.domain, datetime.utcnow(), test_list=[user]) messages.success(request, "Reminder was sent successfully") return self.get(request, *args, **kwargs)
def send_sms_with_backend(domain, phone_number, text, backend_id, metadata=None): phone_number = clean_phone_number(phone_number) msg = SMSLog(domain=domain, phone_number=phone_number, direction=OUTGOING, date=datetime.utcnow(), backend_id=backend_id, text=text) add_msg_tags(msg, metadata) def onerror(): logging.exception("Exception while sending SMS to %s with backend %s" % (phone_number, backend_id)) return queue_outgoing_sms(msg, onerror=onerror)
def send(self, msg, *args, **kwargs): text = msg.text.encode("utf-8") params = { "phone_id": str(self.phone_id), "to_number": clean_phone_number(msg.phone_number), "content": text, "message_type": MESSAGE_TYPE_SMS, } url = "https://api.telerivet.com/v1/projects/%s/messages/outgoing" % str(self.project_id) result = requests.post( url, auth=(str(self.api_key), ''), data=params, verify=True, timeout=settings.SMS_GATEWAY_TIMEOUT, ) result = result.json()
def send(self, msg, *args, **kwargs): config = self.config if config.additional_params: params = config.additional_params.copy() else: params = {} phone_number = msg.phone_number if config.include_plus: phone_number = clean_phone_number(phone_number) else: phone_number = strip_plus(phone_number) try: text = msg.text.encode("iso-8859-1") except UnicodeEncodeError: text = msg.text.encode("utf-8") params[config.message_param] = text params[config.number_param] = phone_number url_params = urlencode(params) try: unverified = ssl._create_unverified_context() if config.method == "GET": urlopen( "%s?%s" % (config.url, url_params), context=unverified, timeout=settings.SMS_GATEWAY_TIMEOUT, ).read() else: urlopen( config.url, url_params, context=unverified, timeout=settings.SMS_GATEWAY_TIMEOUT, ).read() except Exception as e: msg = "Error sending message from backend: '{}'\n\n{}".format( self.pk, str(e)) six.reraise(BackendProcessingException, BackendProcessingException(msg), sys.exc_info()[2])
def send(self, msg, *args, **kwargs): phone_number = clean_phone_number(msg.phone_number) text = msg.text config = self.config data = TEMPLATE.format(affiliate_code=escape(config.affiliate_code), auth_code=escape(config.authentication_code), message=escape(text), msisdn=escape(phone_number)) url = 'http://www.gvi.bms9.vine.co.za/httpInputhandler/ApplinkUpload' response = requests.post( url, data=data.encode('utf-8'), headers={'content-type': 'text/xml'}, timeout=settings.SMS_GATEWAY_TIMEOUT, ) self.handle_response(response)