/** * Send an admin notification e-mail * * @param integer $intId * @param array $arrData */ protected function sendAdminNotification($intId, $arrData) { $objEmail = new \Email(); $objEmail->from = $GLOBALS['TL_ADMIN_EMAIL']; $objEmail->fromName = $GLOBALS['TL_ADMIN_NAME']; $objEmail->subject = sprintf($GLOBALS['TL_LANG']['MSC']['adminSubject'], \Idna::decode(\Environment::get('host'))); $strData = "\n\n"; // Add user details foreach ($arrData as $k => $v) { if ($k == 'password' || $k == 'tstamp' || $k == 'activation' || $k == 'dateAdded') { continue; } $v = \StringUtil::deserialize($v); if ($k == 'dateOfBirth' && strlen($v)) { $v = \Date::parse(\Config::get('dateFormat'), $v); } $strData .= $GLOBALS['TL_LANG']['tl_member'][$k][0] . ': ' . (is_array($v) ? implode(', ', $v) : $v) . "\n"; } $objEmail->text = sprintf($GLOBALS['TL_LANG']['MSC']['adminText'], $intId, $strData . "\n") . "\n"; $objEmail->sendTo($GLOBALS['TL_ADMIN_EMAIL']); $this->log('A new user (ID ' . $intId . ') has registered on the website', __METHOD__, TL_ACCESS); }
/** * Create a new user and redirect * * @param MemberModel $objMember */ protected function sendPasswordLink($objMember) { $confirmationId = md5(uniqid(mt_rand(), true)); // Store the confirmation ID $objMember = \MemberModel::findByPk($objMember->id); $objMember->activation = $confirmationId; $objMember->save(); // Prepare the simple token data $arrData = $objMember->row(); $arrData['domain'] = \Idna::decode(\Environment::get('host')); $arrData['link'] = \Idna::decode(\Environment::get('base')) . \Environment::get('request') . (strpos(\Environment::get('request'), '?') !== false ? '&' : '?') . 'token=' . $confirmationId; // Send e-mail $objEmail = new \Email(); $objEmail->from = $GLOBALS['TL_ADMIN_EMAIL']; $objEmail->fromName = $GLOBALS['TL_ADMIN_NAME']; $objEmail->subject = sprintf($GLOBALS['TL_LANG']['MSC']['passwordSubject'], \Idna::decode(\Environment::get('host'))); $objEmail->text = \StringUtil::parseSimpleTokens($this->reg_password, $arrData); $objEmail->sendTo($objMember->email); $this->log('A new password has been requested for user ID ' . $objMember->id . ' (' . \Idna::decodeEmail($objMember->email) . ')', __METHOD__, TL_ACCESS); // Check whether there is a jumpTo page if (($objJumpTo = $this->objModel->getRelated('jumpTo')) instanceof PageModel) { $this->jumpToOrReload($objJumpTo->row()); } $this->reload(); }
/** * Compile the newsletter and send it * * @param Email $objEmail * @param Database\Result|object $objNewsletter * @param array $arrRecipient * @param string $text * @param string $html * @param string $css * * @return string */ protected function sendNewsletter(Email $objEmail, Database\Result $objNewsletter, $arrRecipient, $text, $html, $css = null) { // Prepare the text content $objEmail->text = \StringUtil::parseSimpleTokens($text, $arrRecipient); if (!$objNewsletter->sendText) { // Default template if ($objNewsletter->template == '') { $objNewsletter->template = 'mail_default'; } /** @var BackendTemplate|object $objTemplate */ $objTemplate = new \BackendTemplate($objNewsletter->template); $objTemplate->setData($objNewsletter->row()); $objTemplate->title = $objNewsletter->subject; $objTemplate->body = \StringUtil::parseSimpleTokens($html, $arrRecipient); $objTemplate->charset = \Config::get('characterSet'); $objTemplate->recipient = $arrRecipient['email']; // Deprecated since Contao 4.0, to be removed in Contao 5.0 $objTemplate->css = $css; // Parse template $objEmail->html = $objTemplate->parse(); $objEmail->imageDir = TL_ROOT . '/'; } // Deactivate invalid addresses try { $objEmail->sendTo($arrRecipient['email']); } catch (\Swift_RfcComplianceException $e) { $_SESSION['REJECTED_RECIPIENTS'][] = $arrRecipient['email']; } // Rejected recipients if ($objEmail->hasFailures()) { $_SESSION['REJECTED_RECIPIENTS'][] = $arrRecipient['email']; } // HOOK: add custom logic if (isset($GLOBALS['TL_HOOKS']['sendNewsletter']) && is_array($GLOBALS['TL_HOOKS']['sendNewsletter'])) { foreach ($GLOBALS['TL_HOOKS']['sendNewsletter'] as $callback) { $this->import($callback[0]); $this->{$callback[0]}->{$callback[1]}($objEmail, $objNewsletter, $arrRecipient, $text, $html); } } }
/** * Notify the subscribers of new comments * * @param CommentsModel $objComment */ public static function notifyCommentsSubscribers(CommentsModel $objComment) { // Notified already if ($objComment->notified) { return; } $objNotify = \CommentsNotifyModel::findActiveBySourceAndParent($objComment->source, $objComment->parent); // No subscriptions if ($objNotify === null) { return; } while ($objNotify->next()) { // Don't notify the commentor about his own comment if ($objNotify->email == $objComment->email) { continue; } // Prepare the URL $strUrl = \Idna::decode(\Environment::get('base')) . $objNotify->url; $objEmail = new \Email(); $objEmail->from = $GLOBALS['TL_ADMIN_EMAIL']; $objEmail->fromName = $GLOBALS['TL_ADMIN_NAME']; $objEmail->subject = sprintf($GLOBALS['TL_LANG']['MSC']['com_notifySubject'], \Idna::decode(\Environment::get('host'))); $objEmail->text = sprintf($GLOBALS['TL_LANG']['MSC']['com_notifyMessage'], $objNotify->name, $strUrl, $strUrl . '?token=' . $objNotify->tokenRemove); $objEmail->sendTo($objNotify->email); } $objComment->notified = 1; $objComment->save(); }
/** * Remove the recipient * * @param string $strEmail * @param array $arrRemove */ protected function removeRecipient($strEmail, $arrRemove) { // Remove the subscriptions if (($objRemove = \NewsletterRecipientsModel::findByEmailAndPids($strEmail, $arrRemove)) !== null) { while ($objRemove->next()) { $strHash = md5($objRemove->email); // Add a blacklist entry (see #4999) if (($objBlacklist = \NewsletterBlacklistModel::findByHashAndPid($strHash, $objRemove->pid)) === null) { $objBlacklist = new \NewsletterBlacklistModel(); $objBlacklist->pid = $objRemove->pid; $objBlacklist->hash = $strHash; $objBlacklist->save(); } $objRemove->delete(); } } // Get the channels $objChannels = \NewsletterChannelModel::findByIds($arrRemove); $arrChannels = $objChannels->fetchEach('title'); // HOOK: post unsubscribe callback if (isset($GLOBALS['TL_HOOKS']['removeRecipient']) && is_array($GLOBALS['TL_HOOKS']['removeRecipient'])) { foreach ($GLOBALS['TL_HOOKS']['removeRecipient'] as $callback) { $this->import($callback[0]); $this->{$callback[0]}->{$callback[1]}($strEmail, $arrRemove); } } // Prepare the simple token data $arrData = array(); $arrData['domain'] = \Idna::decode(\Environment::get('host')); $arrData['channel'] = $arrData['channels'] = implode("\n", $arrChannels); // Confirmation e-mail $objEmail = new \Email(); $objEmail->from = $GLOBALS['TL_ADMIN_EMAIL']; $objEmail->fromName = $GLOBALS['TL_ADMIN_NAME']; $objEmail->subject = sprintf($GLOBALS['TL_LANG']['MSC']['nl_subject'], \Idna::decode(\Environment::get('host'))); $objEmail->text = \StringUtil::parseSimpleTokens($this->nl_unsubscribe, $arrData); $objEmail->sendTo($strEmail); // Redirect to the jumpTo page if ($this->jumpTo && ($objTarget = $this->objModel->getRelated('jumpTo')) !== null) { $this->redirect($this->generateFrontendUrl($objTarget->row())); } \System::getContainer()->get('session')->getFlashBag()->set('nl_removed', $GLOBALS['TL_LANG']['MSC']['nl_removed']); $this->reload(); }
/** * @param $strRecipient * @return bool */ public function sendTo($strRecipient) { if (!$this->strType) { return false; } $objEmail = new ContaoEmail(); $objEmail->from = $GLOBALS['TL_CONFIG']['emailFrom']; $strEmailFromName = Translator::translateValue($GLOBALS['TL_CONFIG']['emailFromName'], $this->strForceLanguage); // Add sender name if ($strEmailFromName != '') { $objEmail->fromName = $strEmailFromName; } $strSubject = $this->getContent('subject'); $strContent = $this->getContent(); $objEmail->embedImages = true; $objEmail->imageDir = TL_ROOT . '/'; $objEmail->subject = $strSubject; // Prepare html template $objTemplate = new BackendTemplate($this->getEmailTemplate()); $objTemplate->title = $strSubject; $objTemplate->body = $strContent; $objTemplate->charset = $GLOBALS['TL_CONFIG']['characterSet']; $objTemplate->css = ''; $objTemplate->recipient = $strRecipient; // Parse html template $objEmail->html = $objTemplate->parse(); // Send email try { $objEmail->sendTo($strRecipient); } catch (\Swift_RfcComplianceException $e) { return false; } // Rejected recipients if ($objEmail->hasFailures()) { return false; } return true; }
/** * Process form data, store it in the session and redirect to the jumpTo page * * @param array $arrSubmitted * @param array $arrLabels * @param array $arrFields */ protected function processFormData($arrSubmitted, $arrLabels, $arrFields) { // HOOK: prepare form data callback if (isset($GLOBALS['TL_HOOKS']['prepareFormData']) && is_array($GLOBALS['TL_HOOKS']['prepareFormData'])) { foreach ($GLOBALS['TL_HOOKS']['prepareFormData'] as $callback) { $this->import($callback[0]); $this->{$callback[0]}->{$callback[1]}($arrSubmitted, $arrLabels, $arrFields, $this); } } // Send form data via e-mail if ($this->sendViaEmail) { $keys = array(); $values = array(); $fields = array(); $message = ''; foreach ($arrSubmitted as $k => $v) { if ($k == 'cc') { continue; } $v = \StringUtil::deserialize($v); // Skip empty fields if ($this->skipEmpty && !is_array($v) && !strlen($v)) { continue; } // Add field to message $message .= (isset($arrLabels[$k]) ? $arrLabels[$k] : ucfirst($k)) . ': ' . (is_array($v) ? implode(', ', $v) : $v) . "\n"; // Prepare XML file if ($this->format == 'xml') { $fields[] = array('name' => $k, 'values' => is_array($v) ? $v : array($v)); } // Prepare CSV file if ($this->format == 'csv') { $keys[] = $k; $values[] = is_array($v) ? implode(',', $v) : $v; } } $recipients = \StringUtil::splitCsv($this->recipient); // Format recipients foreach ($recipients as $k => $v) { $recipients[$k] = str_replace(array('[', ']', '"'), array('<', '>', ''), $v); } $email = new \Email(); // Get subject and message if ($this->format == 'email') { $message = $arrSubmitted['message']; $email->subject = $arrSubmitted['subject']; } // Set the admin e-mail as "from" address $email->from = $GLOBALS['TL_ADMIN_EMAIL']; $email->fromName = $GLOBALS['TL_ADMIN_NAME']; // Get the "reply to" address if (strlen(\Input::post('email', true))) { $replyTo = \Input::post('email', true); // Add name if (strlen(\Input::post('name'))) { $replyTo = '"' . \Input::post('name') . '" <' . $replyTo . '>'; } $email->replyTo($replyTo); } // Fallback to default subject if (!strlen($email->subject)) { $email->subject = $this->replaceInsertTags($this->subject, false); } // Send copy to sender if (strlen($arrSubmitted['cc'])) { $email->sendCc(\Input::post('email', true)); unset($_SESSION['FORM_DATA']['cc']); } // Attach XML file if ($this->format == 'xml') { /** @var FrontendTemplate|object $objTemplate */ $objTemplate = new \FrontendTemplate('form_xml'); $objTemplate->fields = $fields; $objTemplate->charset = \Config::get('characterSet'); $email->attachFileFromString($objTemplate->parse(), 'form.xml', 'application/xml'); } // Attach CSV file if ($this->format == 'csv') { $email->attachFileFromString(\StringUtil::decodeEntities('"' . implode('";"', $keys) . '"' . "\n" . '"' . implode('";"', $values) . '"'), 'form.csv', 'text/comma-separated-values'); } $uploaded = ''; // Attach uploaded files if (!empty($_SESSION['FILES'])) { foreach ($_SESSION['FILES'] as $file) { // Add a link to the uploaded file if ($file['uploaded']) { $uploaded .= "\n" . \Environment::get('base') . str_replace(TL_ROOT . '/', '', dirname($file['tmp_name'])) . '/' . rawurlencode($file['name']); continue; } $email->attachFileFromString(file_get_contents($file['tmp_name']), $file['name'], $file['type']); } } $uploaded = strlen(trim($uploaded)) ? "\n\n---\n" . $uploaded : ''; $email->text = \StringUtil::decodeEntities(trim($message)) . $uploaded . "\n\n"; // Send the e-mail try { $email->sendTo($recipients); } catch (\Swift_SwiftException $e) { $this->log('Form "' . $this->title . '" could not be sent: ' . $e->getMessage(), __METHOD__, TL_ERROR); } } // Store the values in the database if ($this->storeValues && $this->targetTable != '') { $arrSet = array(); // Add the timestamp if ($this->Database->fieldExists('tstamp', $this->targetTable)) { $arrSet['tstamp'] = time(); } // Fields foreach ($arrSubmitted as $k => $v) { if ($k != 'cc' && $k != 'id') { $arrSet[$k] = $v; // Convert date formats into timestamps (see #6827) if ($arrSet[$k] != '' && in_array($arrFields[$k]->rgxp, array('date', 'time', 'datim'))) { $objDate = new \Date($arrSet[$k], \Date::getFormatFromRgxp($arrFields[$k]->rgxp)); $arrSet[$k] = $objDate->tstamp; } } } // Files if (!empty($_SESSION['FILES'])) { foreach ($_SESSION['FILES'] as $k => $v) { if ($v['uploaded']) { $arrSet[$k] = str_replace(TL_ROOT . '/', '', $v['tmp_name']); } } } // HOOK: store form data callback if (isset($GLOBALS['TL_HOOKS']['storeFormData']) && is_array($GLOBALS['TL_HOOKS']['storeFormData'])) { foreach ($GLOBALS['TL_HOOKS']['storeFormData'] as $callback) { $this->import($callback[0]); $arrSet = $this->{$callback[0]}->{$callback[1]}($arrSet, $this); } } // Set the correct empty value (see #6284, #6373) foreach ($arrSet as $k => $v) { if ($v === '') { $arrSet[$k] = \Widget::getEmptyValueByFieldType($GLOBALS['TL_DCA'][$this->targetTable]['fields'][$k]['sql']); } } // Do not use Models here (backwards compatibility) $this->Database->prepare("INSERT INTO " . $this->targetTable . " %s")->set($arrSet)->execute(); } // Store all values in the session foreach (array_keys($_POST) as $key) { $_SESSION['FORM_DATA'][$key] = $this->allowTags ? \Input::postHtml($key, true) : \Input::post($key, true); } $arrFiles = $_SESSION['FILES']; // HOOK: process form data callback if (isset($GLOBALS['TL_HOOKS']['processFormData']) && is_array($GLOBALS['TL_HOOKS']['processFormData'])) { foreach ($GLOBALS['TL_HOOKS']['processFormData'] as $callback) { $this->import($callback[0]); $this->{$callback[0]}->{$callback[1]}($arrSubmitted, $this->arrData, $arrFiles, $arrLabels, $this); } } $_SESSION['FILES'] = array(); // DO NOT CHANGE // Add a log entry if (FE_USER_LOGGED_IN) { $this->import('FrontendUser', 'User'); $this->log('Form "' . $this->title . '" has been submitted by "' . $this->User->username . '".', __METHOD__, TL_FORMS); } else { $this->log('Form "' . $this->title . '" has been submitted by ' . \System::anonymizeIp(\Environment::get('ip')) . '.', __METHOD__, TL_FORMS); } // Check whether there is a jumpTo page if (($objJumpTo = $this->objModel->getRelated('jumpTo')) instanceof PageModel) { $this->jumpToOrReload($objJumpTo->row()); } $this->reload(); }
/** * Try to login the current user * * @return boolean True if the user could be logged in */ public function login() { \System::loadLanguageFile('default'); // Do not continue if username or password are missing if (empty($_POST['username']) || empty($_POST['password'])) { return false; } // Load the user object if ($this->findBy('username', \Input::post('username', true)) == false) { $blnLoaded = false; // HOOK: pass credentials to callback functions if (isset($GLOBALS['TL_HOOKS']['importUser']) && is_array($GLOBALS['TL_HOOKS']['importUser'])) { foreach ($GLOBALS['TL_HOOKS']['importUser'] as $callback) { $this->import($callback[0], 'objImport', true); $blnLoaded = $this->objImport->{$callback[1]}(\Input::post('username', true), \Input::postUnsafeRaw('password'), $this->strTable); // Load successfull if ($blnLoaded === true) { break; } } } // Return if the user still cannot be loaded if (!$blnLoaded || $this->findBy('username', \Input::post('username', true)) == false) { \Message::addError($GLOBALS['TL_LANG']['ERR']['invalidLogin']); $this->log('Could not find user "' . \Input::post('username', true) . '"', __METHOD__, TL_ACCESS); return false; } } $time = time(); // Set the user language if (\Input::post('language')) { $this->language = \Input::post('language'); } // Lock the account if there are too many login attempts if ($this->loginCount < 1) { $this->locked = $time; $this->loginCount = \Config::get('loginCount'); $this->save(); // Add a log entry and the error message, because checkAccountStatus() will not be called (see #4444) $this->log('User "' . $this->username . '" has been locked for ' . ceil(\Config::get('lockPeriod') / 60) . ' minutes', __METHOD__, TL_ACCESS); \Message::addError(sprintf($GLOBALS['TL_LANG']['ERR']['accountLocked'], ceil(($this->locked + \Config::get('lockPeriod') - $time) / 60))); // Send admin notification if (\Config::get('adminEmail') != '') { $objEmail = new \Email(); $objEmail->subject = $GLOBALS['TL_LANG']['MSC']['lockedAccount'][0]; $objEmail->text = sprintf($GLOBALS['TL_LANG']['MSC']['lockedAccount'][1], $this->username, TL_MODE == 'FE' ? $this->firstname . " " . $this->lastname : $this->name, \Idna::decode(\Environment::get('base')), ceil(\Config::get('lockPeriod') / 60)); $objEmail->sendTo(\Config::get('adminEmail')); } return false; } // Check the account status if ($this->checkAccountStatus() == false) { return false; } // The password has been generated with crypt() if (\Encryption::test($this->password)) { $blnAuthenticated = \Encryption::verify(\Input::postUnsafeRaw('password'), $this->password); } else { list($strPassword, $strSalt) = explode(':', $this->password); $blnAuthenticated = $strSalt == '' ? $strPassword === sha1(\Input::postUnsafeRaw('password')) : $strPassword === sha1($strSalt . \Input::postUnsafeRaw('password')); // Store a SHA-512 encrpyted version of the password if ($blnAuthenticated) { $this->password = \Encryption::hash(\Input::postUnsafeRaw('password')); } } // HOOK: pass credentials to callback functions if (!$blnAuthenticated && isset($GLOBALS['TL_HOOKS']['checkCredentials']) && is_array($GLOBALS['TL_HOOKS']['checkCredentials'])) { foreach ($GLOBALS['TL_HOOKS']['checkCredentials'] as $callback) { $this->import($callback[0], 'objAuth', true); $blnAuthenticated = $this->objAuth->{$callback[1]}(\Input::post('username', true), \Input::postUnsafeRaw('password'), $this); // Authentication successfull if ($blnAuthenticated === true) { break; } } } // Redirect if the user could not be authenticated if (!$blnAuthenticated) { --$this->loginCount; $this->save(); \Message::addError($GLOBALS['TL_LANG']['ERR']['invalidLogin']); $this->log('Invalid password submitted for username "' . $this->username . '"', __METHOD__, TL_ACCESS); return false; } $this->setUserFromDb(); // Update the record $this->lastLogin = $this->currentLogin; $this->currentLogin = $time; $this->loginCount = \Config::get('loginCount'); $this->save(); // Generate the session $this->regenerateSessionId(); $this->generateSession(); $this->log('User "' . $this->username . '" has logged in', __METHOD__, TL_ACCESS); // HOOK: post login callback if (isset($GLOBALS['TL_HOOKS']['postLogin']) && is_array($GLOBALS['TL_HOOKS']['postLogin'])) { foreach ($GLOBALS['TL_HOOKS']['postLogin'] as $callback) { $this->import($callback[0], 'objLogin', true); $this->objLogin->{$callback[1]}($this); } } return true; }
/** * Add a new recipient * * @param string $strEmail * @param array $arrNew */ protected function addRecipient($strEmail, $arrNew) { // Remove old subscriptions that have not been activated yet if (($objOld = \NewsletterRecipientsModel::findBy(array("email=? AND active=''"), $strEmail)) !== null) { while ($objOld->next()) { $objOld->delete(); } } $time = time(); $strToken = md5(uniqid(mt_rand(), true)); // Add the new subscriptions foreach ($arrNew as $id) { $objRecipient = new \NewsletterRecipientsModel(); $objRecipient->pid = $id; $objRecipient->tstamp = $time; $objRecipient->email = $strEmail; $objRecipient->active = ''; $objRecipient->addedOn = $time; $objRecipient->ip = $this->anonymizeIp(\Environment::get('ip')); $objRecipient->token = $strToken; $objRecipient->confirmed = ''; $objRecipient->save(); // Remove the blacklist entry (see #4999) if (($objBlacklist = \NewsletterBlacklistModel::findByHashAndPid(md5($strEmail), $id)) !== null) { $objBlacklist->delete(); } } // Get the channels $objChannel = \NewsletterChannelModel::findByIds($arrNew); // Prepare the simple token data $arrData = array(); $arrData['token'] = $strToken; $arrData['domain'] = \Idna::decode(\Environment::get('host')); $arrData['link'] = \Idna::decode(\Environment::get('base')) . \Environment::get('request') . (strpos(\Environment::get('request'), '?') !== false ? '&' : '?') . 'token=' . $strToken; $arrData['channel'] = $arrData['channels'] = implode("\n", $objChannel->fetchEach('title')); // Activation e-mail $objEmail = new \Email(); $objEmail->from = $GLOBALS['TL_ADMIN_EMAIL']; $objEmail->fromName = $GLOBALS['TL_ADMIN_NAME']; $objEmail->subject = sprintf($GLOBALS['TL_LANG']['MSC']['nl_subject'], \Idna::decode(\Environment::get('host'))); $objEmail->text = \StringUtil::parseSimpleTokens($this->nl_subscribe, $arrData); $objEmail->sendTo($strEmail); // Redirect to the jumpTo page if ($this->jumpTo && ($objTarget = $this->objModel->getRelated('jumpTo')) instanceof PageModel) { /** @var PageModel $objTarget */ $this->redirect($objTarget->getFrontendUrl()); } \System::getContainer()->get('session')->getFlashBag()->set('nl_confirm', $GLOBALS['TL_LANG']['MSC']['nl_confirm']); $this->reload(); }