Fix FLEXIAPI-287 Refactor the emails templates

This commit is contained in:
Timothée Jaussoin 2025-04-29 09:12:59 +00:00
parent 0160779784
commit 682b0ae67b
43 changed files with 381 additions and 450 deletions

View file

@ -32,6 +32,7 @@ v1.7
- Fix FLEXIAPI-272 Add Space based email server integration
- Fix FLEXIAPI-284 Add configurable admin API Keys
- Fix FLEXIAPI-232 Add provisioning email + important redesign of the contacts page
- Fix FLEXIAPI-287 Refactor the emails templates
v1.6
----

View file

@ -261,6 +261,11 @@ class Account extends Authenticatable
return $this->hasMany(AuthToken::class);
}
public function currentResetPasswordEmailToken()
{
return $this->hasOne(ResetPasswordEmailToken::class)->where('used', false)->latestOfMany();
}
public function resetPasswordEmailTokens()
{
return $this->hasMany(ResetPasswordEmailToken::class)->latest();

View file

@ -3,7 +3,6 @@
namespace App\Http\Controllers\Admin;
use App\Account;
use App\ResetPasswordEmailToken;
use App\Http\Controllers\Controller;
use App\Mail\Provisioning;
@ -23,7 +22,7 @@ class ProvisioningEmailController extends Controller
]);
}
public function send(int $accountId)
public function send(Request $request, int $accountId)
{
$account = Account::findOrFail($accountId);
$account->provision();

View file

@ -32,7 +32,7 @@ class ResetPasswordEmailController extends Controller
$resetPasswordEmail->email = $account->email;
$resetPasswordEmail->save();
Mail::to($account)->send(new ResetPassword($resetPasswordEmail));
Mail::to($account)->send(new ResetPassword($account));
return redirect()->route('admin.account.activity.index', $account);
}

View file

@ -43,7 +43,7 @@ class SpaceCheck
'username' => $space->emailServer->username,
'password' => $space->emailServer->password,
'signature' => $space->emailServer->signature ?? config('mail.signature')
];
] + Config::get('mail');
Config::set('mail', $config);
}

View file

@ -1,7 +1,7 @@
<?php
/*
Flexisip Account Manager is a set of tools to manage SIP accounts.
Copyright (C) 2020 Belledonne Communications SARL, All rights reserved.
Copyright (C) 2025 Belledonne Communications SARL, All rights reserved.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
@ -19,27 +19,35 @@
namespace App\Mail;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
use App\Account;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Mail\Mailable;
use Illuminate\Mail\Mailables\Content;
use Illuminate\Mail\Mailables\Envelope;
use Illuminate\Queue\SerializesModels;
class ConfirmedRegistration extends Mailable
{
use Queueable, SerializesModels;
private $account;
public function __construct(Account $account)
{
$this->account = $account;
public function __construct(
public Account $account
) {
}
public function build()
public function envelope(): Envelope
{
return $this->view('mails.confirmed_registration')
->text('mails.confirmed_registration_text')
->with(['account' => $this->account]);
return new Envelope(
subject: $this->account->space->name . ': '. __('Registration confirmed'),
);
}
public function content(): Content
{
return new Content(
markdown: 'mails.confirmed_registration',
);
}
}

View file

@ -1,7 +1,7 @@
<?php
/*
Flexisip Account Manager is a set of tools to manage SIP accounts.
Copyright (C) 2020 Belledonne Communications SARL, All rights reserved.
Copyright (C) 2025 Belledonne Communications SARL, All rights reserved.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
@ -19,27 +19,35 @@
namespace App\Mail;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
use App\Account;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Mail\Mailable;
use Illuminate\Mail\Mailables\Content;
use Illuminate\Mail\Mailables\Envelope;
use Illuminate\Queue\SerializesModels;
class NewsletterRegistration extends Mailable
{
use Queueable, SerializesModels;
private $account;
public function __construct(Account $account)
{
$this->account = $account;
public function __construct(
public Account $account
) {
}
public function build()
public function envelope(): Envelope
{
return $this->view('mails.newsletter_registration')
->text('mails.newsletter_registration_text')
->with(['account' => $this->account]);
return new Envelope(
subject: $this->account->space->name . ': '. __('Newsletter registration confirmed'),
);
}
public function content(): Content
{
return new Content(
markdown: 'mails.newsletter_registration',
);
}
}

View file

@ -1,41 +1,55 @@
<?php
/*
Flexisip Account Manager is a set of tools to manage SIP accounts.
Copyright (C) 2025 Belledonne Communications SARL, All rights reserved.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
namespace App\Mail;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
use App\Account;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Mail\Mailable;
use Illuminate\Mail\Mailables\Content;
use Illuminate\Mail\Mailables\Envelope;
use Illuminate\Queue\SerializesModels;
class Provisioning extends Mailable
{
use Queueable, SerializesModels;
private $account;
public function __construct(Account $account)
{
$this->account = $account;
public function __construct(
public Account $account
) {
}
public function build()
public function envelope(): Envelope
{
return $this->view(view()->exists('mails.provisioning_custom')
return new Envelope(
subject: $this->account->space->name . ': '. __('Provisioning of your device'),
);
}
public function content(): Content
{
return new Content(
markdown: view()->exists('mails.provisioning_custom')
? 'mails.provisioning_custom'
: 'mails.provisioning')
->text(view()->exists('mails.provisioning_text_custom')
? 'mails.provisioning_text_custom'
: 'mails.provisioning_text')
->with([
'provisioning_link' => route('provisioning.provision', [
'provisioning_token' => $this->account->provisioning_token,
'reset_password' => true
]),
'provisioning_qrcode' => route('provisioning.qrcode', [
'provisioning_token' => $this->account->provisioning_token,
'reset_password' => true
])
]);
: 'mails.provisioning',
);
}
}

View file

@ -1,7 +1,7 @@
<?php
/*
Flexisip Account Manager is a set of tools to manage SIP accounts.
Copyright (C) 2020 Belledonne Communications SARL, All rights reserved.
Copyright (C) 2025 Belledonne Communications SARL, All rights reserved.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
@ -19,42 +19,37 @@
namespace App\Mail;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
use App\Account;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Mail\Mailable;
use Illuminate\Mail\Mailables\Content;
use Illuminate\Mail\Mailables\Envelope;
use Illuminate\Queue\SerializesModels;
class RecoverByCode extends Mailable
{
use Queueable, SerializesModels;
private $account;
public function __construct(Account $account)
{
$this->account = $account;
public function __construct(
public Account $account
) {
}
public function build()
public function envelope(): Envelope
{
return $this->view(view()->exists('mails.authentication_custom')
? 'mails.authentication_custom'
: 'mails.authentication')
->text(view()->exists('mails.authentication_text_custom')
? 'mails.authentication_text_custom'
: 'mails.authentication_text')
->with([
'expiration_minutes' => config('app.recovery_code_expiration_minutes'),
'recovery_code' => $this->account->recovery_code,
'provisioning_link' => route('provisioning.provision', [
'provisioning_token' => $this->account->provisioning_token,
'reset_password' => true
]),
'provisioning_qrcode' => route('provisioning.qrcode', [
'provisioning_token' => $this->account->provisioning_token,
'reset_password' => true
])
]);
return new Envelope(
subject: $this->account->space->name . ': '. __('Account recovery'),
);
}
public function content(): Content
{
return new Content(
markdown: view()->exists('mails.recover_by_code_custom')
? 'mails.recover_by_code_custom'
: 'mails.recover_by_code',
);
}
}

View file

@ -1,7 +1,7 @@
<?php
/*
Flexisip Account Manager is a set of tools to manage SIP accounts.
Copyright (C) 2020 Belledonne Communications SARL, All rights reserved.
Copyright (C) 2025 Belledonne Communications SARL, All rights reserved.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
@ -19,29 +19,35 @@
namespace App\Mail;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
use App\Account;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Mail\Mailable;
use Illuminate\Mail\Mailables\Content;
use Illuminate\Mail\Mailables\Envelope;
use Illuminate\Queue\SerializesModels;
class RegisterValidation extends Mailable
{
use Queueable, SerializesModels;
private $account;
public function __construct(Account $account)
{
$this->account = $account;
public function __construct(
public Account $account
) {
}
public function build()
public function envelope(): Envelope
{
return $this->view('mails.register_validate')
->text('mails.register_validate_text')
->with([
'code' => $this->account->emailChangeCode()->first()->code
]);
return new Envelope(
subject: $this->account->space->name . ': '. __('Account registered'),
);
}
public function content(): Content
{
return new Content(
markdown: 'mails.register_validation',
);
}
}

View file

@ -1,7 +1,7 @@
<?php
/*
Flexisip Account Manager is a set of tools to manage SIP accounts.
Copyright (C) 2024 Belledonne Communications SARL, All rights reserved.
Copyright (C) 2025 Belledonne Communications SARL, All rights reserved.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
@ -19,30 +19,36 @@
namespace App\Mail;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
use App\Account;
use App\ResetPasswordEmailToken;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Mail\Mailable;
use Illuminate\Mail\Mailables\Content;
use Illuminate\Mail\Mailables\Envelope;
use Illuminate\Queue\SerializesModels;
class ResetPassword extends Mailable
{
use Queueable, SerializesModels;
private $token;
public function __construct(ResetPasswordEmailToken $token)
{
$this->token = $token;
public function __construct(
public Account $account
) {
}
public function build()
public function envelope(): Envelope
{
return $this->view('mails.reset_password')
->text('mails.reset_password')
->with([
'token' => $this->token
]);
return new Envelope(
subject: $this->account->space->name . ': '. __('Reset your password'),
);
}
public function content(): Content
{
return new Content(
markdown: 'mails.reset_password',
);
}
}

View file

@ -5,6 +5,7 @@
"Account creation": "Création de compte",
"Account recovered recently, try again later": "Tentative de récupération de compte récente, retentez ultérieurement",
"Account recovery": "Récupération de compte",
"Account registered": "Compte créé",
"Account settings": "Paramètres de compte",
"Account": "Compte",
"Accounts": "Comptes",
@ -22,9 +23,9 @@
"Administration": "Administration",
"All the admins will be super admins": "Tous les administrateurs seront super-administrateurs",
"Allow a custom CSS theme": "Autoriser un thème CSS personnalisé",
"Allow client settings to be overwritten by the provisioning ones": "Écraser la configuration client avec celle du provisionnement",
"Allow client settings to be overwritten by the provisioning ones": "Écraser la configuration client avec celle du déploiement",
"An email will be sent to :email with a unique link allowing the user to reset its password.": "Un email sera envoyé à :email avec un lien unique l'invitant à réinitialiser son mot de passe",
"An email will be sent to :email with a QR Code and provisioning link.": "Un email sera envoyé à :email contenant un QR Code et un lien de provisionnement.",
"An email will be sent to :email with a QR Code and provisioning link.": "Un email sera envoyé à :email contenant un QR Code et un lien de déploiement.",
"An email will be sent to this email when someone join the newsletter": "Un email sera envoyé à cette addresse quand quelqu'un rejoint la liste de diffusion",
"App Configuration": "Configuration de l'App",
"Api Keys": "Clefs d'API",
@ -115,6 +116,7 @@
"Never expire": "N'expire jamais",
"New Admin": "Nouvel Admin",
"Newsletter registration email address": "Addresse email d'inscription à la liste de diffusion",
"Newsletter registration confirmed": "Confirmation de l'inscription à la newsletter",
"Next": "Suivant",
"No account yet?": "Pas encore de compte ?",
"No email yet": "Pas d'email pour le moment",
@ -131,8 +133,9 @@
"Please enter the new email that you would like to link to your account.": "Veuillez entre l'adresse email que vous souhaitez lier à votre compte.",
"Please enter the new phone number that you would like to link to your account.": "Veuillez entrer le numéro de téléphone que vous souhaitez lier à votre compte.",
"Protocol": "Protocole",
"Provisioning tokens": "Jetons de provisionnement",
"Provisioning": "Provisionnement",
"Provisioning tokens": "Jetons de déploiement",
"Provisioning": "Déploiement",
"Provisioning of your device": "Déploiement sur votre appareil",
"Public registration": "Inscription publiques",
"QR Code scanning": "Scan de QR Code",
"Realm": "Royaume",
@ -142,12 +145,14 @@
"Register": "Inscription",
"Registrar": "Registrar",
"Registration introduction": "Présentation lors de l'inscription",
"Registration confirmed": "Confirmation de l'inscription",
"Remove": "Remove",
"Renew": "Renouveller",
"Requests": "Requêtes",
"Resend": "Ré-envoyer",
"Reset password emails": "Email de réinitialisation de mot de passe",
"Reset password": "Réinitialiser le mot de passe",
"Reset your password": "Réinitialiser votre mot de passe",
"Reset": "Réinitialiser",
"Role": "Rôle",
"Scan the following QR Code using an authenticated device and wait a few seconds.": "Scanner le QR Code avec un appareil authentifié et attendez quelques secondes",
@ -156,7 +161,7 @@
"Select a domain": "Sélectionner un domaine",
"Select a file": "Choisir un fichier",
"Send an email to the user to reset the password": "Envoyer un email à l'utilisateur pour réinitialiser son mot de passe",
"Send an email to the user with provisioning information": "Envoyer un email à l'utilisateur avec les informations de provisionnement",
"Send an email to the user with provisioning information": "Envoyer un email à l'utilisateur avec les informations de déploiement",
"Send": "Envoyer",
"Settings": "Paramètres",
"Sip Adress": "Adresse SIP",

View file

@ -34,6 +34,11 @@
@if ($account->passwords()->count() > 0)
<p><i class="ph">password</i> {{ __('Password') }}: **********</p>
@endif
<p>
<i class="ph">globe-hemisphere-west</i>
{{ __('Space') }}: <a href="{{ route('admin.spaces.show', $account->space->id) }}">{{ $account->domain }}</a>
</p>
<p>
@include('admin.account.parts.badges', ['account' => $account])
</p>

View file

@ -1,30 +0,0 @@
<html>
<head>
<title>Authenticate on {{ space()->name }}</title>
</head>
<body>
<p>Hello,</p>
<p>
You are trying to authenticate to {{ space()->name }} using your email account.<br />
Please enter the code bellow to finish the authentication process.
</p>
<p>
<h2>{{ $recovery_code }}</h2>
</p>
@if ($expiration_minutes > 0)
<p>
The code is only available {{ $expiration_minutes }} minutes.
</p>
@endif
<p>
You can as well configure your new device using the following code or by directly flashing the QRCode:<br />
<img src="{{ $provisioning_qrcode}}"><br />
<a href="{{ $provisioning_link }}">Provisioning link</a>
</p>
<p>
Regards,<br />
{{ config('mail.signature') }}
</p>
</body>
</html>

View file

@ -1,25 +0,0 @@
<html>
<head>
<title>Authenticate on {{ space()->name }}</title>
</head>
<body>
<p>Hello,</p>
<p>
You are trying to authenticate to {{ space()->name }} using your email account.<br />
Please enter the code bellow to finish the authentication process.
</p>
<p>
<h2>{{ $recovery_code }}</h2>
</p>
<p>
You can as well configure your new device using the following code or by directly flashing the QRCode:<br />
<img src="{{ $provisioning_qrcode}}"><br />
<a href="{{ $provisioning_link }}">Provisioning link</a>
</p>
<p>
Regards,<br />
{{ config('mail.signature') }}
</p>
</body>
</html>

View file

@ -1,17 +0,0 @@
Hello,
You are trying to authenticate to {{ space()->name }} using your email account.
Please enter the code bellow to finish the authentication process.
{{ $recovery_code }}
@if ($expiration_minutes > 0)
The code is only available {{ $expiration_minutes }} minutes.
@endif
You can as well configure your new device using the following code or by directly flashing the QRCode in the following link:
{{ $provisioning_qrcode}}
Regards,
{{ config('mail.signature') }}

View file

@ -1,13 +0,0 @@
Hello,
You are trying to authenticate to {{ space()->name }} using your email account.
Please enter the code bellow to finish the authentication process.
{{ $recovery_code }}
You can as well configure your new device using the following code or by directly flashing the QRCode in the following link:
{{ $provisioning_qrcode}}
Regards,
{{ config('mail.signature') }}

View file

@ -1,32 +1,26 @@
<html>
<head>
<title>Registration confirmed {{ space()->name }}</title>
</head>
<body>
<p>Hello,</p>
<p>
@if (space()->confirmed_registration_text)
{{ strip_tags(parsedown(space()->confirmed_registration_text)) }}
@else
Your SIP account has been successfully created.<br />
You can now configure this account on any SIP-compatible application using the following parameters:<br />
<br />
@endif
@extends('mails.layout')
<b>SIP address:</b> sip:{{ $account->identifier }}<br />
<b>Username:</b> {{ $account->username }}<br />
<b>Domain:</b> {{ $account->domain }}<br />
<br />
@if (!empty(space()?->account_proxy_registrar_address))
<b>Proxy/registrar address: </b> sip:{{ space()?->account_proxy_registrar_address }}<br />
@endif
@if (!empty(config('app.transport_protocol_text')))
<b>Transport: </b> {{ config('app.transport_protocol_text') }} <br />
@endif
</p>
<p>
Regards,<br />
{{ config('mail.signature') }}
</p>
</body>
</html>
@section('content')
# Welcome to {{ $account->space->name }}
Hello {{ $account->identifier }},
@if ($account->space->confirmed_registration_text)
{{ strip_tags(parsedown($account->space->confirmed_registration_text)) }}
@else
Your SIP account has been successfully created.
You can now configure this account on any SIP-compatible application using the following parameters:
@endif
* SIP address: sip:{{ $account->identifier }}
* Username: {{ $account->username }}
* Domain: {{ $account->domain }}
@if (!empty($account->space->account_proxy_registrar_address))
* Proxy/registrar address: sip:{{ $account->space->account_proxy_registrar_address }}
@endif
@if (!empty(config('app.transport_protocol_text')))
* Transport: {{ config('app.transport_protocol_text') }}
@endif
@endsection

View file

@ -1,26 +0,0 @@
Registration confirmed {{ space()->name }}
Hello,
@if (space()->confirmed_registration_text)
{{ strip_tags(parsedown(space()->confirmed_registration_text)) }}
@else
Your SIP account has been successfully created.
You can now configure this account on any SIP-compatible application using the following parameters:
@endif
SIP address: sip:{{ $account->identifier }}
Username: {{ $account->username }}
Domain: {{ $account->domain }}
@if (!empty(space()?->account_proxy_registrar_address))
Proxy/registrar address: sip:{{ space()?->account_proxy_registrar_address }}
@endif
@if (!empty(config('app.transport_protocol_text')))
Transport: {{ config('app.transport_protocol_text') }}
@endif
Regards,
{{ config('mail.signature') }}
strip_tags

View file

@ -0,0 +1,14 @@
<x-mail::message>
@yield('content')
Regards,
{{ config('mail.signature') }}
<x-mail::panel>
You dont have the app yet? [Download Linphone](https://www.linphone.org/en/docs/install-linphone/)
Need help? [Visit our user guide](https://linphone.org/en/docs)
</x-mail::panel>
</x-mail::message>

View file

@ -1,11 +1,7 @@
<html>
<head>
<title>Mailing list email registration</title>
</head>
<body>
<p>Hello,</p>
<p>
The following email address wants to register to the mailing list: {{ $account->email }}.
</p>
</body>
</html>
@extends('mails.layout')
@section('content')
Hello,
The following email address wants to register to the mailing list: {{ $account->email }}.
@endsection

View file

@ -1,3 +0,0 @@
Hello,
The following email address wants to register to the mailing list: {{ $account->email }}.

View file

@ -0,0 +1,9 @@
To connect your account to the application, click on the following button:
<x-mail::button :url="route('provisioning.provision', ['provisioning_token' => $account->provisioning_token, 'reset_password' => true])" color="primary">
Connect my account
</x-mail::button>
You can also configure your device by scanning the QR code with the mobile app, or by pasting the link below into the desktop application.
![QRCode]({{ route('provisioning.qrcode', ['provisioning_token' => $account->provisioning_token, 'reset_password' => true]) }})

View file

@ -1,20 +1,9 @@
<html>
<head>
<title>Authenticate on {{ space()->name }}</title>
</head>
<body>
<p>Hello,</p>
<p>
You are trying to authenticate to {{ space()->name }} using your device.<br />
You can configure your new device by directly flashing the QRCode or using the provisioning link:<br />
@extends('mails.layout')
<img src="{{ $provisioning_qrcode}}"><br />
@section('content')
# Welcome to {{ space()->name }}
Provisioning link: {{ $provisioning_link }}
</p>
<p>
Regards,<br />
{{ config('mail.signature') }}
</p>
</body>
</html>
Hello {{ $account->identifier }},
@include('mails.parts.provisioning')
@endsection

View file

@ -1,19 +1,9 @@
<html>
<head>
<title>Authenticate on {{ space()->name }}</title>
</head>
<body>
<p>Hello,</p>
<p>
You are trying to authenticate to {{ space()->name }} using your device.<br />
You can configure your new device by directly flashing the QRCode or using the provisioning link:<br />
@extends('mails.layout')
<img src="{{ $provisioning_qrcode}}"><br />
Provisioning link: {{ $provisioning_link }}
</p>
<p>
Regards,<br />
{{ config('mail.signature') }}
</p>
</body>
</html>
@section('content')
# Welcome to {{ space()->name }}
Hello {{ $account->identifier }},
@include('mails.parts.provisioning')
@endsection

View file

@ -1,10 +0,0 @@
Hello,
You are trying to authenticate to {{ space()->name }} using your device.
You can configure your new device by using the provisioning link.
Provisioning link: {{ $provisioning_link }}
Regards,
{{ config('mail.signature') }}

View file

@ -1,10 +0,0 @@
Hello,
You are trying to authenticate to {{ space()->name }} using your device.
You can configure your new device by using the provisioning link.
Provisioning link: {{ $provisioning_link }}
Regards,
{{ config('mail.signature') }}

View file

@ -0,0 +1,20 @@
@extends('mails.layout')
@section('content')
# Authenticate on {{ $account->space->name }}
Hello {{ $account->identifier }},
You are trying to authenticate to {{ $account->space->name }} using your email account.
Please enter the code bellow to finish the authentication process.
## {{ $account->recovery_code }
@if (config('app.recovery_code_expiration_minutes') > 0)
The code is only available {{ config('app.recovery_code_expiration_minutes') }} minutes.
@endif
@include('mails.parts.provisioning')
@endsection

View file

@ -0,0 +1,20 @@
@extends('mails.layout')
@section('content')
# Authenticate on {{ $account->space->name }}
Hello {{ $account->identifier }},
You are trying to authenticate to {{ $account->space->name }} using your email account.
Please enter the code bellow to finish the authentication process.
## {{ $account->recovery_code }
@if (config('app.recovery_code_expiration_minutes') > 0)
The code is only available {{ config('app.recovery_code_expiration_minutes') }} minutes.
@endif
@include('mails.parts.provisioning')
@endsection

View file

@ -1,19 +0,0 @@
<html>
<head>
<title>Account registered on {{ space()->name }}</title>
</head>
<body>
<p>Hello,</p>
<p>
You just created an account on {{ space()->name }} using your email account.<br />
Please enter the following code on the confirmation page:
</p>
<p>
<h2>{{ $code }}</h2>
</p>
<p>
Regards,<br />
{{ config('mail.signature') }}
</p>
</body>
</html>

View file

@ -1,10 +0,0 @@
Hello,
You just created an account on {{ space()->name }} using your email account.
Please enter the following code on the confirmation page:
{{ $code }}
Regards,
{{ config('mail.signature') }}

View file

@ -0,0 +1,13 @@
@extends('mails.layout')
@section('content')
# Account registration on {{ $account->space->name }}
Hello {{ $account->identifier }},
You just created an account on {{ $account->space->name }} using your email account.
Please enter the following code on the confirmation page:
## {{ $account->emailChangeCode()->first()->code }}
@endsection

View file

@ -1,21 +1,15 @@
<html>
<head>
<title>Reset your password on {{ space()->name }}</title>
</head>
<body>
<p>Hello,</p>
<p>
You are invited to reset your {{ $token->account->identifier }} account password on {{ space()->name }} via your email account.
</p>
<p>The following link will be valid for {{ config('app.reset_password_email_token_expiration_minutes')/60 }} hours.</p>
<p>
<a href="{{ route('account.reset_password_email.change', $token->token) }}">
{{ route('account.reset_password_email.change', $token->token) }}
</a>
</p>
<p>
Regards,<br />
{{ config('mail.signature') }}
</p>
</body>
</html>
@extends('mails.layout')
@section('content')
# Reset your password on {{ $account->space->name }}
Hello {{ $account->identifier }},
You are invited to reset your {{ $account->identifier }} account password on {{ $account->space->name }} via your email account.
The following link will be valid for {{ config('app.reset_password_email_token_expiration_minutes')/60 }} hours.
<x-mail::button :url="route('account.reset_password_email.change', $account->currentResetPasswordEmailToken->token)" color="primary">
Reset by email
</x-mail::button>
@endsection

View file

@ -1,10 +0,0 @@
Hello,
You are invited to reset your {{ $token->account->identifier }} account password on {{ space()->name }} via your email account.
The following link will be valid for {{ config('app.reset_password_email_token_expiration_minutes')/60 }} hours.
{{ route('account.reset_password_email.change', $token->token) }}
Regards,
{{ config('mail.signature') }}

View file

@ -1,13 +1,18 @@
<table class="action" align="center" width="100%" cellpadding="0" cellspacing="0" role="presentation">
@props([
'url',
'color' => 'primary',
'align' => 'center',
])
<table class="action" align="{{ $align }}" width="100%" cellpadding="0" cellspacing="0" role="presentation">
<tr>
<td align="center">
<td align="{{ $align }}">
<table width="100%" border="0" cellpadding="0" cellspacing="0" role="presentation">
<tr>
<td align="center">
<td align="{{ $align }}">
<table border="0" cellpadding="0" cellspacing="0" role="presentation">
<tr>
<td>
<a href="{{ $url }}" class="button button-{{ $color ?? 'primary' }}" target="_blank" rel="noopener">{{ $slot }}</a>
<a href="{{ $url }}" class="button button-{{ $color }}" target="_blank" rel="noopener">{{ $slot }}</a>
</td>
</tr>
</table>

View file

@ -1,3 +1,4 @@
@props(['url'])
<tr>
<td class="header">
<a href="{{ $url }}" style="display: inline-block;">

View file

@ -1,10 +1,11 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>{{ config('app.name') }}</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
<meta name="color-scheme" content="light">
<meta name="supported-color-schemes" content="light">
<style>
@media only screen and (max-width: 600px) {
.inner-body {
@ -22,6 +23,8 @@ width: 100% !important;
}
}
</style>
</head>
<body>
<table class="wrapper" width="100%" cellpadding="0" cellspacing="0" role="presentation">
<tr>
@ -31,7 +34,7 @@ width: 100% !important;
<!-- Email Body -->
<tr>
<td class="body" width="100%" cellpadding="0" cellspacing="0">
<td class="body" width="100%" cellpadding="0" cellspacing="0" style="border: hidden !important;">
<table class="inner-body" align="center" width="570" cellpadding="0" cellspacing="0" role="presentation">
<!-- Body content -->
<tr>

View file

@ -1,27 +1,27 @@
@component('mail::layout')
<x-mail::layout>
{{-- Header --}}
@slot('header')
@component('mail::header', ['url' => config('app.url')])
{{ space()->name }}
@endcomponent
@endslot
<x-slot:header>
<x-mail::header :url="config('app.url')">
{{ config('app.name') }}
</x-mail::header>
</x-slot:header>
{{-- Body --}}
{{ $slot }}
{{-- Subcopy --}}
@isset($subcopy)
@slot('subcopy')
@component('mail::subcopy')
<x-slot:subcopy>
<x-mail::subcopy>
{{ $subcopy }}
@endcomponent
@endslot
</x-mail::subcopy>
</x-slot:subcopy>
@endisset
{{-- Footer --}}
@slot('footer')
@component('mail::footer')
© {{ date('Y') }} {{ space()->name }}. @lang('All rights reserved.')
@endcomponent
@endslot
@endcomponent
<x-slot:footer>
<x-mail::footer>
© {{ date('Y') }} {{ config('app.name') }}. @lang('All rights reserved.')
</x-mail::footer>
</x-slot:footer>
</x-mail::layout>

View file

@ -1,3 +1,3 @@
<div>
<div class="table">
{{ Illuminate\Mail\Markdown::parse($slot) }}
</div>

View file

@ -28,7 +28,7 @@ blockquote {
}
a {
color: #3869d4;
color: rgba(254, 94, 0, 1);
}
a img {
@ -74,13 +74,18 @@ img {
max-width: 100%;
}
p img {
display: block;
margin: 0 auto;
}
/* Layout */
.wrapper {
-premailer-cellpadding: 0;
-premailer-cellspacing: 0;
-premailer-width: 100%;
background-color: #edf2f7;
background-color: rgba(249, 249, 249, 1);
margin: 0;
padding: 0;
width: 100%;
@ -113,6 +118,7 @@ img {
.logo {
height: 75px;
max-height: 75px;
width: 75px;
}
@ -122,9 +128,9 @@ img {
-premailer-cellpadding: 0;
-premailer-cellspacing: 0;
-premailer-width: 100%;
background-color: #edf2f7;
border-bottom: 1px solid #edf2f7;
border-top: 1px solid #edf2f7;
background-color: rgba(249, 249, 249, 1);
border-bottom: 1px solid rgba(249, 249, 249, 1);
border-top: 1px solid rgba(249, 249, 249, 1);
margin: 0;
padding: 0;
width: 100%;
@ -231,11 +237,9 @@ img {
.button-blue,
.button-primary {
background-color: #2d3748;
border-bottom: 8px solid #2d3748;
border-left: 18px solid #2d3748;
border-right: 18px solid #2d3748;
border-top: 8px solid #2d3748;
border-radius: 3rem;
background-color: rgba(254, 94, 0, 1);
padding: 0.5rem 1rem;
}
.button-green,
@ -259,12 +263,12 @@ img {
/* Panels */
.panel {
border-left: #2d3748 solid 4px;
margin: 21px 0;
}
.panel-content {
background-color: #edf2f7;
background-color: rgba(249, 249, 249, 1);
border-radius: 1rem;
color: #718096;
padding: 16px;
}

View file

@ -1 +1 @@
[{{ $slot }}]({{ $url }})
{{ $slot }}: {{ $url }}

View file

@ -1,4 +1,4 @@
{!! strip_tags($header) !!}
{!! strip_tags($header ?? '') !!}
{!! strip_tags($slot) !!}
@isset($subcopy)
@ -6,4 +6,4 @@
{!! strip_tags($subcopy) !!}
@endisset
{!! strip_tags($footer) !!}
{!! strip_tags($footer ?? '') !!}

View file

@ -1,27 +1,27 @@
@component('mail::layout')
<x-mail::layout>
{{-- Header --}}
@slot('header')
@component('mail::header', ['url' => config('app.url')])
{{ space()->name }}
@endcomponent
@endslot
<x-slot:header>
<x-mail::header :url="config('app.url')">
{{ config('app.name') }}
</x-mail::header>
</x-slot:header>
{{-- Body --}}
{{ $slot }}
{{-- Subcopy --}}
@isset($subcopy)
@slot('subcopy')
@component('mail::subcopy')
<x-slot:subcopy>
<x-mail::subcopy>
{{ $subcopy }}
@endcomponent
@endslot
</x-mail::subcopy>
</x-slot:subcopy>
@endisset
{{-- Footer --}}
@slot('footer')
@component('mail::footer')
© {{ date('Y') }} {{ space()->name }}. @lang('All rights reserved.')
@endcomponent
@endslot
@endcomponent
<x-slot:footer>
<x-mail::footer>
© {{ date('Y') }} {{ config('app.name') }}. @lang('All rights reserved.')
</x-mail::footer>
</x-slot:footer>
</x-mail::layout>