/** * Выбираем пул заданий и рассылаем по ним e-mail */ public function Client() { $aNotifyTasks = E::ModuleNotify()->GetTasksDelayed(Config::Get('module.notify.per_process')); if (empty($aNotifyTasks)) { $this->Log('No tasks are found.'); return; } // * Последовательно загружаем задания на отправку $aArrayId = array(); foreach ($aNotifyTasks as $oTask) { E::ModuleNotify()->SendTask($oTask); $aArrayId[] = $oTask->getTaskId(); } $this->Log('Send notify: ' . count($aArrayId)); // * Удаляем отработанные задания E::ModuleNotify()->DeleteTaskByArrayId($aArrayId); }
/** * Рассылает уведомления о новом топике подписчикам блога * * @param ModuleBlog_EntityBlog $oBlog Объект блога * @param ModuleTopic_EntityTopic $oTopic Объект топика * @param ModuleUser_EntityUser $oUserTopic Объект пользователя */ public function SendNotifyTopicNew($oBlog, $oTopic, $oUserTopic) { $aBlogUsersResult = E::ModuleBlog()->GetBlogUsersByBlogId($oBlog->getId(), null, null); // нужно постранично пробегаться по всем /** @var ModuleBlog_EntityBlogUser[] $aBlogUsers */ $aBlogUsers = $aBlogUsersResult['collection']; foreach ($aBlogUsers as $oBlogUser) { if ($oBlogUser->getUserId() == $oUserTopic->getId()) { continue; } E::ModuleNotify()->SendTopicNewToSubscribeBlog($oBlogUser->getUser(), $oTopic, $oBlog, $oUserTopic); } //отправляем создателю блога if ($oBlog->getOwnerId() != $oUserTopic->getId()) { E::ModuleNotify()->SendTopicNewToSubscribeBlog($oBlog->getOwner(), $oTopic, $oBlog, $oUserTopic); } }
protected function _eventRecoverySend($sRecoveryCode) { /** @var ModuleUser_EntityReminder $oReminder */ if ($oReminder = E::ModuleUser()->GetReminderByCode($sRecoveryCode)) { /** @var ModuleUser_EntityUser $oUser */ if ($oReminder->IsValid() && ($oUser = E::ModuleUser()->GetUserById($oReminder->getUserId()))) { $sNewPassword = F::RandomStr(7); $oUser->setPassword($sNewPassword, true); if (E::ModuleUser()->Update($oUser)) { // Do logout of current user E::ModuleUser()->Logout(); // Close all sessions of this user E::ModuleUser()->CloseAllSessions($oUser); $oReminder->setDateUsed(F::Now()); $oReminder->setIsUsed(1); E::ModuleUser()->UpdateReminder($oReminder); E::ModuleNotify()->SendReminderPassword($oUser, $sNewPassword); $this->SetTemplateAction('reminder_confirm'); if (($sUrl = F::GetPost('return_url')) || ($sUrl = F::GetPost('return-path'))) { E::ModuleViewer()->Assign('return-path', $sUrl); } return true; } } } return false; }
/** * Формирование процесса смены емайла в профиле пользователя * * @param ModuleUser_EntityUser $oUser Объект пользователя * @param string $sMailNew Новый емайл * * @return bool|ModuleUser_EntityChangemail */ public function MakeUserChangemail($oUser, $sMailNew) { /** @var ModuleUser_EntityChangemail $oChangemail */ $oChangemail = E::GetEntity('ModuleUser_EntityChangemail'); $oChangemail->setUserId($oUser->getId()); $oChangemail->setDateAdd(date('Y-m-d H:i:s')); $oChangemail->setDateExpired(date('Y-m-d H:i:s', time() + 3 * 24 * 60 * 60)); // 3 дня для смены емайла $oChangemail->setMailFrom($oUser->getMail() ? $oUser->getMail() : ''); $oChangemail->setMailTo($sMailNew); $oChangemail->setCodeFrom(F::RandomStr(32)); $oChangemail->setCodeTo(F::RandomStr(32)); if ($this->AddUserChangemail($oChangemail)) { // * Если у пользователя раньше не было емайла, то сразу шлем подтверждение на новый емайл if (!$oChangemail->getMailFrom()) { $oChangemail->setConfirmFrom(1); E::ModuleUser()->UpdateUserChangemail($oChangemail); // * Отправляем уведомление на новый емайл E::ModuleNotify()->Send($oChangemail->getMailTo(), 'user_changemail_to.tpl', E::ModuleLang()->Get('notify_subject_user_changemail'), array('oUser' => $oUser, 'oChangemail' => $oChangemail), null, true); } else { // * Отправляем уведомление на старый емайл E::ModuleNotify()->Send($oUser, 'user_changemail_from.tpl', E::ModuleLang()->Get('notify_subject_user_changemail'), array('oUser' => $oUser, 'oChangemail' => $oChangemail), null, true); } return $oChangemail; } return false; }
/** * Показ и обработка формы приглаешний * */ protected function EventInvite() { /** * Только при активном режиме инвайтов */ if (!Config::Get('general.reg.invite')) { return parent::EventNotFound(); } $this->sMenuItemSelect = 'invite'; $this->sMenuSubItemSelect = ''; E::ModuleViewer()->AddHtmlTitle(E::ModuleLang()->Get('settings_menu_invite')); /** * Если отправили форму */ if (isPost('submit_invite')) { E::ModuleSecurity()->ValidateSendForm(); $bError = false; /** * Есть права на отправку инфайтов? */ if (!E::ModuleACL()->CanSendInvite($this->oUserCurrent) && !$this->oUserCurrent->isAdministrator()) { E::ModuleMessage()->AddError(E::ModuleLang()->Get('settings_invite_available_no'), E::ModuleLang()->Get('error')); $bError = true; } /** * Емайл корректен? */ if (!F::CheckVal(F::GetRequestStr('invite_mail'), 'mail')) { E::ModuleMessage()->AddError(E::ModuleLang()->Get('settings_invite_mail_error'), E::ModuleLang()->Get('error')); $bError = true; } /** * Запускаем выполнение хуков */ E::ModuleHook()->Run('settings_invate_send_before', array('oUser' => $this->oUserCurrent)); /** * Если нет ошибок, то отправляем инвайт */ if (!$bError) { $oInvite = E::ModuleUser()->GenerateInvite($this->oUserCurrent); E::ModuleNotify()->SendInvite($this->oUserCurrent, F::GetRequestStr('invite_mail'), $oInvite); E::ModuleMessage()->AddNoticeSingle(E::ModuleLang()->Get('settings_invite_submit_ok')); E::ModuleHook()->Run('settings_invate_send_after', array('oUser' => $this->oUserCurrent)); } } E::ModuleViewer()->Assign('iCountInviteAvailable', E::ModuleUser()->GetCountInviteAvailable($this->oUserCurrent)); E::ModuleViewer()->Assign('iCountInviteUsed', E::ModuleUser()->GetCountInviteUsed($this->oUserCurrent->getId())); }
/** * Добавление нового участника разговора (ajax) * */ public function AjaxAddTalkUser() { // * Устанавливаем формат Ajax ответа E::ModuleViewer()->SetResponseAjax('json'); $sUsers = F::GetRequestStr('users', null, 'post'); $idTalk = F::GetRequestStr('idTalk', null, 'post'); // * Если пользователь не авторизирован, возвращаем ошибку if (!E::ModuleUser()->IsAuthorization()) { E::ModuleMessage()->AddErrorSingle(E::ModuleLang()->Get('need_authorization'), E::ModuleLang()->Get('error')); return; } // * Если разговор не найден, или пользователь не является его автором (или админом), возвращаем ошибку if (!($oTalk = E::ModuleTalk()->GetTalkById($idTalk)) || $oTalk->getUserId() != $this->oUserCurrent->getId() && !$this->oUserCurrent->isAdministrator()) { E::ModuleMessage()->AddErrorSingle(E::ModuleLang()->Get('talk_not_found'), E::ModuleLang()->Get('error')); return; } // * Получаем список всех участников разговора $aTalkUsers = $oTalk->getTalkUsers(); $aUsers = explode(',', $sUsers); // * Получаем список пользователей, которые не принимают письма $aUserInBlacklist = E::ModuleTalk()->GetBlacklistByTargetId($this->oUserCurrent->getId()); // * Ограничения на максимальное число участников разговора if (count($aTalkUsers) >= Config::Get('module.talk.max_users') && !$this->oUserCurrent->isAdministrator()) { E::ModuleMessage()->AddError(E::ModuleLang()->Get('talk_create_users_error_many'), E::ModuleLang()->Get('error')); return; } // * Обрабатываем добавление по каждому переданному логину пользователя foreach ($aUsers as $sUser) { $sUser = trim($sUser); if ($sUser == '') { continue; } // * Попытка добавить себя if (strtolower($sUser) == strtolower($this->oUserCurrent->getLogin())) { $aResult[] = array('bStateError' => true, 'sMsgTitle' => E::ModuleLang()->Get('error'), 'sMsg' => E::ModuleLang()->Get('talk_speaker_add_self')); continue; } if (($oUser = E::ModuleUser()->GetUserByLogin($sUser)) && $oUser->getActivate() == 1) { if (!in_array($oUser->getId(), $aUserInBlacklist)) { if (array_key_exists($oUser->getId(), $aTalkUsers)) { switch ($aTalkUsers[$oUser->getId()]->getUserActive()) { // * Если пользователь ранее был удален админом разговора, то добавляем его снова case ModuleTalk::TALK_USER_DELETE_BY_AUTHOR: if (E::ModuleTalk()->AddTalkUser(E::GetEntity('Talk_TalkUser', array('talk_id' => $idTalk, 'user_id' => $oUser->getId(), 'date_last' => null, 'talk_user_active' => ModuleTalk::TALK_USER_ACTIVE)))) { E::ModuleNotify()->SendTalkNew($oUser, $this->oUserCurrent, $oTalk); $aResult[] = array('bStateError' => false, 'sMsgTitle' => E::ModuleLang()->Get('attention'), 'sMsg' => E::ModuleLang()->Get('talk_speaker_add_ok', array('login', htmlspecialchars($sUser))), 'sUserId' => $oUser->getId(), 'sUserLogin' => $oUser->getLogin(), 'sUserLink' => $oUser->getUserWebPath(), 'sUserWebPath' => $oUser->getUserWebPath(), 'sUserAvatar48' => $oUser->getAvatarUrl(48)); $bState = true; } else { $aResult[] = array('bStateError' => true, 'sMsgTitle' => E::ModuleLang()->Get('error'), 'sMsg' => E::ModuleLang()->Get('system_error')); } break; // * Если пользователь является активным участником разговора, возвращаем ошибку // * Если пользователь является активным участником разговора, возвращаем ошибку case ModuleTalk::TALK_USER_ACTIVE: $aResult[] = array('bStateError' => true, 'sMsgTitle' => E::ModuleLang()->Get('error'), 'sMsg' => E::ModuleLang()->Get('talk_speaker_user_already_exist', array('login' => htmlspecialchars($sUser)))); break; // * Если пользователь удалил себя из разговора самостоятельно, то блокируем повторное добавление // * Если пользователь удалил себя из разговора самостоятельно, то блокируем повторное добавление case ModuleTalk::TALK_USER_DELETE_BY_SELF: $aResult[] = array('bStateError' => true, 'sMsgTitle' => E::ModuleLang()->Get('error'), 'sMsg' => E::ModuleLang()->Get('talk_speaker_delete_by_self', array('login' => htmlspecialchars($sUser)))); break; default: $aResult[] = array('bStateError' => true, 'sMsgTitle' => E::ModuleLang()->Get('error'), 'sMsg' => E::ModuleLang()->Get('system_error')); } } elseif (E::ModuleTalk()->AddTalkUser(E::GetEntity('Talk_TalkUser', array('talk_id' => $idTalk, 'user_id' => $oUser->getId(), 'date_last' => null, 'talk_user_active' => ModuleTalk::TALK_USER_ACTIVE)))) { E::ModuleNotify()->SendTalkNew($oUser, $this->oUserCurrent, $oTalk); $aResult[] = array('bStateError' => false, 'sMsgTitle' => E::ModuleLang()->Get('attention'), 'sMsg' => E::ModuleLang()->Get('talk_speaker_add_ok', array('login', htmlspecialchars($sUser))), 'sUserId' => $oUser->getId(), 'sUserLogin' => $oUser->getLogin(), 'sUserLink' => $oUser->getUserWebPath(), 'sUserWebPath' => $oUser->getUserWebPath(), 'sUserAvatar48' => $oUser->getAvatarUrl(48)); $bState = true; } else { $aResult[] = array('bStateError' => true, 'sMsgTitle' => E::ModuleLang()->Get('error'), 'sMsg' => E::ModuleLang()->Get('system_error')); } } else { // * Добавляем пользователь не принимает сообщения $aResult[] = array('bStateError' => true, 'sMsgTitle' => E::ModuleLang()->Get('error'), 'sMsg' => E::ModuleLang()->Get('talk_user_in_blacklist', array('login' => htmlspecialchars($sUser)))); } } else { // * Пользователь не найден в базе данных или не активен $aResult[] = array('bStateError' => true, 'sMsgTitle' => E::ModuleLang()->Get('error'), 'sMsg' => E::ModuleLang()->Get('user_not_found', array('login' => htmlspecialchars($sUser)))); } } // * Передаем во вьевер массив результатов обработки по каждому пользователю E::ModuleViewer()->AssignAjax('aUsers', $aResult); }
public function EventAjaxUserList() { E::ModuleViewer()->SetResponseAjax('json'); if ($this->IsPost()) { $sList = trim($this->GetPost('invite_listmail')); if ($aList = F::Array_Str2Array($sList, "\n", true)) { $iSentCount = 0; foreach ($aList as $iKey => $sMail) { if (F::CheckVal($sMail, 'mail')) { $oInvite = E::ModuleUser()->GenerateInvite($this->oUserCurrent); if (E::ModuleNotify()->SendInvite($this->oUserCurrent, $sMail, $oInvite)) { unset($aList[$iKey]); $iSentCount++; } } } E::ModuleMessage()->AddNotice(E::ModuleLang()->Get('action.admin.invaite_mail_done', array('num' => $iSentCount)), null, true); if ($aList) { E::ModuleMessage()->AddError(E::ModuleLang()->Get('action.admin.invaite_mail_err', array('num' => count($aList))), null, true); } } } else { E::ModuleMessage()->AddErrorSingle(E::ModuleLang()->Get('system_error')); } }
/** * Формирует и отправляет личное сообщение * * @param string $sTitle Заголовок сообщения * @param string $sText Текст сообщения * @param int|ModuleUser_EntityUser $oUserFrom Пользователь от которого отправляем * @param array|int|ModuleUser_EntityUser $aUserTo Пользователь которому отправляем * @param bool $bSendNotify Отправлять или нет уведомление на емайл * @param bool $bUseBlacklist Исклюать или нет пользователей из блэклиста * * @return ModuleTalk_EntityTalk|bool */ public function SendTalk($sTitle, $sText, $oUserFrom, $aUserTo, $bSendNotify = true, $bUseBlacklist = true) { $iUserIdFrom = $oUserFrom instanceof ModuleUser_EntityUser ? $oUserFrom->getId() : (int) $oUserFrom; if (!is_array($aUserTo)) { $aUserTo = array($aUserTo); } $aUserIdTo = array($iUserIdFrom); if ($bUseBlacklist) { $aUserInBlacklist = $this->GetBlacklistByTargetId($iUserIdFrom); } foreach ($aUserTo as $oUserTo) { $nUserIdTo = $oUserTo instanceof ModuleUser_EntityUser ? $oUserTo->getId() : (int) $oUserTo; if (!$bUseBlacklist || !in_array($nUserIdTo, $aUserInBlacklist)) { $aUserIdTo[] = $nUserIdTo; } } $aUserIdTo = array_unique($aUserIdTo); if (!empty($aUserIdTo)) { $oTalk = E::GetEntity('Talk'); $oTalk->setUserId($iUserIdFrom); $oTalk->setTitle($sTitle); $oTalk->setText($sText); $oTalk->setDate(date('Y-m-d H:i:s')); $oTalk->setDateLast(date('Y-m-d H:i:s')); $oTalk->setUserIdLast($oTalk->getUserId()); $oTalk->setUserIp(F::GetUserIp()); if ($oTalk = $this->AddTalk($oTalk)) { foreach ($aUserIdTo as $iUserId) { $oTalkUser = E::GetEntity('Talk_TalkUser'); $oTalkUser->setTalkId($oTalk->getId()); $oTalkUser->setUserId($iUserId); if ($iUserId == $iUserIdFrom) { $oTalkUser->setDateLast(date('Y-m-d H:i:s')); } else { $oTalkUser->setDateLast(null); } $this->AddTalkUser($oTalkUser); if ($bSendNotify) { if ($iUserId != $iUserIdFrom) { $oUserFrom = E::ModuleUser()->GetUserById($iUserIdFrom); $oUserToMail = E::ModuleUser()->GetUserById($iUserId); E::ModuleNotify()->SendTalkNew($oUserToMail, $oUserFrom, $oTalk); } } } return $oTalk; } } return false; }
/** * Обработка Ajax регистрации */ protected function EventAjaxRegistration() { // * Устанавливаем формат Ajax ответа E::ModuleViewer()->SetResponseAjax('json'); E::ModuleSecurity()->ValidateSendForm(); // * Создаем объект пользователя и устанавливаем сценарий валидации /** @var ModuleUser_EntityUser $oUser */ $oUser = E::GetEntity('ModuleUser_EntityUser'); $oUser->_setValidateScenario('registration'); // * Заполняем поля (данные) $oUser->setLogin($this->GetPost('login')); $oUser->setMail($this->GetPost('mail')); $oUser->setPassword($this->GetPost('password')); $oUser->setPasswordConfirm($this->GetPost('password_confirm')); $oUser->setCaptcha($this->GetPost('captcha')); $oUser->setDateRegister(F::Now()); $oUser->setIpRegister(F::GetUserIp()); // * Если используется активация, то генерим код активации if (Config::Get('general.reg.activation')) { $oUser->setActivate(0); $oUser->setActivationKey(F::RandomStr()); } else { $oUser->setActivate(1); $oUser->setActivationKey(null); } E::ModuleHook()->Run('registration_validate_before', array('oUser' => $oUser)); // * Запускаем валидацию if ($oUser->_Validate()) { // Сбросим капчу // issue#342. E::ModuleSession()->Drop(E::ModuleCaptcha()->GetKeyName()); E::ModuleHook()->Run('registration_validate_after', array('oUser' => $oUser)); $oUser->setPassword($oUser->getPassword(), true); if ($this->_addUser($oUser)) { E::ModuleHook()->Run('registration_after', array('oUser' => $oUser)); // * Подписываем пользователя на дефолтные события в ленте активности E::ModuleStream()->SwitchUserEventDefaultTypes($oUser->getId()); // * Если юзер зарегистрировался по приглашению то обновляем инвайт if (Config::Get('general.reg.invite') && ($oInvite = E::ModuleUser()->GetInviteByCode($this->GetInviteRegister()))) { $oInvite->setUserToId($oUser->getId()); $oInvite->setDateUsed(F::Now()); $oInvite->setUsed(1); E::ModuleUser()->UpdateInvite($oInvite); } // * Если стоит регистрация с активацией то проводим её if (Config::Get('general.reg.activation')) { // * Отправляем на мыло письмо о подтверждении регистрации E::ModuleNotify()->SendRegistrationActivate($oUser, F::GetRequestStr('password')); E::ModuleViewer()->AssignAjax('sUrlRedirect', R::GetPath('registration') . 'confirm/'); } else { E::ModuleNotify()->SendRegistration($oUser, F::GetRequestStr('password')); $oUser = E::ModuleUser()->GetUserById($oUser->getId()); // * Сразу авторизуем E::ModuleUser()->Authorization($oUser, false); $this->DropInviteRegister(); // * Определяем URL для редиректа после авторизации $sUrl = Config::Get('module.user.redirect_after_registration'); if (F::GetRequestStr('return-path')) { $sUrl = F::GetRequestStr('return-path'); } E::ModuleViewer()->AssignAjax('sUrlRedirect', $sUrl ? $sUrl : Config::Get('path.root.url')); E::ModuleMessage()->AddNoticeSingle(E::ModuleLang()->Get('registration_ok')); } } else { E::ModuleMessage()->AddErrorSingle(E::ModuleLang()->Get('system_error')); return; } } else { // * Получаем ошибки E::ModuleViewer()->AssignAjax('aErrors', $oUser->_getValidateErrors()); } }
/** * Выполняет отправку приглашения в блог * (по внутренней почте и на email) * * @param ModuleBlog_EntityBlog $oBlog * @param ModuleUser_EntityUser $oUser */ protected function SendBlogInvite($oBlog, $oUser) { $sTitle = E::ModuleLang()->Get('blog_user_invite_title', array('blog_title' => $oBlog->getTitle())); F::IncludeLib('XXTEA/encrypt.php'); // Формируем код подтверждения в URL $sCode = $oBlog->getId() . '_' . $oUser->getId(); $sCode = rawurlencode(base64_encode(xxtea_encrypt($sCode, Config::Get('module.blog.encrypt')))); $aPath = array('accept' => R::GetPath('blog') . 'invite/accept/?code=' . $sCode, 'reject' => R::GetPath('blog') . 'invite/reject/?code=' . $sCode); // Сформируем название типа блога на языке приложения. // Это может быть либо название, либо текстовка. $sBlogType = mb_strtolower(preg_match('~^\\{\\{(.*)\\}\\}$~', $sBlogType = $oBlog->getBlogType()->getTypeName(), $aMatches) ? E::ModuleLang()->Get($aMatches[1]) : $sBlogType, 'UTF-8'); $sText = E::ModuleLang()->Get('blog_user_invite_text', array('login' => $this->oUserCurrent->getLogin(), 'accept_path' => $aPath['accept'], 'reject_path' => $aPath['reject'], 'blog_title' => $oBlog->getTitle(), 'blog_type' => $sBlogType)); $oTalk = E::ModuleTalk()->SendTalk($sTitle, $sText, $this->oUserCurrent, array($oUser), false, false); // Отправляем пользователю заявку E::ModuleNotify()->SendBlogUserInvite($oUser, $this->oUserCurrent, $oBlog, R::GetPath('talk') . 'read/' . $oTalk->getId() . '/'); // Удаляем отправляющего юзера из переписки E::ModuleTalk()->DeleteTalkUserByArray($oTalk->getId(), $this->oUserCurrent->getId()); }
/** * Производит отправку писем по подписчикам подписки * * @param int $sTargetType Тип объекта подписки * @param int $iTargetId ID объекта подписки * @param string $sTemplate Имя шаблона письма, например, mail.tpl * @param string $sTitle Заголовок письма * @param array $aParams Параметра для передачи в шаблон письма * @param array $aExcludeMail Список емайлов на которые НЕ нужно отправлять * @param string $sPluginName Название или класс плагина для корректной отправки */ public function Send($sTargetType, $iTargetId, $sTemplate, $sTitle, $aParams = array(), $aExcludeMail = array(), $sPluginName = null) { $iPage = 1; $aSubscribes = E::ModuleSubscribe()->GetSubscribes(array('target_type' => $sTargetType, 'target_id' => $iTargetId, 'status' => 1, 'exclude_mail' => $aExcludeMail), array(), $iPage, 20); while ($aSubscribes['collection']) { $iPage++; foreach ($aSubscribes['collection'] as $oSubscribe) { $aParams['sSubscribeKey'] = $oSubscribe->getKey(); E::ModuleNotify()->Send($oSubscribe->getMail(), $sTemplate, $sTitle, $aParams, $sPluginName); } $aSubscribes = E::ModuleSubscribe()->GetSubscribes(array('target_type' => $sTargetType, 'target_id' => $iTargetId, 'status' => 1, 'exclude_mail' => $aExcludeMail), array(), $iPage, 20); } }
/** * Обработка подтверждения старого емайла при его смене */ public function EventChangemailConfirmFrom() { if (!($oChangemail = E::ModuleUser()->GetUserChangemailByCodeFrom($this->GetParamEventMatch(1, 0)))) { return parent::EventNotFound(); } if ($oChangemail->getConfirmFrom() || strtotime($oChangemail->getDateExpired()) < time()) { return parent::EventNotFound(); } $oChangemail->setConfirmFrom(1); E::ModuleUser()->UpdateUserChangemail($oChangemail); /** * Отправляем уведомление */ $oUser = E::ModuleUser()->GetUserById($oChangemail->getUserId()); E::ModuleNotify()->Send($oChangemail->getMailTo(), 'user_changemail_to.tpl', E::ModuleLang()->Get('notify_subject_user_changemail'), array('oUser' => $oUser, 'oChangemail' => $oChangemail), null, true); E::ModuleViewer()->Assign('sText', E::ModuleLang()->Get('settings_profile_mail_change_to_notice')); // Исправление ошибки смены email {@link https://github.com/altocms/altocms/issues/260} E::ModuleViewer()->Assign('oUserProfile', $oUser); $this->SetTemplateAction('changemail_confirm'); }