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_sms_to_verified_number(verified_number, text, metadata=None): """ Sends an sms using the given verified phone number entry. verified_number The VerifiedNumber entry to use when sending. text The text of the message to send. return True on success, False on failure """ backend = verified_number.backend msg = SMSLog(couch_recipient_doc_type=verified_number.owner_doc_type, couch_recipient=verified_number.owner_id, phone_number="+" + str(verified_number.phone_number), direction=OUTGOING, date=datetime.utcnow(), domain=verified_number.domain, backend_id=backend._id, text=text) add_msg_tags(msg, metadata) def onerror(): logging.exception("Exception while sending SMS to VerifiedNumber id " + verified_number._id) return queue_outgoing_sms(msg, onerror=onerror)
def post(request, domain): # TODO: Figure out if this is being used anywhere and remove it if not """ We assume sms sent to HQ will come in the form http://hqurl.com?username=%(username)s&password=%(password)s&id=%(phone_number)s&text=%(message)s """ text = request.REQUEST.get('text', '') to = request.REQUEST.get('id', '') username = request.REQUEST.get('username', '') # ah, plaintext passwords.... # this seems to be the most common API that a lot of SMS gateways expose password = request.REQUEST.get('password', '') if not text or not to or not username or not password: error_msg = 'ERROR missing parameters. Received: %(1)s, %(2)s, %(3)s, %(4)s' % \ ( text, to, username, password ) logging.error(error_msg) return HttpResponseBadRequest(error_msg) user = authenticate(username=username, password=password) if user is None or not user.is_active: return HttpResponseBadRequest("Authentication fail") msg = SMSLog( domain=domain, # TODO: how to map phone numbers to recipients, when phone numbers are shared? #couch_recipient=id, phone_number=to, direction=INCOMING, date=datetime.now(), text=text) msg.save() return HttpResponse('OK')
def testFRISMSLogSync(self): prev_couch_count = self.getSMSLogCount() prev_sql_count = self.getSMSCount() # Test Create smslog = SMSLog() self.setRandomSMSLogValues(smslog) smslog.save() sleep(1) smslog = FRISMSLog.get(smslog._id) self.setRandomFRISMSLogValues(smslog) smslog.save() sleep(1) self.assertEqual(self.getSMSLogCount(), prev_couch_count + 1) self.assertEqual(self.getSMSCount(), prev_sql_count + 1) sms = SMS.objects.get(couch_id=smslog._id) self.checkFieldValues(smslog, sms, FRISMSLog._migration_get_fields()) self.assertTrue(FRISMSLog.get_db().get_rev( smslog._id).startswith('2-')) # Test Update self.setRandomSMSLogValues(smslog) self.setRandomFRISMSLogValues(smslog) smslog.save() sleep(1) self.assertEqual(self.getSMSLogCount(), prev_couch_count + 1) self.assertEqual(self.getSMSCount(), prev_sql_count + 1) sms = SMS.objects.get(couch_id=smslog._id) self.checkFieldValues(smslog, sms, FRISMSLog._migration_get_fields()) self.assertTrue(SMSLog.get_db().get_rev(smslog._id).startswith('3-'))
def _get_fake_sms(self, text): msg = SMSLog(domain=self.domain, phone_number='+16175555454', direction=OUTGOING, date=datetime.utcnow(), backend_id=self.mobile_backend.get_id, text=text) msg.save() return msg
def send_sms_with_backend(domain, phone_number, text, backend_id): 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 %s" % (phone_number, backend_id)) return send_message_via_backend(msg, MobileBackend.load(backend_id), onerror=onerror)
def send_test_message(verified_number, text, metadata=None): msg = SMSLog(couch_recipient_doc_type=verified_number.owner_doc_type, couch_recipient=verified_number.owner_id, phone_number="+" + str(verified_number.phone_number), direction=OUTGOING, date=datetime.utcnow(), domain=verified_number.domain, text=text, processed=True, datetime_to_process=datetime.utcnow(), queued_timestamp=datetime.utcnow()) msg.save() add_msg_tags(msg, metadata) return True
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) return queue_outgoing_sms(msg)
def q_and_a(testcase, answer, expected_response, domain=DOMAIN, contact_id=CONTACT_ID, print_output=True): responses = get_responses( SMSLog(couch_recipient=contact_id, domain=domain, text=answer)) [answer_back] = responses testcase.assertEqual(expected_response, answer_back, "Response to '%s' expected '%s' but was '%s'" % \ (answer, expected_response, answer_back)) if print_output: print "%s -> %s" % (answer, answer_back)
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 arbitrary_messages_by_backend_and_direction(backend_ids, phone_number=None, domain=None, directions=DIRECTIONS): phone_number = phone_number or TEST_NUMBER domain = domain or TEST_DOMAIN messages = [] for api_id, instance_id in backend_ids.items(): for direction in directions: sms_log = SMSLog(direction=direction, phone_number=phone_number, domain=domain, backend_api=api_id, backend_id=instance_id, text=arbitrary_message(), date=datetime.datetime.utcnow()) sms_log.save() messages.append(sms_log) return messages
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_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 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