Esempio n. 1
0
function Users_user_validate()
{
    Q_Valid::nonce(true);
    $type = isset($_REQUEST['identifierType']) ? $_REQUEST['identifierType'] : Q_Config::get("Users", "login", "identifierType", "email,mobile");
    $parts = explode(',', $type);
    $accept_mobile = true;
    $expected = 'email address or mobile number';
    $fields = array('emailAddress', 'mobileNumber', 'identifier');
    if (count($parts) === 1) {
        if ($parts[0] === 'email') {
            $expected = 'email address';
            $fields = array('emailAddress', 'identifier');
            $accept_mobile = false;
        } else {
            if ($parts[0] === 'mobile') {
                $expected = 'mobile number';
                $fields = array('mobileNumber', 'identifier');
            }
        }
    }
    if (!isset($_REQUEST['identifier'])) {
        throw new Q_Exception("a valid {$expected} is required", $fields);
    }
    if (!Q_Valid::email($_REQUEST['identifier'])) {
        if (!$accept_mobile) {
            throw new Q_Exception("a valid {$expected} is required", $fields);
        }
        if (!Q_Valid::phone($_REQUEST['identifier'])) {
            throw new Q_Exception("a valid {$expected} is required", $fields);
        }
    }
}
Esempio n. 2
0
function Users_activate_validate()
{
    $uri = Q_Dispatcher::uri();
    $emailAddress = Q::ifset($_REQUEST, 'e', $uri->emailAddress);
    $mobileNumber = Q::ifset($_REQUEST, 'm', $uri->mobileNumber);
    if ($emailAddress && !Q_Valid::email($emailAddress, $e_normalized, array('no_ip' => 'false'))) {
        throw new Q_Exception_WrongValue(array('field' => 'email', 'range' => 'a valid email address'), 'emailAddress');
    }
    if ($mobileNumber && !Q_Valid::phone($mobileNumber, $m_normalized)) {
        throw new Q_Exception_WrongValue(array('field' => 'mobile phone', 'range' => 'a valid phone number'), 'mobileNumber');
    }
    if ($emailAddress or $mobileNumber) {
        if (empty($_REQUEST['code'])) {
            throw new Q_Exception("The activation code is missing");
        }
    } else {
        throw new Q_Exception("The contact information is missing");
    }
    if (!empty($e_normalized)) {
        Users::$cache['emailAddress'] = $e_normalized;
    }
    if (!empty($m_normalized)) {
        Users::$cache['mobileNumber'] = $m_normalized;
    }
}
Esempio n. 3
0
function Users_user_validate()
{
    if (isset($_REQUEST['userIds']) or isset($_REQUEST['batch'])) {
        return;
    }
    $type = isset($_REQUEST['identifierType']) ? $_REQUEST['identifierType'] : Q_Config::get("Users", "login", "identifierType", "email,mobile");
    $parts = explode(',', $type);
    $accept_mobile = true;
    $expected = 'email address or mobile number';
    $fields = array('emailAddress', 'mobileNumber', 'identifier');
    if (count($parts) === 1) {
        if ($parts[0] === 'email') {
            $expected = 'email address';
            $fields = array('emailAddress', 'identifier');
            $accept_mobile = false;
        } else {
            if ($parts[0] === 'mobile') {
                $expected = 'mobile number';
                $fields = array('mobileNumber', 'identifier');
            }
        }
    }
    if (!isset($_REQUEST['identifier'])) {
        throw new Q_Exception("a valid {$expected} is required", $fields);
    }
    if (!Q_Valid::email($_REQUEST['identifier'])) {
        if (!$accept_mobile) {
            throw new Q_Exception("a valid {$expected} is required", $fields);
        }
        if (!Q_Valid::phone($_REQUEST['identifier'])) {
            throw new Q_Exception("a valid {$expected} is required", $fields);
        }
    }
    $identifier = Users::requestedIdentifier($type);
    // check our db
    if ($user = Users::userFromContactInfo($type, $identifier)) {
        $verified = !!Users::identify($type, $identifier);
        return array('exists' => $user->id, 'verified' => $verified, 'username' => $user->username, 'icon' => $user->icon, 'passphrase_set' => !empty($user->passphraseHash), 'fb_uid' => $user->fb_uid ? $user->fb_uid : null);
    }
    if ($type === 'email') {
        $email = new Users_Email();
        Q_Valid::email($identifier, $normalized);
        $email->address = $normalized;
        $exists = $email->retrieve();
    } else {
        if ($type === 'mobile') {
            $mobile = new Users_Mobile();
            Q_Valid::phone($identifier, $normalized);
            $mobile->number = $normalized;
            $exists = $mobile->retrieve();
        }
    }
    if (empty($exists) and Q_Config::get('Users', 'login', 'noRegister', false)) {
        $nicetype = $type === 'email' ? 'email address' : 'mobile number';
        throw new Q_Exception("This {$nicetype} was not registered", array('identifier'));
    }
}
Esempio n. 4
0
function Users_user_response_data($params)
{
    $identifier = Users::requestedIdentifier($type);
    // check our db
    if ($user = Users::userFromContactInfo($type, $identifier)) {
        $verified = !!Users::identify($type, $identifier);
        return array('exists' => $user->id, 'verified' => $verified, 'username' => $user->username, 'icon' => $user->icon, 'passphrase_set' => !empty($user->passphraseHash), 'fb_uid' => $user->fb_uid ? $user->fb_uid : null);
    }
    if ($type === 'email') {
        $email = new Users_Email();
        Q_Valid::email($identifier, $normalized);
        $email->address = $normalized;
        $exists = $email->retrieve();
    } else {
        if ($type === 'mobile') {
            $mobile = new Users_Mobile();
            Q_Valid::phone($identifier, $normalized);
            $mobile->number = $normalized;
            $exists = $mobile->retrieve();
        }
    }
    if (empty($exists) and Q_Config::get('Users', 'login', 'noRegister', false)) {
        $nicetype = $type === 'email' ? 'email address' : 'mobile number';
        throw new Q_Exception("This {$nicetype} was not registered", array('identifier'));
    }
    // Get Gravatar info
    // WARNING: INTERNET_REQUEST
    $hash = md5(strtolower(trim($identifier)));
    $thumbnailUrl = Q_Request::baseUrl() . "/action.php/Users/thumbnail?hash={$hash}&size=80&type=" . Q_Config::get('Users', 'login', 'iconType', 'wavatar');
    $json = @file_get_contents("http://www.gravatar.com/{$hash}.json");
    $result = json_decode($json, true);
    if ($result) {
        if ($type === 'email') {
            $result['emailExists'] = !empty($exists);
        } else {
            if ($type === 'mobile') {
                $result['mobileExists'] = !empty($exists);
            }
        }
        return $result;
    }
    // otherwise, return default
    $email_parts = explode('@', $identifier, 2);
    $result = array("entry" => array(array("id" => "571", "hash" => "357a20e8c56e69d6f9734d23ef9517e8", "requestHash" => "357a20e8c56e69d6f9734d23ef9517e8", "profileUrl" => "http://gravatar.com/test", "preferredUsername" => ucfirst($email_parts[0]), "thumbnailUrl" => $thumbnailUrl, "photos" => array(), "displayName" => "", "urls" => array())));
    if ($type === 'email') {
        $result['emailExists'] = !empty($exists);
    } else {
        $result['mobileExists'] = !empty($exists);
    }
    if ($terms_label = Users::termsLabel('register')) {
        $result['termsLabel'] = $terms_label;
    }
    return $result;
}
Esempio n. 5
0
function Streams_user_response_data($params)
{
    $identifier = Users::requestedIdentifier($type);
    $hash = md5(strtolower(trim($identifier)));
    $icon = Q_Config::get('Users', 'register', 'icon', 'leaveDefault', false) ? $url = "plugins/Users/img/icons/default/80.png" : Q_Request::baseUrl() . "/action.php/Users/thumbnail?hash={$hash}&size=80&type=" . Q_Config::get('Users', 'login', 'iconType', 'wavatar');
    // check our db
    if ($user = Users::userFromContactInfo($type, $identifier)) {
        $displayname = Streams::displayName($user);
        $verified = !!Users::identify($type, $identifier);
        return array('exists' => $user->id, 'verified' => $verified, 'username' => $user->username, 'displayName' => $displayname, 'icon' => $verified ? $icon : $user->icon, 'passphrase_set' => !empty($user->passphraseHash), 'fb_uid' => $user->fb_uid ? $user->fb_uid : null);
    }
    if ($type === 'email') {
        $email = new Users_Email();
        Q_Valid::email($identifier, $normalized);
        $email->address = $normalized;
        $exists = $email->retrieve();
    } else {
        if ($type === 'mobile') {
            $mobile = new Users_Mobile();
            Q_Valid::phone($identifier, $normalized);
            $mobile->number = $normalized;
            $exists = $mobile->retrieve();
        }
    }
    if (empty($exists) and Q_Config::get('Users', 'login', 'noRegister', false)) {
        $nicetype = $type === 'email' ? 'email address' : 'mobile number';
        throw new Q_Exception("This {$nicetype} was not registered", array('identifier'));
    }
    $result = array("entry" => array(array("thumbnailUrl" => $icon)));
    if ($type === 'email') {
        $result['emailExists'] = !empty($exists);
    } else {
        $result['mobileExists'] = !empty($exists);
    }
    if ($terms_label = Users::termsLabel('register')) {
        $result['termsLabel'] = $terms_label;
    }
    return $result;
}
Esempio n. 6
0
function Users_activate_objects_mobile($mobileNumber, &$mobile)
{
    Q_Response::removeNotice('Users/activate/objects');
    $mobile = new Users_Mobile();
    if (!Q_Valid::phone($mobileNumber, $normalized)) {
        return;
    }
    $mobile->number = $normalized;
    if (!$mobile->retrieve()) {
        throw new Q_Exception_MissingRow(array('table' => 'mobile phone', 'criteria' => "number {$normalized}"));
    }
    $user = Users::loggedInUser();
    if ($user) {
        if ($user->id != $mobile->userId) {
            throw new Q_Exception("You are logged in as a different user. Please log out and click the link again.");
        }
    } else {
        $user = new Users_User();
        $user->id = $mobile->userId;
        if (!$user->retrieve()) {
            throw new Q_Exception_MissingRow(array('table' => 'user', 'criteria' => 'id = ' . $user->id));
        }
    }
    if ($mobile->activationCode != $_REQUEST['code']) {
        throw new Q_Exception("The activation code does not match. Did you get a newer message?", 'code');
    }
    $timestamp = Users_Mobile::db()->getCurrentTimestamp();
    if ($timestamp > Users_Mobile::db()->fromDateTime($mobile->activationCodeExpires)) {
        throw new Q_Exception("Activation code expired");
    }
    if (Q_Request::method() !== 'POST' and empty($_REQUEST['p']) and isset($user->mobileNumber) and $user->mobileNumber == $mobile->number) {
        $displayName = Streams::displayName($user);
        Q_Response::setNotice('Users/activate/objects', "{$normalized} has already been activated for {$displayName}", true);
        return $user;
    }
    return $user;
}
Esempio n. 7
0
 /**
  * Get the email address or mobile number from the request, if it can be deduced.
  * Note: it should still be tested for validity.
  * @method requestedIdentifier
  * @static
  * @param {&string} [$type=null] The identifier's type will be filled here. Might be "email", "mobile" or "token".
  * @return {string|null} The identifier, or null if one wasn't requested
  */
 static function requestedIdentifier(&$type = null)
 {
     $identifier = null;
     $type = null;
     if (!empty($_REQUEST['identifier'])) {
         $identifier = $_REQUEST['identifier'];
         if (strpos($identifier, ':') !== false) {
             list($type, $token) = explode(':', $identifier);
             if ($type === 'token') {
                 return $token;
             }
         }
         if (Q_Valid::email($identifier, $normalized)) {
             $type = 'email';
         } else {
             if (Q_Valid::phone($identifier, $normalized)) {
                 $type = 'mobile';
             }
         }
     }
     if (!empty($_REQUEST['emailAddress'])) {
         $identifier = $_REQUEST['emailAddress'];
         Q_Valid::email($identifier, $normalized);
         $type = 'email';
     }
     if (!empty($_REQUEST['mobileNumber'])) {
         $identifier = $_REQUEST['mobileNumber'];
         Q_Valid::phone($identifier, $normalized);
         $type = 'mobile';
     }
     return isset($normalized) ? $normalized : $identifier;
 }
Esempio n. 8
0
 /**
  * Check identifier or array of identifiers and return users - existing or future
  * @method idsFromIdentifiers
  * @static
  * @param $asUserId {string} The user id of inviting user
  * @param $identifiers {string|array}
  * @param $statuses {array} Optional reference to an array to populate with $userId => $status pairs.
  * @return {array} The array of user ids
  */
 static function idsFromIdentifiers($identifiers, &$statuses = array())
 {
     if (empty($identifiers)) {
         return array();
     }
     if (!is_array($identifiers)) {
         $identifiers = array_map('trim', explode(',', $identifiers));
     }
     $users = array();
     foreach ($identifiers as $identifier) {
         if (Q_Valid::email($identifier, $emailAddress)) {
             $ui_identifier = $emailAddress;
             $type = 'email';
         } else {
             if (Q_Valid::phone($identifier, $mobileNumber)) {
                 $ui_identifier = $mobileNumber;
                 $type = 'mobile';
             } else {
                 throw new Q_Exception_WrongType(array('field' => 'identifier', 'type' => 'email address or mobile number'), array('emailAddress', 'mobileNumber'));
             }
         }
         $status = null;
         $users[] = $user = Users::futureUser($type, $ui_identifier, $status);
         $statuses[$user->id] = $status;
     }
     return array_map(array('Users_User', '_getId'), $users);
 }
Esempio n. 9
0
 /**
  * Invites a user (or a future user) to a stream .
  * @method invite
  * @static
  * @param {string} $publisherId The id of the stream publisher
  * @param {string} $streamName The name of the stream the user will be invited to
  * @param {array} $who Array that can contain the following keys:
  * @param {string|array} [$who.userId] user id or an array of user ids
  * @param {string|array} [$who.fb_uid]  fb user id or array of fb user ids
  * @param {string|array} [$who.label]  label or an array of labels, or tab-delimited string
  * @param {string|array} [$who.identifier]  identifier or an array of identifiers, or tab-delimited string
  * @param {integer} [$who.newFutureUsers] the number of new Users_User objects to create via Users::futureUser in order to invite them to this stream. This typically is used in conjunction with passing the "html" option to this function.
  * @param {array} [$options=array()]
  *  @param {string|array} [$options.label] label or an array of labels for adding publisher's contacts
  *  @param {string|array} [$options.myLabel] label or an array of labels for adding logged-in user's contacts
  *  @param {integer} [$options.readLevel] => the read level to grant those who are invited
  *  @param {integer} [$options.writeLevel] => the write level to grant those who are invited
  *  @param {integer} [$options.adminLevel] => the admin level to grant those who are invited
  *	@param {string} [$options.displayName] => the display name to use to represent the inviting user
  *  @param {string} [$options.appUrl] => Can be used to override the URL to which the invited user will be redirected and receive "Q.Streams.token" in the querystring.
  *	@param {array} [$options.html] => an array of ($template, $batchName) such as ("MyApp/foo.handlebars", "foo") for generating html snippets which can then be viewed from and printed via the action Streams/invitations?batchName=$batchName
  * @param {array} [$options.asUserId=null] Invite as this user id
  * @see Users::addLink()
  * @return {array} returns array with keys "success", "invited", "statuses", "identifierTypes", "alreadyParticipating"
  */
 static function invite($publisherId, $streamName, $who, $options = array())
 {
     if (isset($options['asUserId'])) {
         $asUserId = $options['asUserId'];
         $asUser = Users_User::fetch($asUserId);
     } else {
         $asUser = Users::loggedInUser(true);
         $asUserId = $asUser->id;
     }
     // Fetch the stream as the logged-in user
     $stream = Streams::fetch($asUserId, $publisherId, $streamName);
     if (!$stream) {
         throw new Q_Exception_MissingRow(array('table' => 'stream', 'criteria' => 'with that name'), 'streamName');
     }
     $stream = reset($stream);
     // Do we have enough admin rights to invite others to this stream?
     if (!$stream->testAdminLevel('invite') || !$stream->testWriteLevel('join')) {
         throw new Users_Exception_NotAuthorized();
     }
     if (isset($options['html'])) {
         $html = $options['html'];
         if (!is_array($html) or count($html) < 2) {
             throw new Q_Exception_WrongType(array('field' => "options.html", 'type' => 'array of 2 strings'));
         }
         list($template, $batchName) = $html;
         // validate these paths
         $filename = APP_VIEWS_DIR . DS . $template;
         if (!Q::realPath($filename)) {
             throw new Q_Exception_MissingFile(compact('filename'));
         }
         $ext = $pathinfo = pathinfo($template, PATHINFO_EXTENSION);
         if ($ext !== 'handlebars') {
             throw new Q_Exception_WrongValue(array('field' => 'options.html[0]', 'range' => 'a filename with extension .handlebars'));
         }
         $path = Streams::invitationsPath($asUserId) . DS . $batchName;
         Q_Utils::canWriteToPath($path, true, true);
     }
     // get user ids if any to array, throw if user not found
     $raw_userIds = isset($who['userId']) ? Users_User::verifyUserIds($who['userId'], true) : array();
     // merge labels if any
     if (isset($who['label'])) {
         $label = $who['label'];
         if (is_string($label)) {
             $label = array_map('trim', explode("\t", $labels));
         }
         $raw_userIds = array_merge($raw_userIds, Users_User::labelsToIds($asUserId, $label));
     }
     // merge identifiers if any
     $identifierType = null;
     $statuses = null;
     if (isset($who['identifier'])) {
         $identifier = $who['identifier'];
         if (is_string($identifier)) {
             if (Q_Valid::email($who['identifier'])) {
                 $identifierType = 'email';
             } else {
                 if (Q_Valid::phone($who['identifier'])) {
                     $identifierType = 'mobile';
                 }
             }
             $identifier = array_map('trim', explode("\t", $identifier));
         }
         $statuses = array();
         $identifier_ids = Users_User::idsFromIdentifiers($identifier, $statuses);
         $raw_userIds = array_merge($raw_userIds, $identifier_ids);
     }
     // merge fb uids if any
     if (isset($who['fb_uid'])) {
         $fb_uids = $who['fb_uid'];
         if (is_string($fb_uids)) {
             $fb_uids = array_map('trim', explode("\t", $fb_uids));
         }
         $raw_userIds = array_merge($raw_userIds, Users_User::idsFromFacebook($fb_uids));
     }
     if (!empty($who['newFutureUsers'])) {
         $nfu = $who['newFutureUsers'];
         for ($i = 0; $i < $nfu; ++$i) {
             $raw_userIds[] = Users::futureUser('none', null)->id;
         }
     }
     // ensure that each userId is included only once
     // and remove already participating users
     $raw_userIds = array_unique($raw_userIds);
     $total = count($raw_userIds);
     $userIds = Streams_Participant::filter($raw_userIds, $stream);
     $to_invite = count($userIds);
     $appUrl = !empty($options['appUrl']) ? $options['appUrl'] : Q_Request::baseUrl() . '/' . Q_Config::get("Streams", "types", $stream->type, "invite", "url", "plugins/Streams/stream");
     // now check and define levels for invited user
     $readLevel = isset($options['readLevel']) ? $options['readLevel'] : null;
     if (isset($readLevel)) {
         if (!$stream->testReadLevel($readLevel)) {
             // We can't assign greater read level to other people than we have ourselves!
             throw new Users_Exception_NotAuthorized();
         }
     }
     $writeLevel = isset($options['writeLevel']) ? $options['writeLevel'] : null;
     if (isset($writeLevel)) {
         if (!$stream->testWriteLevel($writeLevel)) {
             // We can't assign greater write level to other people than we have ourselves!
             throw new Users_Exception_NotAuthorized();
         }
     }
     $adminLevel = isset($options['adminLevel']) ? $options['adminLevel'] : null;
     if (isset($adminLevel)) {
         if (!$stream->testAdminLevel($adminLevel + 1)) {
             // We can't assign an admin level greater, or equal, to our own!
             // A stream's publisher can assign owners. Owners can assign admins.
             // Admins can confer powers to invite others, to some people.
             // Those people can confer the privilege to publish a message re this stream.
             // But admins can't assign other admins, and even stream owners
             // can't assign other owners.
             throw new Users_Exception_NotAuthorized();
         }
     }
     // calculate expiry time
     $duration = Q_Config::get("Streams", "types", $stream->type, "invite", "duration", false);
     $expiry = $duration ? strtotime($duration) : null;
     // let node handle the rest, and get the result
     $params = array("Q/method" => "Streams/Stream/invite", "invitingUserId" => $asUserId, "username" => $asUser->username, "userIds" => Q::json_encode($userIds), "stream" => Q::json_encode($stream->toArray()), "appUrl" => $appUrl, "label" => Q::ifset($options, 'label', null), "myLabel" => Q::ifset($options, 'myLabel', null), "readLevel" => $readLevel, "writeLevel" => $writeLevel, "adminLevel" => $adminLevel, "displayName" => isset($options['displayName']) ? $options['displayName'] : Streams::displayName($asUser), "expiry" => $expiry);
     if ($template) {
         $params['template'] = $template;
         $params['batchName'] = $batchName;
     }
     $result = Q_Utils::queryInternal('Q/node', $params);
     return array('success' => $result, 'invited' => $userIds, 'statuses' => $statuses, 'identifierType' => $identifierType, 'alreadyParticipating' => $total - $to_invite);
 }
Esempio n. 10
0
 /**
  * @method sendMessage
  * @param {string} $view
  *  The name of a view for the message. Fields are passed to this array.
  * @param {array} $fields=array()
  *  The fields referenced in the subject and/or view
  * @param {array} $options=array()
  *  Array of options. Can include:<br/>
  *  "delay" => A delay, in milliseconds, to wait until sending email. Only works if Node server is listening.
  * @return {boolean}
  * @throws {Q_Exception_WrongType}
  *	If phone number is invalid
  */
 function sendMessage($view, $fields = array(), $options = array())
 {
     /**
      * @event Users/sms/sendMessage {before}
      * @param {string} view
      * @param {array} fields
      * @param {array} options
      * @return {boolean}
      */
     $result = Q::event('Users/sms/sendMessage', compact('view', 'fields', 'options'), 'before');
     if (isset($result)) {
         return $result;
     }
     if (!Q_Valid::phone($this->number, $number)) {
         throw new Q_Exception_WrongType(array('field' => '$this->number', 'type' => 'mobile number', 'mobileNumber' => $this->number));
     }
     $app = Q_Config::expect('Q', 'app');
     $body = Q::view($view, $fields);
     $overrideLog = Q::event('Users/mobile/log', compact('mobileNumber', 'body'), 'before');
     if (is_null($overrideLog) and $key = Q_Config::get('Users', 'mobile', 'log', 'key', null)) {
         Q::log("\nSent mobile message to {$this->number}:\n{$body}", $key);
     }
     $sent = false;
     if (!empty($options['delay'])) {
         // Try to use Node.js to send the message
         $sent = Q_Utils::sendToNode(array("Q/method" => "Users/sendMessage", "delay" => $options['delay'], "mobileNumber" => $number, "body" => $body, "options" => $options));
     }
     if (!$sent) {
         $from = Q::ifset($options, 'from', Q_Config::get('Users', 'mobile', 'from', null));
         if (!isset($from)) {
             // deduce from base url
             $url_parts = parse_url(Q_Request::baseUrl());
             $domain = $url_parts['host'];
             $from = array("notifications@{$domain}", $domain);
         }
         $sid = Q_Config::get('Users', 'mobile', 'twilio', 'sid', null);
         $token = Q_Config::get('Users', 'mobile', 'twilio', 'token', null);
         if ($sid and $token) {
             $client = new Services_Twilio($sid, $token);
             $message = $client->account->sms_messages->create($from, $number, Q::view($view, $fields));
         } else {
             if (!Q_Config::get('Users', 'email', 'smtp', null)) {
                 Q_Response::setNotice("Q/mobile", "Please set up transport in Users/mobile/twilio as in docs", false);
                 return true;
             }
             if (!is_array($from)) {
                 $from = array($from, "{$app} activation");
             }
             // Set up the default mail transport
             $host = Q_Config::get('Users', 'email', 'smtp', 'host', 'sendmail');
             if ($host === 'sendmail') {
                 $transport = new Zend_Mail_Transport_Sendmail('-f' . reset($from));
             } else {
                 if (is_array($host)) {
                     $smtp = $host;
                     $host = $smtp['host'];
                     unset($smtp['host']);
                 } else {
                     $smtp = null;
                 }
                 $transport = new Zend_Mail_Transport_Smtp($host, $smtp);
             }
             $mail = new Zend_Mail();
             $from_name = reset($from);
             $mail->setFrom(next($from), $from_name);
             $gateways = Q_Config::get('Users', 'mobile', 'gateways', array('at&t' => 'txt.att.net', 'sprint' => 'messaging.sprintpcs.com', 'verizon' => 'vtext.com', 't-mobile' => 'tmomail.net'));
             $number2 = substr($this->number, 2);
             foreach ($gateways as $k => $v) {
                 $mail->addTo($number2 . '@' . $v);
             }
             $mail->setBodyText($body);
             try {
                 $mail->send($transport);
             } catch (Exception $e) {
                 throw new Users_Exception_MobileMessage(array('error' => $e->getMessage()));
             }
         }
     }
     /**
      * @event Users/sms/sendMessage {after}
      * @param {string} view
      * @param {array} fields
      * @param {array} options
      * @param {string} mail
      */
     Q::event('Users/email/sendMessage', compact('view', 'fields', 'options', 'mail', 'app'), 'after');
     return true;
 }