Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mail related improvements #1173

Merged
merged 8 commits into from
May 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 5 additions & 11 deletions backend/commands/PlayerController.php
Original file line number Diff line number Diff line change
Expand Up @@ -165,24 +165,18 @@ public function actionMail($active=false, $email=false,$status=9)
$this->stdout("Mailing Registered users:\n", Console::BOLD);
}
$event_name=Sysconfig::findOne('event_name')->val;
$emailtpl=\app\modules\content\models\EmailTemplate::findOne(['name' => 'emailVerify']);
$subject=Yii::t('app', '{event_name} Account approved', ['event_name' => trim(Yii::$app->sys->event_name)]);

foreach($players as $player)
{
// Generate activation URL
$activationURL=sprintf("https://%s/verify-email?token=%s",\Yii::$app->sys->offense_domain, $player->verification_token);
$contentHtml = \app\components\BaseController::renderPhpContent("?>" . $emailtpl->html, ['user' => $player,'verifyLink'=>$activationURL]);
$contentTxt = \app\components\BaseController::renderPhpContent("?>" . $emailtpl->txt, ['user' => $player,'verifyLink'=>$activationURL]);

$this->stdout($player->email);
$numSend=Yii::$app
->mailer
->compose(
['html' => 'emailVerify-html', 'text' => 'emailVerify-text'],
['user' => $player,'verifyLink'=>$activationURL]
)
->setFrom([Yii::$app->sys->mail_from => Yii::$app->sys->mail_fromName])
->setBcc([Yii::$app->sys->mail_from => Yii::$app->sys->mail_fromName])
->setTo([$player->email => $player->fullname])
->setSubject(trim(Yii::$app->sys->event_name). ' Account approved')
->send();
$numSend=intval($player->mail($subject,$contentHtml,$contentTxt));
$this->stdout($numSend ? " Ok\n" : "Not Ok\n");
}
}
Expand Down
2 changes: 1 addition & 1 deletion backend/components/BaseController.php
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ public function init()
parent::init();
}

public function renderPhpContent($_content_, $_params_ = [])
public static function renderPhpContent($_content_, $_params_ = [])
{
$_obInitialLevel_ = ob_get_level();
ob_start();
Expand Down
55 changes: 17 additions & 38 deletions backend/components/Mailer.php
Original file line number Diff line number Diff line change
@@ -1,49 +1,28 @@
<?php

namespace app\components;

use Yii;

class Mailer extends \yii\symfonymailer\Mailer
{
public function init()
{
parent::init();

$this->useFileTransport=Yii::$app->sys->mail_useFileTransport;

$config['scheme']='smtp';
$config['options']['local_domain']=\Yii::$app->sys->offense_domain;

if(Yii::$app->sys->mail_host !== false)
{
$config['host']=Yii::$app->sys->mail_host;
}

if(Yii::$app->sys->mail_port !== false)
{
$config['port']=intval(Yii::$app->sys->mail_port);
}

if(Yii::$app->sys->mail_username !== false)
{
$config['username']=Yii::$app->sys->mail_username;
}

if(Yii::$app->sys->mail_password !== false)
{
$config['password']=Yii::$app->sys->mail_password;
}

if(Yii::$app->sys->mail_encryption !== false && trim(Yii::$app->sys->mail_encryption)!='')
{
$config['scheme']=Yii::$app->sys->mail_encryption;
}

if(Yii::$app->sys->mail_verify_peer !== false)
{
$this->ssl['verify_peer']=Yii::$app->sys->mail_verify_peer;
}
if(Yii::$app->sys->mail_verify_peer_name !== false)
{
$this->ssl['verify_peer_name']=Yii::$app->sys->mail_verify_peer_name;
$this->useFileTransport = (bool)Yii::$app->sys->mail_useFileTransport;
if (trim(\Yii::$app->sys->dsn)!=="") {
$config['dsn']=trim(\Yii::$app->sys->dsn);
} else {
$config['dsn'] = Yii::t('app', '{mail_encryption}://{mail_userpass}{mail_host}:{mail_port}?verify_peer={verify_peer}&local_domain={local_domain}&verify_peer_name={verify_peer_name}', [
'mail_encryption' => \Yii::$app->sys->mail_encryption ?? "smtp",
'mail_userpass' => (trim(\Yii::$app->sys->mail_username) != "" && trim(\Yii::$app->sys->mail_password) != "") ? trim(\Yii::$app->sys->mail_username) . ':' . trim(\Yii::$app->sys->mail_password) . '@' : '',
'mail_password' => \Yii::$app->sys->mail_password,
'mail_host' => \Yii::$app->sys->mail_host,
'mail_port' => \Yii::$app->sys->mail_port ?? "25",
'verify_peer' => intval(\Yii::$app->sys->verify_peer),
'local_domain' => \Yii::$app->sys->offense_domain,
'verify_peer_name' => intval(\Yii::$app->sys->verify_peer_name),
]);
}
$this->setTransport($config);
}
Expand Down
52 changes: 25 additions & 27 deletions backend/modules/frontend/actions/player/MailAction.php
Original file line number Diff line number Diff line change
Expand Up @@ -53,13 +53,21 @@ public function run(int $id, $baseURL = "https://echoctf.red/activate/")
private function rejectionMail($player)
{
try {
$this->sendMail(
$player,
'rejectVerify-html',
'rejectVerify-text',
Yii::t('app', '{event_name} Account rejected', ['event_name' => trim(Yii::$app->sys->event_name)])
);
\Yii::$app->getSession()->setFlash('success', Yii::t('app', 'Player rejection mail send.'));
$emailtpl=\app\modules\content\models\EmailTemplate::findOne(['name' => 'rejectVerify']);
$contentHtml = $this->controller->renderPhpContent("?>" . $emailtpl->html, ['user' => $player]);
$contentTxt = $this->controller->renderPhpContent("?>" . $emailtpl->txt, ['user' => $player]);
$subject=Yii::t('app', '{event_name} Account rejected', ['event_name' => trim(Yii::$app->sys->event_name)]);
if(!$player->mail($subject,$contentHtml,$contentTxt))
{
throw new \Exception('Could not send mail');
}

if (Yii::$app->sys->player_require_approval === true && $player->approval == 3) {
$player->updateAttributes(['approval' => 4]);
\Yii::$app->getSession()->setFlash('success', Yii::t('app', 'Player rejection mail send and approval status updated.'));
} else {
\Yii::$app->getSession()->setFlash('success', Yii::t('app', 'Player rejection mail send.'));
}
} catch (\Exception $e) {
\Yii::$app->getSession()->setFlash('error', Yii::t('app', 'Failed to mail rejection to player. {exception}', ['exception' => Html::encode($e->getMessage())]));
}
Expand All @@ -72,12 +80,16 @@ private function approvalMail($player)
{
try {
$activationURL = sprintf("https://%s/verify-email?token=%s", \Yii::$app->sys->offense_domain, $player->verification_token);
$this->sendMail(
$player,
'emailVerify-html',
'emailVerify-text',
Yii::t('app', '{event_name} Account approved', ['event_name' => trim(Yii::$app->sys->event_name)])
);
$emailtpl=\app\modules\content\models\EmailTemplate::findOne(['name' => 'emailVerify']);
$contentHtml = $this->controller->renderPhpContent("?>" . $emailtpl->html, ['user' => $player,'verifyLink'=>$activationURL]);
$contentTxt = $this->controller->renderPhpContent("?>" . $emailtpl->txt, ['user' => $player,'verifyLink'=>$activationURL]);
$subject=Yii::t('app', '{event_name} Account approved', ['event_name' => trim(Yii::$app->sys->event_name)]);

if(!$player->mail($subject,$contentHtml,$contentTxt))
{
throw new \Exception('Could not send mail');
}

if (Yii::$app->sys->player_require_approval === true && $player->approval == 1) {
$player->updateAttributes(['approval' => 2]);
\Yii::$app->getSession()->setFlash('success', Yii::t('app', 'Player activation mail send and approval status updated.'));
Expand All @@ -88,18 +100,4 @@ private function approvalMail($player)
\Yii::$app->getSession()->setFlash('error', Yii::t('app', 'Failed to mail player. {exception}', ['exception' => Html::encode($e->getMessage())]));
}
}

private function sendMail($player, $html, $text, $subject)
{
Yii::$app
->mailer
->compose(
['html' => $html, 'text' => $text],
['user' => $player]
)
->setFrom([Yii::$app->sys->mail_from => Yii::$app->sys->mail_fromName . ' robot'])
->setTo([$player->email => $player->fullname])
->setSubject($subject)
->send();
}
}
19 changes: 15 additions & 4 deletions backend/modules/frontend/models/Player.php
Original file line number Diff line number Diff line change
Expand Up @@ -68,17 +68,28 @@ public function saveWithSsl()
return false;
}

public function mail($content, $subject)
/**
* Send mail to player with
* @param string $subject
* @param string $html
* @param string $txt
* @param array $headers
* @return bool
*/
public function mail($subject, $html, $txt,$headers=[])
{
// Get mailer
try
{
\Yii::$app->mailer->compose()
$message=\Yii::$app->mailer->compose()
->setFrom([\app\modules\settings\models\Sysconfig::findOne('mail_from')->val => \app\modules\settings\models\Sysconfig::findOne('mail_fromName')->val])
->setTo([$this->email=>$this->username])
->setSubject($subject)
->setTextBody($content)
->send();
->setTextBody($txt)
->setHtmlBody($html);
foreach($headers as $entry)
$message->addHeader($entry[0],$entry[1]);
$message->send();
if (Yii::$app instanceof \yii\web\Application)
\Yii::$app->session->setFlash('success', Yii::t('app',"The user has been mailed."));
else {
Expand Down
9 changes: 7 additions & 2 deletions backend/modules/settings/models/ConfigureForm.php
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ class ConfigureForm extends Model
public $profile_twitch;
public $profile_youtube;
public $guest_visible_leaderboards;
public $dsn;

public $dn_countryName;
public $dn_stateOrProvinceName;
Expand Down Expand Up @@ -164,7 +165,8 @@ class ConfigureForm extends Model
'profile_htb',
'profile_twitch',
'profile_youtube',
'guest_visible_leaderboards'
'guest_visible_leaderboards',
'dsn'
];

/**
Expand Down Expand Up @@ -203,6 +205,7 @@ public function rules()
'stripe_apiKey',
'stripe_publicApiKey',
'stripe_webhookSecret',
'dsn'
], 'string'],
[['offense_registered_tag',
'defense_registered_tag',
Expand Down Expand Up @@ -233,7 +236,8 @@ public function rules()
'dn_localityName',
'dn_organizationName',
'dn_organizationalUnitName',
'pf_state_limits'
'pf_state_limits',
'dsn'
], 'trim'],
// required fields
[['teams',
Expand Down Expand Up @@ -380,6 +384,7 @@ public function attributeLabels()
'profile_twitch'=>'Twitch',
'profile_youtube'=>'Youtube',
'guest_visible_leaderboards'=>'Guest visible leaderboards',
'dsn'=>'Mail DSN'
];
}

Expand Down
11 changes: 3 additions & 8 deletions backend/modules/settings/views/sysconfig/configure.php
Original file line number Diff line number Diff line change
Expand Up @@ -114,13 +114,7 @@
<div class="col-sm-3"><?= $form->field($model, 'mail_useFileTransport')->checkbox()->hint('Activate the use of file transport (save mails in files)?') ?></div>
<div class="col-sm-3"><?= $form->field($model, 'mail_from')->textInput(['maxlength' => true])->hint('Mail From (eg. dontreply@echoctf.red)') ?></div>
<div class="col-sm-3"><?= $form->field($model, 'mail_fromName')->textInput(['maxlength' => true])->hint('Mail From Name (eg. echoCTF RED)') ?></div>
<div class="col-sm-3"><?= $form->field($model, 'mail_host')->textInput(['maxlength' => true])->hint('Mail host (eg. smtp-relay.gmail.com)') ?></div>
<div class="col-sm-3"><?= $form->field($model, 'mail_port')->textInput(['maxlength' => true])->hint('Mail port (eg. 25)') ?></div>
<div class="col-sm-3"><?= $form->field($model, 'mail_username')->textInput(['maxlength' => true])->hint('Mail server username') ?></div>
<div class="col-sm-3"><?= $form->field($model, 'mail_password')->textInput(['maxlength' => true])->hint('Mail server password') ?></div>
<div class="col-sm-3"><?= $form->field($model, 'mail_encryption')->textInput(['maxlength' => true])->hint('Mail server encryption (ssl,tls,none)') ?></div>
<div class="col-sm-3"><?= $form->field($model, 'mail_verify_peer')->checkbox()->hint('Verify peer sertificate?') ?></div>
<div class="col-sm-3"><?= $form->field($model, 'mail_verify_peer_name')->checkbox()->hint('Verify peer name from certificate?') ?></div>
<div class="col-sm-6"><?= $form->field($model, 'dsn')->textInput(['maxlength' => true,'placeholder'=>'smtp://username:password@mail.example.com:25?local_domain=blah'])->hint('Mail DSN see '.Html::a('Symphony Mailer','https://symfony.com/doc/current/mailer.html',['title'=>'Symphony Mailer Reference','target'=>'_blank'])) ?></div>
</div>
<hr/>

Expand Down Expand Up @@ -150,7 +144,8 @@
</div>
<hr/>

<h4>VPN Certificate Settings <span><small>If you change these values you will have to regenerate your ca keys and player certificates again.</small></span></h4>
<h4>VPN Certificate Settings</h4>
<small class="text-danger">If you change these values you will have to regenerate your CA keys and player certificates.</small>

<div class="row form-group">
<div class="col-sm-2"><?= $form->field($model, 'dn_countryName')->textInput(['maxlength' => true])->input('text', ['placeholder' => ""])->hint('') ?></div>
Expand Down
6 changes: 6 additions & 0 deletions docs/Sysconfig-Keys.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,10 +70,16 @@
## mail configuration
* `mail_from` Email address used to send registration and password reset mails from
* `mail_fromName` The name appeared on the email send for registration and password resets
* `dsn` A symphony mailer compatible DSN

Or instead if not DSN then use the following
* `mail_host` The mail server host to send mails through
* `mail_port` The mail server port to connect
* `mail_username` The username to authenticate to the mail server
* `mail_password` The password to authenticate to the mail server
* `local_domain` Set the EHLO mail used when sending mail
* `verify_peer_name` Verify the SSL peer name of the remote server when sending email
* `verify_peer` Verify the remote peer certificate when sending mail

## VPN specific keys
* `CA.csr` The CA CSR
Expand Down
51 changes: 14 additions & 37 deletions frontend/components/Mailer.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,43 +6,20 @@ class Mailer extends \yii\symfonymailer\Mailer
public function init()
{
parent::init();

$this->useFileTransport=Yii::$app->sys->mail_useFileTransport;

$config['scheme']='smtp';
$config['options']['local_domain']=\Yii::$app->sys->offense_domain;
if(Yii::$app->sys->mail_host !== false)
{
$config['host']=Yii::$app->sys->mail_host;
}

if(Yii::$app->sys->mail_port !== false)
{
$config['port']=intval(Yii::$app->sys->mail_port);
}

if(Yii::$app->sys->mail_username !== false)
{
$config['username']=Yii::$app->sys->mail_username;
}

if(Yii::$app->sys->mail_password !== false)
{
$config['password']=Yii::$app->sys->mail_password;
}

if(Yii::$app->sys->mail_encryption !== false && trim(Yii::$app->sys->mail_encryption)!='')
{
$config['scheme']=Yii::$app->sys->mail_encryption;
}

if(Yii::$app->sys->mail_verify_peer !== false)
{
$this->ssl['verify_peer']=Yii::$app->sys->mail_verify_peer;
}
if(Yii::$app->sys->mail_verify_peer_name !== false)
{
$this->ssl['verify_peer_name']=Yii::$app->sys->mail_verify_peer_name;
$this->useFileTransport = (bool)Yii::$app->sys->mail_useFileTransport;
if (\Yii::$app->sys->dsn !== false) {
$config['dsn']=trim(\Yii::$app->sys->dsn);
} else {
$config['dsn'] = Yii::t('app', '{mail_encryption}://{mail_userpass}{mail_host}:{mail_port}?verify_peer={verify_peer}&local_domain={local_domain}&verify_peer_name={verify_peer_name}', [
'mail_encryption' => \Yii::$app->sys->mail_encryption ?? "smtp",
'mail_userpass' => (trim(\Yii::$app->sys->mail_username) != "" && trim(\Yii::$app->sys->mail_password) != "") ? trim(\Yii::$app->sys->mail_username) . ':' . trim(\Yii::$app->sys->mail_password) . '@' : '',
'mail_password' => \Yii::$app->sys->mail_password,
'mail_host' => \Yii::$app->sys->mail_host,
'mail_port' => \Yii::$app->sys->mail_port ?? "25",
'verify_peer' => intval(\Yii::$app->sys->verify_peer),
'local_domain' => \Yii::$app->sys->offense_domain,
'verify_peer_name' => intval(\Yii::$app->sys->verify_peer_name),
]);
}
$this->setTransport($config);
}
Expand Down
2 changes: 1 addition & 1 deletion frontend/components/echoCTFView.php
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ public function getTwitter_image_height()
return ['name'=>'twitter:image:height', 'content'=>$this->_image_height];
}

public function renderPhpContent($_content_, $_params_ = [])
public static function renderPhpContent($_content_, $_params_ = [])
{
$_obInitialLevel_ = ob_get_level();
ob_start();
Expand Down
Loading
Loading