Exceptions, Mail, Auth, Register, UserMapper, Validator
This commit is contained in:
parent
a1f5f61a50
commit
35c9d5583c
12 changed files with 159 additions and 99 deletions
9
app/Core/Exceptions/ForkException.php
Normal file
9
app/Core/Exceptions/ForkException.php
Normal file
|
@ -0,0 +1,9 @@
|
|||
<?php
|
||||
|
||||
namespace ForkBB\Core\Exceptions;
|
||||
|
||||
use Exception;
|
||||
|
||||
class ForkException extends Exception
|
||||
{
|
||||
}
|
7
app/Core/Exceptions/MailException.php
Normal file
7
app/Core/Exceptions/MailException.php
Normal file
|
@ -0,0 +1,7 @@
|
|||
<?php
|
||||
|
||||
namespace ForkBB\Core\Exceptions;
|
||||
|
||||
class MailException extends ForkException
|
||||
{
|
||||
}
|
7
app/Core/Exceptions/SmtpException.php
Normal file
7
app/Core/Exceptions/SmtpException.php
Normal file
|
@ -0,0 +1,7 @@
|
|||
<?php
|
||||
|
||||
namespace ForkBB\Core\Exceptions;
|
||||
|
||||
class StmpException extends MailException
|
||||
{
|
||||
}
|
|
@ -2,7 +2,8 @@
|
|||
|
||||
namespace ForkBB\Core;
|
||||
|
||||
use RuntimeException;
|
||||
use ForkBB\Core\Exceptions\MailException;
|
||||
use ForkBB\Core\Exceptions\StmpException;
|
||||
|
||||
class Mail
|
||||
{
|
||||
|
@ -81,14 +82,33 @@ class Mail
|
|||
/**
|
||||
* Валидация email
|
||||
* @param mixed $email
|
||||
* @return bool
|
||||
* @param bool $strict
|
||||
* @param bool $idna
|
||||
* @return false|string
|
||||
*/
|
||||
public function valid($email)
|
||||
public function valid($email, $strict = false, $idna = false)
|
||||
{
|
||||
return is_string($email)
|
||||
&& strlen($email) <= 80
|
||||
&& trim($email) === $email
|
||||
&& preg_match('%^.+@.+$%D', $email);
|
||||
if (! is_string($email)
|
||||
|| mb_strlen($email, 'UTF-8') > 80
|
||||
|| ! preg_match('%^([\w!#$\%&\'*+-/=?^`{|}~]+(?:\.[\w!#$\%&\'*+-/=?^`{|}~]+)*)@([^\x00-\x20]+)$%D', $email, $matches)
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
$local = $matches[1];
|
||||
$domain = mb_strtolower($matches[2], 'UTF-8');
|
||||
if (! preg_match('%^(?:[\p{L}\p{N}]+(?:\-[\p{L}\p{N}]+)*\.)*\p{L}+$%u', $domain)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$domainASCII = idn_to_ascii($domain);
|
||||
|
||||
if ($strict) {
|
||||
$mx = dns_get_record($domainASCII, DNS_MX);
|
||||
if (empty($mx)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return $local . '@' . ($idna ? $domainASCII : $domain);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -127,8 +147,8 @@ class Mail
|
|||
$email = preg_split('%[,\n\r]%', (string) $email, -1, PREG_SPLIT_NO_EMPTY);
|
||||
}
|
||||
foreach($email as $cur) {
|
||||
$cur = trim((string) $cur);
|
||||
if ($this->valid($cur)) {
|
||||
$cur = $this->valid(trim((string) $cur), false, true);
|
||||
if (false !== $cur) {
|
||||
$this->to[] = $this->formatAddress($cur, $name);
|
||||
}
|
||||
}
|
||||
|
@ -155,7 +175,8 @@ class Mail
|
|||
*/
|
||||
public function setFrom($email, $name = null)
|
||||
{
|
||||
if ($this->valid($email)) {
|
||||
$email = $this->valid($email, false, true);
|
||||
if (false !== $email) {
|
||||
$this->headers['From'] = $this->formatAddress($email, $name);
|
||||
}
|
||||
return $this;
|
||||
|
@ -169,7 +190,8 @@ class Mail
|
|||
*/
|
||||
public function setReplyTo($email, $name = null)
|
||||
{
|
||||
if ($this->valid($email)) {
|
||||
$email = $this->valid($email, false, true);
|
||||
if (false !== $email) {
|
||||
$this->headers['Reply-To'] = $this->formatAddress($email, $name);
|
||||
}
|
||||
return $this;
|
||||
|
@ -183,8 +205,7 @@ class Mail
|
|||
*/
|
||||
protected function formatAddress($email, $name = null)
|
||||
{
|
||||
$email = $this->filterEmail($email);
|
||||
if (null === $name || ! is_string($name) || strlen(trim($name)) == 0) {
|
||||
if (! is_string($name) || strlen(trim($name)) == 0) {
|
||||
return $email;
|
||||
} else {
|
||||
$name = $this->encodeText($this->filterName($name));
|
||||
|
@ -206,16 +227,6 @@ class Mail
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Фильтрация email
|
||||
* @param string $email
|
||||
* @return string
|
||||
*/
|
||||
protected function filterEmail($email)
|
||||
{
|
||||
return preg_replace('%[\x00-\x1F",<>]%', '', $email);
|
||||
}
|
||||
|
||||
/**
|
||||
* Фильтрация имени
|
||||
* @param string $name
|
||||
|
@ -223,14 +234,7 @@ class Mail
|
|||
*/
|
||||
protected function filterName($name)
|
||||
{
|
||||
return strtr(trim($name), [
|
||||
"\r" => '',
|
||||
"\n" => '',
|
||||
"\t" => '',
|
||||
'"' => '\'',
|
||||
'<' => '[',
|
||||
'>' => ']',
|
||||
]);
|
||||
return addcslashes(preg_replace('%[\x00-\x1F]%', '', trim($name)), '\\"');
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -259,14 +263,14 @@ class Mail
|
|||
* Задает сообщение по шаблону
|
||||
* @param string $tpl
|
||||
* @param array $data
|
||||
* @throws \RuntimeException
|
||||
* @throws MailException
|
||||
* @return Mail
|
||||
*/
|
||||
public function setTpl($tpl, array $data)
|
||||
{
|
||||
$file = rtrim($this->folder, '\\/') . '/' . $this->language . '/mail/' . $tpl;
|
||||
if (! file_exists($file)) {
|
||||
throw new RuntimeException('Tpl not found');
|
||||
throw new MailException('The template isn\'t found (' . $file . ').');
|
||||
}
|
||||
$tpl = trim(file_get_contents($file));
|
||||
foreach ($data as $key => $val) {
|
||||
|
@ -274,7 +278,7 @@ class Mail
|
|||
}
|
||||
list($subject, $tpl) = explode("\n", $tpl, 2);
|
||||
if (! isset($tpl)) {
|
||||
throw new RuntimeException('Tpl empty');
|
||||
throw new MailException('The template is empty (' . $file . ').');
|
||||
}
|
||||
$this->setSubject(substr($subject, 8));
|
||||
return $this->setMessage($tpl);
|
||||
|
@ -283,7 +287,6 @@ class Mail
|
|||
/**
|
||||
* Задает сообщение
|
||||
* @param string $message
|
||||
* @throws \RuntimeException
|
||||
* @return Mail
|
||||
*/
|
||||
public function setMessage($message)
|
||||
|
@ -297,21 +300,22 @@ class Mail
|
|||
|
||||
/**
|
||||
* Отправляет письмо
|
||||
* @throws MailException
|
||||
* @return bool
|
||||
*/
|
||||
public function send()
|
||||
{
|
||||
if (empty($this->to)) {
|
||||
throw new RuntimeException('No recipient(s)');
|
||||
throw new MailException('No recipient for the email.');
|
||||
}
|
||||
if (empty($this->headers['From'])) {
|
||||
throw new RuntimeException('No sender');
|
||||
throw new MailException('No sender for the email.');
|
||||
}
|
||||
if (! isset($this->headers['Subject'])) {
|
||||
throw new RuntimeException('Subject empty');
|
||||
throw new MailException('The subject of the email is empty.');
|
||||
}
|
||||
if (trim($this->message) == '') {
|
||||
throw new RuntimeException('Message empty');
|
||||
throw new MailException('The body of the email is empty.');
|
||||
}
|
||||
|
||||
$this->headers = array_replace($this->headers, [
|
||||
|
@ -359,7 +363,7 @@ class Mail
|
|||
|
||||
/**
|
||||
* Отправка письма через smtp
|
||||
* @throws \RuntimeException
|
||||
* @throws SmtpException
|
||||
* @return bool
|
||||
*/
|
||||
protected function smtp()
|
||||
|
@ -367,7 +371,7 @@ class Mail
|
|||
// подлючение
|
||||
if (! is_resource($this->connect)) {
|
||||
if (($connect = @fsockopen($this->smtp['host'], $this->smtp['port'], $errno, $errstr, 5)) === false) {
|
||||
throw new RuntimeException('Could not connect to smtp host "' . $this->smtp['host'] . '" (' . $errno . ') (' . $errstr . ')');
|
||||
throw new SmtpException('Couldn\'t connect to smtp host "' . $this->smtp['host'] . ':' . $this->smtp['port'] . '" (' . $errno . ') (' . $errstr . ').');
|
||||
}
|
||||
stream_set_timeout($connect, 5);
|
||||
$this->connect = $connect;
|
||||
|
@ -389,15 +393,6 @@ class Mail
|
|||
return true;
|
||||
}
|
||||
|
||||
public function __destruct()
|
||||
{
|
||||
// завершение сеанса smtp
|
||||
if (is_resource($this->connect)) {
|
||||
$this->smtpData('QUIT', null);
|
||||
@fclose($this->connect);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Hello SMTP server
|
||||
*/
|
||||
|
@ -425,23 +420,25 @@ class Mail
|
|||
}
|
||||
|
||||
/**
|
||||
* Отправляет данные на сервер
|
||||
* Проверяет ответ
|
||||
* Возвращает код ответа
|
||||
* @param string $data
|
||||
* @param mixed $code
|
||||
* @throws \RuntimeException
|
||||
* @throws SmtpException
|
||||
* @return string
|
||||
*/
|
||||
protected function smtpData($data, $code)
|
||||
{
|
||||
//var_dump($data);
|
||||
if (is_string($data)) {
|
||||
@fwrite($this->connect, $data . $this->EOL);
|
||||
if (is_resource($this->connect) && is_string($data)) {
|
||||
if (@fwrite($this->connect, $data . $this->EOL) === false) {
|
||||
throw new SmtpException('Couldn\'t send data to mail server.');
|
||||
}
|
||||
}
|
||||
|
||||
$response = '';
|
||||
// while (! isset($get{3}) || $get{3} !== ' ') {
|
||||
while (is_resource($this->connect) && !feof($this->connect)) {
|
||||
while (is_resource($this->connect) && ! feof($this->connect)) {
|
||||
if (($get = @fgets($this->connect, 512)) === false) {
|
||||
throw new RuntimeException('Couldn\'t get mail server response codes');
|
||||
throw new SmtpException('Couldn\'t get mail server response codes.');
|
||||
}
|
||||
$response .= $get;
|
||||
if (isset($get{3}) && $get{3} === ' ') {
|
||||
|
@ -449,9 +446,8 @@ class Mail
|
|||
break;
|
||||
}
|
||||
}
|
||||
//var_dump($response);
|
||||
if ($code !== null && ! in_array($return, (array) $code)) {
|
||||
throw new RuntimeException('Unable to send email. Response of the SMTP server: "'.$get.'"');
|
||||
throw new SmtpException('Unable to send email. Response of mail server: "' . $get . '"');
|
||||
}
|
||||
return $return;
|
||||
}
|
||||
|
@ -481,4 +477,16 @@ class Mail
|
|||
? (isset($_SERVER['SERVER_ADDR']) ? '[' . $_SERVER['SERVER_ADDR'] . ']' : '[127.0.0.1]')
|
||||
: $_SERVER['SERVER_NAME'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Деструктор
|
||||
*/
|
||||
public function __destruct()
|
||||
{
|
||||
// завершение сеанса smtp
|
||||
if (is_resource($this->connect)) {
|
||||
$this->smtpData('QUIT', null);
|
||||
@fclose($this->connect);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,8 +2,9 @@
|
|||
|
||||
namespace ForkBB\Models\Pages;
|
||||
|
||||
use ForkBB\Models\Validator;
|
||||
use ForkBB\Core\Exceptions\MailException;
|
||||
use ForkBB\Models\User;
|
||||
use ForkBB\Models\Validator;
|
||||
|
||||
class Auth extends Page
|
||||
{
|
||||
|
@ -226,14 +227,21 @@ class Auth extends Page
|
|||
'username' => $this->tmpUser->username,
|
||||
'link' => $link,
|
||||
];
|
||||
$mail = $this->c->Mail->reset()
|
||||
->setFolder($this->c->DIR_LANG)
|
||||
->setLanguage($this->tmpUser->language)
|
||||
->setTo($v->email, $this->tmpUser->username)
|
||||
->setFrom($this->config['o_webmaster_email'], __('Mailer', $this->config['o_board_title']))
|
||||
->setTpl('password_reset.tpl', $tplData);
|
||||
|
||||
if ($mail->send()) {
|
||||
try {
|
||||
$isSent = $this->c->Mail
|
||||
->reset()
|
||||
->setFolder($this->c->DIR_LANG)
|
||||
->setLanguage($this->tmpUser->language)
|
||||
->setTo($v->email, $this->tmpUser->username)
|
||||
->setFrom($this->config['o_webmaster_email'], __('Mailer', $this->config['o_board_title']))
|
||||
->setTpl('password_reset.tpl', $tplData)
|
||||
->send();
|
||||
} catch (MailException $e) {
|
||||
$isSent = false;
|
||||
}
|
||||
|
||||
if ($isSent) {
|
||||
$this->c->UserMapper->updateUser($this->tmpUser->id, ['activate_string' => $key, 'last_email_sent' => time()]);
|
||||
return $this->c->Message->message(__('Forget mail', $this->config['o_admin_email']), false, 200);
|
||||
} else {
|
||||
|
@ -283,7 +291,6 @@ class Auth extends Page
|
|||
} else {
|
||||
// что-то пошло не так
|
||||
if (! hash_equals($args['hash'], $this->c->Secury->hash($args['email'] . $args['key']))
|
||||
|| ! $this->c->Mail->valid($args['email'])
|
||||
|| ! ($user = $this->c->UserMapper->getUser($args['email'], 'email')) instanceof User
|
||||
|| empty($user->activateString)
|
||||
|| $user->activateString{0} !== 'p'
|
||||
|
@ -295,6 +302,12 @@ class Auth extends Page
|
|||
|
||||
$this->c->Lang->load('auth');
|
||||
|
||||
if ($user->isUnverified) {
|
||||
$this->c->UserMapper->updateUser($user->id, ['group_id' => $this->config['o_default_user_group'], 'email_confirmed' => 1]);
|
||||
$this->c->{'users_info update'};
|
||||
$this->iswev['i'][] = __('Account activated');
|
||||
}
|
||||
|
||||
$this->titles = [
|
||||
__('Change pass'),
|
||||
];
|
||||
|
@ -315,7 +328,6 @@ class Auth extends Page
|
|||
{
|
||||
// что-то пошло не так
|
||||
if (! hash_equals($args['hash'], $this->c->Secury->hash($args['email'] . $args['key']))
|
||||
|| ! $this->c->Mail->valid($args['email'])
|
||||
|| ! ($user = $this->c->UserMapper->getUser($args['email'], 'email')) instanceof User
|
||||
|| empty($user->activateString)
|
||||
|| $user->activateString{0} !== 'p'
|
||||
|
|
|
@ -2,8 +2,9 @@
|
|||
|
||||
namespace ForkBB\Models\Pages;
|
||||
|
||||
use ForkBB\Models\Validator;
|
||||
use ForkBB\Core\Exceptions\MailException;
|
||||
use ForkBB\Models\User;
|
||||
use ForkBB\Models\Validator;
|
||||
|
||||
class Register extends Page
|
||||
{
|
||||
|
@ -134,11 +135,9 @@ class Register extends Page
|
|||
if ($this->config['o_regs_verify'] == '1') {
|
||||
$groupId = PUN_UNVERIFIED;
|
||||
$key = 'w' . $this->c->Secury->randomPass(79);
|
||||
$visit = 0;
|
||||
} else {
|
||||
$groupId = $this->config['o_default_user_group'];
|
||||
$key = null;
|
||||
$visit = time(); //????
|
||||
}
|
||||
|
||||
$newUserId = $this->c->UserMapper->newUser(new User([
|
||||
|
@ -147,8 +146,8 @@ class Register extends Page
|
|||
'password' => password_hash($v->password, PASSWORD_DEFAULT),
|
||||
'email' => $v->email,
|
||||
'email_confirmed' => 0,
|
||||
'last_visit' => $visit,
|
||||
'activate_string' => $key,
|
||||
'u_mark_all_read' => time(),
|
||||
], $this->c));
|
||||
|
||||
// обновление статистики по пользователям
|
||||
|
@ -157,7 +156,7 @@ class Register extends Page
|
|||
}
|
||||
|
||||
// уведомление о регистрации
|
||||
if ($this->config['o_mailing_list'] != '' && $this->config['o_regs_report'] == '1') {
|
||||
if ($this->config['o_regs_report'] == '1' && $this->config['o_mailing_list'] != '') {
|
||||
$tplData = [
|
||||
'fTitle' => $this->config['o_board_title'],
|
||||
'fRootLink' => $this->c->Router->link('Index'),
|
||||
|
@ -165,13 +164,19 @@ class Register extends Page
|
|||
'username' => $v->username,
|
||||
'userLink' => $this->c->Router->link('User', ['id' => $newUserId, 'name' => $v->username]),
|
||||
];
|
||||
$mail = $this->c->Mail->reset()
|
||||
->setFolder($this->c->DIR_LANG)
|
||||
->setLanguage($this->config['o_default_lang'])
|
||||
->setTo($this->config['o_mailing_list'])
|
||||
->setFrom($this->config['o_webmaster_email'], __('Mailer', $this->config['o_board_title']))
|
||||
->setTpl('new_user.tpl', $tplData)
|
||||
->send();
|
||||
|
||||
try {
|
||||
$this->c->Mail
|
||||
->reset()
|
||||
->setFolder($this->c->DIR_LANG)
|
||||
->setLanguage($this->config['o_default_lang'])
|
||||
->setTo($this->config['o_mailing_list'])
|
||||
->setFrom($this->config['o_webmaster_email'], __('Mailer', $this->config['o_board_title']))
|
||||
->setTpl('new_user.tpl', $tplData)
|
||||
->send();
|
||||
} catch (MailException $e) {
|
||||
//????
|
||||
}
|
||||
}
|
||||
|
||||
$this->c->Lang->load('register');
|
||||
|
@ -187,15 +192,22 @@ class Register extends Page
|
|||
'username' => $v->username,
|
||||
'link' => $link,
|
||||
];
|
||||
$mail = $this->c->Mail->reset()
|
||||
->setFolder($this->c->DIR_LANG)
|
||||
->setLanguage($this->c->user->language)
|
||||
->setTo($v->email)
|
||||
->setFrom($this->config['o_webmaster_email'], __('Mailer', $this->config['o_board_title']))
|
||||
->setTpl('welcome.tpl', $tplData);
|
||||
|
||||
try {
|
||||
$isSent = $this->c->Mail
|
||||
->reset()
|
||||
->setFolder($this->c->DIR_LANG)
|
||||
->setLanguage($this->c->user->language)
|
||||
->setTo($v->email)
|
||||
->setFrom($this->config['o_webmaster_email'], __('Mailer', $this->config['o_board_title']))
|
||||
->setTpl('welcome.tpl', $tplData)
|
||||
->send();
|
||||
} catch (MailException $e) {
|
||||
$isSent = false;
|
||||
}
|
||||
|
||||
// письмо активации аккаунта отправлено
|
||||
if ($mail->send()) {
|
||||
if ($isSent) {
|
||||
return $this->c->Message->message(__('Reg email', $this->config['o_admin_email']), false, 200);
|
||||
// форма сброса пароля
|
||||
} else {
|
||||
|
|
|
@ -2,8 +2,8 @@
|
|||
|
||||
namespace ForkBB\Models;
|
||||
|
||||
use ForkBB\Models\User;
|
||||
use ForkBB\Core\Container;
|
||||
use ForkBB\Models\User;
|
||||
use RuntimeException;
|
||||
use InvalidArgumentException;
|
||||
|
||||
|
@ -172,7 +172,7 @@ class UserMapper
|
|||
*/
|
||||
public function newUser(User $user)
|
||||
{
|
||||
$this->db->query('INSERT INTO '.$this->db->prefix.'users (username, group_id, password, email, email_confirmed, email_setting, timezone, dst, language, style, registered, registration_ip, last_visit, activate_string) VALUES(\''.$this->db->escape($user->username).'\', '.$user->groupId.', \''.$this->db->escape($user->password).'\', \''.$this->db->escape($user->email).'\', '.$user->emailConfirmed.', '.$this->config['o_default_email_setting'].', '.$this->config['o_default_timezone'].' , '.$this->config['o_default_dst'].', \''.$this->db->escape($user->language).'\', \''.$user->style.'\', '.time().', \''.$this->db->escape($this->getIpAddress()).'\', '.$user->lastVisit.', \''.$this->db->escape($user->activateString).'\')') or error('Unable to create user', __FILE__, __LINE__, $this->db->error());
|
||||
$this->db->query('INSERT INTO '.$this->db->prefix.'users (username, group_id, password, email, email_confirmed, email_setting, timezone, dst, language, style, registered, registration_ip, activate_string, u_mark_all_read) VALUES(\''.$this->db->escape($user->username).'\', '.$user->groupId.', \''.$this->db->escape($user->password).'\', \''.$this->db->escape($user->email).'\', '.$user->emailConfirmed.', '.$this->config['o_default_email_setting'].', '.$this->config['o_default_timezone'].' , '.$this->config['o_default_dst'].', \''.$this->db->escape($user->language).'\', \''.$user->style.'\', '.time().', \''.$this->db->escape($this->getIpAddress()).'\', \''.$this->db->escape($user->activateString).'\', '.$user->uMarkAllRead.')') or error('Unable to create user', __FILE__, __LINE__, $this->db->error());
|
||||
$new_uid = $this->db->insert_id(); //????
|
||||
return $new_uid;
|
||||
}
|
||||
|
|
|
@ -491,13 +491,12 @@ class Validator
|
|||
{
|
||||
if (null === $value) {
|
||||
return [$value, $type, false];
|
||||
} elseif ($this->c->Mail->valid($value)) {
|
||||
return [$value, $type, false];
|
||||
}
|
||||
$email = $this->c->Mail->valid($value, true);
|
||||
if (false === $email) {
|
||||
return [(string) $value, $type, 'The :alias is not valid email'];
|
||||
} else {
|
||||
if (! is_string($value)) {
|
||||
$value = (string) $value;
|
||||
}
|
||||
return [$value, $type, 'The :alias is not valid email'];
|
||||
return [$email, $type, false];
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -74,3 +74,6 @@ msgstr "Passwords must be at least 8 characters long. Passwords are case sensiti
|
|||
|
||||
msgid "Pass updated"
|
||||
msgstr "Your password has been updated. You can now login with your new password."
|
||||
|
||||
msgid "Account activated"
|
||||
msgstr "Account activated."
|
||||
|
|
|
@ -67,4 +67,4 @@ msgid "Login format"
|
|||
msgstr "The username must begin with a letter. May contain letters, numbers, spaces, dots, dashes and underscores."
|
||||
|
||||
msgid "Error welcom mail"
|
||||
msgstr "When sending email there was an error. Please use the password reset form or contact the forum administrator at <a href=\"mailto:%1$s\">%1$s</a>."
|
||||
msgstr "When sending email there was an error. Please use the password reset form for activate your account or contact the forum administrator at <a href=\"mailto:%1$s\">%1$s</a>."
|
||||
|
|
|
@ -74,3 +74,6 @@ msgstr "Пароль должен состоять минимум из 8 сим
|
|||
|
||||
msgid "Pass updated"
|
||||
msgstr "Ваш пароль изменён. Вы можете войти на форум с новым паролем."
|
||||
|
||||
msgid "Account activated"
|
||||
msgstr "Аккаунт активирован."
|
||||
|
|
|
@ -67,4 +67,4 @@ msgid "Login format"
|
|||
msgstr "Имя пользователя должно начинаться с буквы. Может содержать буквы, цифры, пробел, точку, дефис и знак подчеркивания."
|
||||
|
||||
msgid "Error welcom mail"
|
||||
msgstr "При отправке письма возникла ошибка. Пожалуйста, воспользуйтесь формой восстановления пароля или свяжитесь с администратором форума по адресу <a href=\"mailto:%1$s\">%1$s</a>."
|
||||
msgstr "При отправке письма возникла ошибка. Пожалуйста, воспользуйтесь формой восстановления пароля для активации аккаунта или свяжитесь с администратором форума по адресу <a href=\"mailto:%1$s\">%1$s</a>."
|
||||
|
|
Loading…
Add table
Reference in a new issue