Make email messages Markdown.

This commit is contained in:
James Cole 2022-03-29 12:45:48 +02:00
parent 9c19a08b17
commit 09bd0b572a
No known key found for this signature in database
GPG Key ID: B49A324B7EAD6D80
71 changed files with 747 additions and 555 deletions

View File

@ -37,21 +37,16 @@ class AdminRequestedTestMessage extends Event
{
use SerializesModels;
/** @var string The users IP address */
public $ipAddress;
/** @var User The user */
public $user;
public User $user;
/**
* Create a new event instance.
*
* @param User $user
* @param string $ipAddress
*/
public function __construct(User $user, string $ipAddress)
public function __construct(User $user)
{
Log::debug(sprintf('Triggered AdminRequestedTestMessage for user #%d (%s) and IP %s!', $user->id, $user->email, $ipAddress));
Log::debug(sprintf('Triggered AdminRequestedTestMessage for user #%d (%s)', $user->id, $user->email));
$this->user = $user;
$this->ipAddress = $ipAddress;
}
}

View File

@ -40,10 +40,8 @@ class RequestedReportOnJournals
{
use Dispatchable, InteractsWithSockets, SerializesModels;
/** @var Collection The transaction groups to report on. */
public $groups;
/** @var int The ID of the user. */
public $userId;
public Collection $groups;
public int $userId;
/**
* Create a new event instance.

View File

@ -36,14 +36,9 @@ class UserChangedEmail extends Event
{
use SerializesModels;
/** @var string The user's IP address */
public $ipAddress;
/** @var string The user's new email address */
public $newEmail;
/** @var string The user's old email address */
public $oldEmail;
/** @var User The user itself */
public $user;
public string $newEmail;
public string $oldEmail;
public User $user;
/**
* UserChangedEmail constructor.
@ -51,12 +46,10 @@ class UserChangedEmail extends Event
* @param User $user
* @param string $newEmail
* @param string $oldEmail
* @param string $ipAddress
*/
public function __construct(User $user, string $newEmail, string $oldEmail, string $ipAddress)
public function __construct(User $user, string $newEmail, string $oldEmail)
{
$this->user = $user;
$this->ipAddress = $ipAddress;
$this->oldEmail = $oldEmail;
$this->newEmail = $newEmail;
}

View File

@ -59,18 +59,16 @@ class APIEventHandler
$email = config('firefly.site_owner');
}
$ipAddress = Request::ip();
// see if user has alternative email address:
$pref = app('preferences')->getForUser($user, 'remote_guard_alt_email');
if (null !== $pref) {
$email = (string)(is_array($pref->data) ? $email : $pref->data);
}
Log::debug(sprintf('Now in APIEventHandler::accessTokenCreated. Email is %s, IP is %s', $email, $ipAddress));
Log::debug(sprintf('Now in APIEventHandler::accessTokenCreated. Email is %s', $email));
try {
Log::debug('Trying to send message...');
Mail::to($email)->send(new AccessTokenCreatedMail($email, $ipAddress));
Mail::to($email)->send(new AccessTokenCreatedMail);
} catch (Exception $e) { // @phpstan-ignore-line
Log::debug('Send message failed! :(');

View File

@ -52,7 +52,6 @@ class AdminEventHandler
// is user even admin?
if ($repository->hasRole($event->user, 'owner')) {
$email = $event->user->email;
$ipAddress = $event->ipAddress;
// if user is demo user, send to owner:
if ($event->user->hasRole('demo')) {
@ -65,10 +64,10 @@ class AdminEventHandler
$email = $pref->data;
}
Log::debug(sprintf('Now in sendTestMessage event handler. Email is %s, IP is %s', $email, $ipAddress));
Log::debug(sprintf('Now in sendTestMessage event handler. Email is %s', $email));
try {
Log::debug('Trying to send message...');
Mail::to($email)->send(new AdminTestMail($email, $ipAddress));
Mail::to($email)->send(new AdminTestMail($email));
// Laravel cannot pretend this process failed during testing.
} catch (Exception $e) { // @phpstan-ignore-line

View File

@ -58,23 +58,9 @@ class AutomationHandler
$repository = app(UserRepositoryInterface::class);
$user = $repository->find($event->userId);
if (null !== $user && 0 !== $event->groups->count()) {
$email = $user->email;
// see if user has alternative email address:
$pref = app('preferences')->getForUser($user, 'remote_guard_alt_email');
if (null !== $pref) {
$email = $pref->data;
}
// if user is demo user, send to owner:
if ($user->hasRole('demo')) {
$email = config('firefly.site_owner');
}
try {
Log::debug('Trying to mail...');
Mail::to($user->email)->send(new ReportNewJournalsMail($email, '127.0.0.1', $event->groups));
Mail::to($user->email)->send(new ReportNewJournalsMail($event->groups));
} catch (Exception $e) { // @phpstan-ignore-line
Log::debug('Send message failed! :(');

View File

@ -229,11 +229,10 @@ class UserEventHandler
$newEmail = $event->newEmail;
$oldEmail = $event->oldEmail;
$user = $event->user;
$ipAddress = $event->ipAddress;
$token = app('preferences')->getForUser($user, 'email_change_confirm_token', 'invalid');
$uri = route('profile.confirm-email-change', [$token->data]);
try {
Mail::to($newEmail)->send(new ConfirmEmailChangeMail($newEmail, $oldEmail, $uri, $ipAddress));
Mail::to($newEmail)->send(new ConfirmEmailChangeMail($newEmail, $oldEmail, $uri));
} catch (Exception $e) { // @phpstan-ignore-line
Log::error($e->getMessage());
@ -255,12 +254,11 @@ class UserEventHandler
$newEmail = $event->newEmail;
$oldEmail = $event->oldEmail;
$user = $event->user;
$ipAddress = $event->ipAddress;
$token = app('preferences')->getForUser($user, 'email_change_undo_token', 'invalid');
$hashed = hash('sha256', sprintf('%s%s', (string)config('app.key'), $oldEmail));
$uri = route('profile.undo-email-change', [$token->data, $hashed]);
try {
Mail::to($oldEmail)->send(new UndoEmailChangeMail($newEmail, $oldEmail, $uri, $ipAddress));
Mail::to($oldEmail)->send(new UndoEmailChangeMail($newEmail, $oldEmail, $uri));
} catch (Exception $e) { // @phpstan-ignore-line
Log::error($e->getMessage());

View File

@ -83,9 +83,8 @@ class HomeController extends Controller
Log::channel('audit')->info('User sends test message.');
/** @var User $user */
$user = auth()->user();
$ipAddress = $request->ip();
Log::debug(sprintf('Now in testMessage() controller. IP is %s', $ipAddress));
event(new AdminRequestedTestMessage($user, $ipAddress));
Log::debug('Now in testMessage() controller.');
event(new AdminRequestedTestMessage($user));
session()->flash('info', (string)trans('firefly.send_test_triggered'));
return redirect(route('admin.index'));

View File

@ -96,7 +96,7 @@ class RegisterController extends Controller
$this->validator($request->all())->validate();
$user = $this->createUser($request->all());
Log::info(sprintf('Registered new user %s', $user->email));
event(new RegisteredUser($user, $request->ip()));
event(new RegisteredUser($user));
$this->guard()->login($user);

View File

@ -27,6 +27,7 @@ use Exception;
use FireflyIII\Events\RequestedVersionCheckStatus;
use FireflyIII\Helpers\Collector\GroupCollectorInterface;
use FireflyIII\Http\Middleware\Installer;
use FireflyIII\Mail\UndoEmailChangeMail;
use FireflyIII\Models\AccountType;
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\Repositories\Bill\BillRepositoryInterface;
@ -35,6 +36,7 @@ use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Collection;
use Log;
use Mail;
/**
* Class HomeController.

View File

@ -427,9 +427,7 @@ class ProfileController extends Controller
// now actually update user:
$repository->changeEmail($user, $newEmail);
// call event.
$ipAddress = $request->ip();
event(new UserChangedEmail($user, $newEmail, $oldEmail, $ipAddress));
event(new UserChangedEmail($user, $newEmail, $oldEmail));
// force user logout.
Auth::guard()->logout();

View File

@ -37,21 +37,11 @@ class AccessTokenCreatedMail extends Mailable
use Queueable, SerializesModels;
/** @var string Email address of admin */
public $email;
/** @var string IP address of admin */
public $ipAddress;
/**
* AccessTokenCreatedMail constructor.
*
* @param string $email
* @param string $ipAddress
*/
public function __construct(string $email, string $ipAddress)
public function __construct()
{
$this->email = $email;
$this->ipAddress = $ipAddress;
}
/**
@ -61,7 +51,8 @@ class AccessTokenCreatedMail extends Mailable
*/
public function build(): self
{
return $this->view('emails.access-token-created-html')->text('emails.access-token-created-text')
return $this
->markdown('emails.token-created')
->subject((string)trans('email.access_token_created_subject'));
}
}

View File

@ -38,18 +38,15 @@ class AdminTestMail extends Mailable
use Queueable, SerializesModels;
public string $email;
public string $ipAddress;
/**
* ConfirmEmailChangeMail constructor.
*
* @param string $email
* @param string $ipAddress
*/
public function __construct(string $email, string $ipAddress)
public function __construct(string $email)
{
$this->email = $email;
$this->ipAddress = $ipAddress;
}
/**
@ -59,7 +56,8 @@ class AdminTestMail extends Mailable
*/
public function build(): self
{
return $this->view('emails.admin-test-html')->text('emails.admin-test-text')
return $this
->markdown('emails.admin-test')
->subject((string)trans('email.admin_test_subject'));
}
}

View File

@ -14,7 +14,6 @@ class BillWarningMail extends Mailable
public Bill $bill;
public string $field;
public int $diff;
public string $ipAddress;
/**
* ConfirmEmailChangeMail constructor.
@ -22,14 +21,12 @@ class BillWarningMail extends Mailable
* @param Bill $bill
* @param string $field
* @param int $diff
* @param string $ipAddress
*/
public function __construct(Bill $bill, string $field, int $diff, string $ipAddress)
public function __construct(Bill $bill, string $field, int $diff)
{
$this->bill = $bill;
$this->field = $field;
$this->diff = $diff;
$this->ipAddress = $ipAddress;
}
/**
@ -45,8 +42,7 @@ class BillWarningMail extends Mailable
}
return $this
->view('emails.bill-warning-html')
->text('emails.bill-warning-text')
->markdown('emails.bill-warning')
->subject($subject);
}
}

View File

@ -37,25 +37,23 @@ class ConfirmEmailChangeMail extends Mailable
{
use Queueable, SerializesModels;
public string $ipAddress;
public string $newEmail;
public string $oldEmail;
public string $uri;
public string $url;
/**
* ConfirmEmailChangeMail constructor.
*
* @param string $newEmail
* @param string $oldEmail
* @param string $uri
* @param string $url
* @param string $ipAddress
*/
public function __construct(string $newEmail, string $oldEmail, string $uri, string $ipAddress)
public function __construct(string $newEmail, string $oldEmail, string $url)
{
$this->newEmail = $newEmail;
$this->oldEmail = $oldEmail;
$this->uri = $uri;
$this->ipAddress = $ipAddress;
$this->url = $url;
}
/**
@ -65,7 +63,10 @@ class ConfirmEmailChangeMail extends Mailable
*/
public function build(): self
{
return $this->view('emails.confirm-email-change-html')->text('emails.confirm-email-change-text')
return $this
//->view('emails.confirm-email-change-html')
//->text('emails.confirm-email-change-text')
->markdown('emails.confirm-email-change')
->subject((string) trans('email.email_change_subject'));
}
}

View File

@ -56,8 +56,6 @@ class NewIPAddressWarningMail extends Mailable
*/
public function build(): self
{
// time
$this->time = now(config('app.timezone'))->isoFormat((string)trans('config.date_time_js'));
$this->host = '';
try {
@ -69,7 +67,8 @@ class NewIPAddressWarningMail extends Mailable
$this->host = $hostName;
}
return $this->view('emails.new-ip-html')->text('emails.new-ip-text')
return $this
->markdown('emails.new-ip')
->subject((string)trans('email.login_from_new_ip'));
}
}

View File

@ -37,24 +37,15 @@ class OAuthTokenCreatedMail extends Mailable
{
use Queueable, SerializesModels;
/** @var Client The client */
public $client;
/** @var string Email address of admin */
public $email;
/** @var string IP address of admin */
public $ipAddress;
public Client $client;
/**
* OAuthTokenCreatedMail constructor.
*
* @param string $email
* @param string $ipAddress
* @param Client $client
*/
public function __construct(string $email, string $ipAddress, Client $client)
public function __construct(Client $client)
{
$this->email = $email;
$this->ipAddress = $ipAddress;
$this->client = $client;
}
@ -65,7 +56,8 @@ class OAuthTokenCreatedMail extends Mailable
*/
public function build(): self
{
return $this->view('emails.oauth-client-created-html')->text('emails.oauth-client-created-text')
return $this
->markdown('emails.oauth-client-created')
->subject((string) trans('email.oauth_created_subject'));
}
}

View File

@ -38,21 +38,16 @@ class RegisteredUser extends Mailable
{
use Queueable, SerializesModels;
/** @var string Email address of user */
public $address;
/** @var string IP address of user */
public $ipAddress;
public string $address;
/**
* Create a new message instance.
*
* @param string $address
* @param string $ipAddress
*/
public function __construct(string $address, string $ipAddress)
public function __construct(string $address)
{
$this->address = $address;
$this->ipAddress = $ipAddress;
}
/**
@ -62,6 +57,8 @@ class RegisteredUser extends Mailable
*/
public function build(): self
{
return $this->view('emails.registered-html')->text('emails.registered-text')->subject((string)trans('email.registered_subject'));
return $this
->markdown('emails.registered')
->subject((string)trans('email.registered_subject'));
}
}

View File

@ -40,22 +40,16 @@ class ReportNewJournalsMail extends Mailable
{
use Queueable, SerializesModels;
public string $email;
public Collection $groups;
public string $ipAddress;
public array $transformed;
/**
* ConfirmEmailChangeMail constructor.
*
* @param string $email
* @param string $ipAddress
* @param Collection $groups
*/
public function __construct(string $email, string $ipAddress, Collection $groups)
public function __construct(Collection $groups)
{
$this->email = $email;
$this->ipAddress = $ipAddress;
$this->groups = $groups;
}
@ -68,7 +62,8 @@ class ReportNewJournalsMail extends Mailable
{
$this->transform();
return $this->view('emails.report-new-journals-html')->text('emails.report-new-journals-text')
return $this
->markdown('emails.report-new-journals')
->subject((string) trans_choice('email.new_journals_subject', $this->groups->count()));
}

View File

@ -37,21 +37,16 @@ class RequestedNewPassword extends Mailable
{
use Queueable, SerializesModels;
/** @var string IP address of user */
public $ipAddress;
/** @var string URI of password change link */
public $url;
public string $url;
/**
* RequestedNewPassword constructor.
*
* @param string $url
* @param string $ipAddress
*/
public function __construct(string $url, string $ipAddress)
public function __construct(string $url)
{
$this->url = $url;
$this->ipAddress = $ipAddress;
}
/**
@ -61,6 +56,8 @@ class RequestedNewPassword extends Mailable
*/
public function build(): self
{
return $this->view('emails.password-html')->text('emails.password-text')->subject((string)trans('email.reset_pw_subject'));
return $this
->markdown('emails.password')
->subject((string)trans('email.reset_pw_subject'));
}
}

View File

@ -35,29 +35,22 @@ class UndoEmailChangeMail extends Mailable
{
use Queueable, SerializesModels;
/** @var string IP address of user */
public $ipAddress;
/** @var string New email address */
public $newEmail;
/** @var string Old email address */
public $oldEmail;
/** @var string URI to undo */
public $uri;
public string $newEmail;
public string $oldEmail;
public string $url;
/**
* UndoEmailChangeMail constructor.
*
* @param string $newEmail
* @param string $oldEmail
* @param string $uri
* @param string $ipAddress
* @param string $url
*/
public function __construct(string $newEmail, string $oldEmail, string $uri, string $ipAddress)
public function __construct(string $newEmail, string $oldEmail, string $url)
{
$this->newEmail = $newEmail;
$this->oldEmail = $oldEmail;
$this->uri = $uri;
$this->ipAddress = $ipAddress;
$this->url = $url;
}
/**
@ -67,7 +60,8 @@ class UndoEmailChangeMail extends Mailable
*/
public function build(): self
{
return $this->view('emails.undo-email-change-html')->text('emails.undo-email-change-text')
return $this
->markdown('emails.undo-email-change')
->subject((string)trans('email.email_change_subject'));
}
}

View File

@ -179,7 +179,6 @@ class EventServiceProvider extends ServiceProvider
}
$email = $user->email;
$ipAddress = Request::ip();
// see if user has alternative email address:
$pref = app('preferences')->getForUser($user, 'remote_guard_alt_email');
@ -187,10 +186,10 @@ class EventServiceProvider extends ServiceProvider
$email = $pref->data;
}
Log::debug(sprintf('Now in EventServiceProvider::registerCreateEvents. Email is %s, IP is %s', $email, $ipAddress));
Log::debug(sprintf('Now in EventServiceProvider::registerCreateEvents. Email is %s', $email));
try {
Log::debug('Trying to send message...');
Mail::to($email)->send(new OAuthTokenCreatedMail($email, $ipAddress, $oauthClient));
Mail::to($email)->send(new OAuthTokenCreatedMail($oauthClient));
} catch (Exception $e) { // @phpstan-ignore-line
Log::debug('Send message failed! :(');
Log::error($e->getMessage());

View File

@ -1,6 +1,9 @@
<?php
declare(strict_types=1);
use FireflyIII\Http\Middleware\EncryptCookies;
use FireflyIII\Http\Middleware\VerifyCsrfToken;
return [
/*
@ -55,8 +58,8 @@ return [
*/
'middleware' => [
'verify_csrf_token' => \FireflyIII\Http\Middleware\VerifyCsrfToken::class,
'encrypt_cookies' => \FireflyIII\Http\Middleware\EncryptCookies::class,
'verify_csrf_token' => VerifyCsrfToken::class,
'encrypt_cookies' => EncryptCookies::class,
],
];

View File

@ -44,16 +44,16 @@ return [
// access token created
'access_token_created_subject' => 'A new access token was created',
'access_token_created_body' => 'Somebody (hopefully you) just created a new Firefly III API Access Token for your user account.',
'access_token_created_explanation' => 'With this token, they can access <strong>all</strong> of your financial records through the Firefly III API.',
'access_token_created_revoke' => 'If this wasn\'t you, please revoke this token as soon as possible at :url.',
'access_token_created_explanation' => 'With this token, they can access **all** of your financial records through the Firefly III API.',
'access_token_created_revoke' => 'If this wasn\'t you, please revoke this token as soon as possible at :url',
// registered
'registered_subject' => 'Welcome to Firefly III!',
'registered_welcome' => 'Welcome to <a style="color:#337ab7" href=":address">Firefly III</a>. Your registration has made it, and this email is here to confirm it. Yay!',
'registered_pw' => 'If you have forgotten your password already, please reset it using <a style="color:#337ab7" href=":address/password/reset">the password reset tool</a>.',
'registered_welcome' => 'Welcome to [Firefly III](:address). Your registration has made it, and this email is here to confirm it. Yay!',
'registered_pw' => 'If you have forgotten your password already, please reset it using [the password reset tool](:address/password/reset).',
'registered_help' => 'There is a help-icon in the top right corner of each page. If you need help, click it!',
'registered_doc_html' => 'If you haven\'t already, please read the <a style="color:#337ab7" href="https://docs.firefly-iii.org/about-firefly-iii/personal-finances">grand theory</a>.',
'registered_doc_text' => 'If you haven\'t already, please read the first use guide and the full description.',
'registered_doc_html' => 'If you haven\'t already, please read the [grand theory](https://docs.firefly-iii.org/about-firefly-iii/personal-finances).',
'registered_doc_text' => 'If you haven\'t already, please also read the first use guide and the full description.',
'registered_closing' => 'Enjoy!',
'registered_firefly_iii_link' => 'Firefly III:',
'registered_pw_reset_link' => 'Password reset:',
@ -62,25 +62,25 @@ return [
// email change
'email_change_subject' => 'Your Firefly III email address has changed',
'email_change_body_to_new' => 'You or somebody with access to your Firefly III account has changed your email address. If you did not expect this message, please ignore and delete it.',
'email_change_body_to_old' => 'You or somebody with access to your Firefly III account has changed your email address. If you did not expect this to happen, you <strong>must</strong> follow the "undo"-link below to protect your account!',
'email_change_body_to_old' => 'You or somebody with access to your Firefly III account has changed your email address. If you did not expect this to happen, you **must** follow the "undo"-link below to protect your account!',
'email_change_ignore' => 'If you initiated this change, you may safely ignore this message.',
'email_change_old' => 'The old email address was: :email',
'email_change_old_strong' => 'The old email address was: <strong>:email</strong>',
'email_change_old_strong' => 'The old email address was: **:email**',
'email_change_new' => 'The new email address is: :email',
'email_change_new_strong' => 'The new email address is: <strong>:email</strong>',
'email_change_new_strong' => 'The new email address is: **:email**',
'email_change_instructions' => 'You cannot use Firefly III until you confirm this change. Please follow the link below to do so.',
'email_change_undo_link' => 'To undo the change, follow this link:',
// OAuth token created
'oauth_created_subject' => 'A new OAuth client has been created',
'oauth_created_body' => 'Somebody (hopefully you) just created a new Firefly III API OAuth Client for your user account. It\'s labeled ":name" and has callback URL <span style="font-family: monospace;">:url</span>.',
'oauth_created_explanation' => 'With this client, they can access <strong>all</strong> of your financial records through the Firefly III API.',
'oauth_created_undo' => 'If this wasn\'t you, please revoke this client as soon as possible at :url.',
'oauth_created_body' => 'Somebody (hopefully you) just created a new Firefly III API OAuth Client for your user account. It\'s labeled ":name" and has callback URL `:url`.',
'oauth_created_explanation' => 'With this client, they can access **all** of your financial records through the Firefly III API.',
'oauth_created_undo' => 'If this wasn\'t you, please revoke this client as soon as possible at `:url`',
// reset password
'reset_pw_subject' => 'Your password reset request',
'reset_pw_instructions' => 'Somebody tried to reset your password. If it was you, please follow the link below to do so.',
'reset_pw_warning' => '<strong>PLEASE</strong> verify that the link actually goes to the Firefly III you expect it to go!',
'reset_pw_warning' => '**PLEASE** verify that the link actually goes to the Firefly III you expect it to go!',
// error
'error_subject' => 'Caught an error in Firefly III',
@ -108,13 +108,10 @@ return [
'bill_warning_subject_now_end_date' => 'Your bill ":name" is due to end TODAY',
'bill_warning_subject_extension_date' => 'Your bill ":name" is due to be extended or cancelled in :diff days',
'bill_warning_subject_now_extension_date' => 'Your bill ":name" is due to be extended or cancelled TODAY',
'bill_warning_end_date_text' => 'Your bill ":name" is due to end on :date. This moment will pass in about :diff days.',
'bill_warning_extension_date_text' => 'Your bill ":name" is due to be extended or cancelled on :date. This moment will pass in about :diff days.',
'bill_warning_end_date_text_zero' => 'Your bill ":name" is due to end on :date. This moment will pass TODAY!',
'bill_warning_extension_date_text_zero' => 'Your bill ":name" is due to be extended or cancelled on :date. This moment will pass TODAY!',
'bill_warning_end_date' => 'Your bill **":name"** is due to end on :date. This moment will pass in about **:diff days**.',
'bill_warning_extension_date' => 'Your bill **":name"** is due to be extended or cancelled on :date. This moment will pass in about **:diff days**.',
'bill_warning_end_date_zero' => 'Your bill **":name"** is due to end on :date. This moment will pass **TODAY!**',
'bill_warning_extension_date_zero' => 'Your bill **":name"** is due to be extended or cancelled on :date. This moment will pass **TODAY!**',
'bill_warning_please_action' => 'Please take the appropriate action.',
'bill_warning_end_date_html' => 'Your bill <strong>":name"</strong> is due to end on :date. This moment will pass in about <strong>:diff days</strong>.',
'bill_warning_extension_date_html' => 'Your bill <strong>":name"</strong> is due to be extended or cancelled on :date. This moment will pass in about <strong>:diff days</strong>.',
'bill_warning_end_date_html_zero' => 'Your bill <strong>":name"</strong> is due to end on :date. This moment will pass <strong>TODAY!</strong>',
'bill_warning_extension_date_html_zero' => 'Your bill <strong>":name"</strong> is due to be extended or cancelled on :date. This moment will pass <strong>TODAY!</strong>',
];

View File

@ -1,13 +0,0 @@
{% include 'emails.header-html' %}
<p style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;font-size:13px;">
{{ trans('email.access_token_created_body') }}
</p>
<p style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;font-size:13px;">
{{ trans('email.access_token_created_explanation')|raw }}
</p>
<p style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;font-size:13px;">
{{ trans('email.access_token_created_revoke', {url: route('profile.index') }) }}
</p>
{% include 'emails.footer-html' %}

View File

@ -1,7 +0,0 @@
{% include 'emails.header-text' %}
{{ trans('email.access_token_created_body')|raw }}
{{ trans('email.access_token_created_explanation')|striptags|raw }}
{{ trans('email.access_token_created_revoke', {url: route('profile.index') })|raw }}
{% include 'emails.footer-text' %}

View File

@ -1,5 +0,0 @@
{% include 'emails.header-html' %}
<p style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;font-size:13px;">
{{ trans('email.admin_test_body', {email: email })}}
</p>
{% include 'emails.footer-html' %}

View File

@ -1,3 +0,0 @@
{% include 'emails.header-text' %}
{{ trans('email.admin_test_body', {email: email })|raw }}
{% include 'emails.footer-text' %}

View File

@ -0,0 +1,3 @@
@component('mail::message')
{{ trans('email.admin_test_body', ['email' => $email]) }}
@endcomponent

View File

@ -1,25 +0,0 @@
{% include 'emails.header-html' %}
<p style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;font-size:13px;">
{% if field == 'end_date' and diff != 0 %}
{{ trans('email.bill_warning_end_date_html', {name: bill.name|escape, date: bill.end_date.isoFormat(trans('config.month_and_day_js')), diff: diff})|raw }}
{% endif %}
{% if field == 'extension_date' and diff != 0 %}
{{ trans('email.bill_warning_extension_date_html', {name: bill.name|escape, date: bill.extension_date.isoFormat(trans('config.month_and_day_js')), diff: diff})|raw }}
{% endif %}
{% if field == 'end_date' and diff == 0 %}
{{ trans('email.bill_warning_end_date_html_zero', {name: bill.name|escape, date: bill.end_date.isoFormat(trans('config.month_and_day_js'))})|raw }}
{% endif %}
{% if field == 'extension_date' and diff == 0 %}
{{ trans('email.bill_warning_extension_date_html_zero', {name: bill.name|escape, date: bill.end_date.isoFormat(trans('config.month_and_day_js'))})|raw }}
{% endif %}
</p>
<p style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;font-size:13px;">
Please take the appropriate action.
</p>
{% include 'emails.footer-html' %}

View File

@ -1,17 +0,0 @@
{% include 'emails.header-text' %}
{% if field == 'end_date' and diff != 0 %}
{{ trans('email.bill_warning_end_date_text', {name: bill.name, date: bill.end_date.isoFormat(trans('config.month_and_day_js')), diff: diff})|raw }}
{% endif %}
{% if field == 'extension_date' and diff != 0 %}
{{ trans('email.bill_warning_extension_date_text', {name: bill.name|escape, date: bill.extension_date.isoFormat(trans('config.month_and_day_js')), diff: diff})|raw }}
{% endif %}
{% if field == 'end_date' and diff == 0 %}
{{ trans('email.bill_warning_end_date_text_zero', {name: bill.name|escape, date: bill.end_date.isoFormat(trans('config.month_and_day_js'))})|raw }}
{% endif %}
{% if field == 'extension_date' and diff == 0 %}
{{ trans('email.bill_warning_extension_date_text_zero', {name: bill.name|escape, date: bill.end_date.isoFormat(trans('config.month_and_day_js'))})|raw }}
{% endif %}
{{ trans('email.bill_warning_please_action') }}
{% include 'emails.footer-text' %}

View File

@ -0,0 +1,20 @@
@component('mail::message')
@if($field === 'end_date' && $diff !== 0)
{{ trans('email.bill_warning_end_date', ['name' => $bill->name, 'date' => $bill->end_date->isoFormat(trans('config.month_and_day_js')), 'diff' => $diff]) }}
@endif
@if($field === 'extension_date' && $diff !== 0)
{{ trans('email.bill_warning_extension_date', ['name' => $bill->name, 'date' => $bill->end_date->isoFormat(trans('config.month_and_day_js')), 'diff' => $diff]) }}
@endif
@if($field === 'end_date' && $diff === 0)
{{ trans('email.bill_warning_end_date_zero', ['name' => $bill->name, 'date' => $bill->end_date->isoFormat(trans('config.month_and_day_js')) ]) }}
@endif
@if($field === 'extension_date' && $diff === 0)
{{ trans('email.bill_warning_extension_date_zero', ['name' => $bill->name, 'date' => $bill->end_date->isoFormat(trans('config.month_and_day_js')) ]) }}
@endif
{{ trans('email.bill_warning_please_action') }}
@endcomponent

View File

@ -1,18 +0,0 @@
{% include 'emails.header-html' %}
<p style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;font-size:13px;">
{{ trans('email.email_change_body_to_new')}}
</p>
<p style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;font-size:13px;">
{{trans('email.email_change_old', { email: oldEmail }) }}
</p>
<p style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;font-size:13px;">
{{trans('email.email_change_new_strong', { email: newEmail })|raw }}
</p>
<p style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;font-size:13px;">
{{ trans('email.email_change_instructions')}}
</p>
<p style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;font-size:13px;">
<a href="{{ uri }}">{{ uri }}</a>
</p>
{% include 'emails.footer-html' %}

View File

@ -1,10 +0,0 @@
{% include 'emails.header-text' %}
{{ trans('email.email_change_body_to_new')|raw }}
{{trans('email.email_change_old', { email: oldEmail })|raw }}
{{trans('email.email_change_new', { email: newEmail })|raw }}
{{ trans('email.email_change_instructions')|raw }}
{{ uri }}
{% include 'emails.footer-text' %}

View File

@ -0,0 +1,11 @@
@component('mail::message')
{{ trans('email.email_change_body_to_new') }}
{{trans('email.email_change_old', ['email' => $oldEmail]) }}
{{trans('email.email_change_new', ['email' => $newEmail]) }}
{{ trans('email.email_change_instructions') }}
{{ $url }}
@endcomponent

View File

@ -1,16 +0,0 @@
{% include 'emails.header-html' %}
<p style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;font-size:13px;">
{{ trans('email.new_ip_body') }}
</p>
<p style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;font-size:13px;">
{{ trans('email.ip_address') }}: <strong>{{ ipAddress }}</strong><br />
{% if ''!= host %}{{ trans('email.host_name') }}: {{ host }}<br />{% endif %}
{{ trans('email.date_time') }}: {{ time }}<br />
</p>
<p style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;font-size:13px;">
{{ trans('email.new_ip_warning') }}
</p>
{% include 'emails.footer-html' %}

View File

@ -1,10 +0,0 @@
{% include 'emails.header-text' %}
{{ trans('email.new_ip_body') }}
{{ trans('email.ip_address') }}: {{ ipAddress }}
{% if ''!= host %}{{ trans('email.host_name') }}: {{ host }}{% endif %}
{{ trans('email.date_time') }}: {{ time }}
{{ trans('email.new_ip_warning') }}
{% include 'emails.footer-text' %}

View File

@ -0,0 +1,13 @@
@component('mail::message')
{{ trans('email.new_ip_body') }}
{{ trans('email.ip_address') }}: {{ $ipAddress }}
@if('' !== $host)
{{ trans('email.host_name') }}: {{ $host }}
@endif
{{ trans('email.date_time') }}: {{ $time }}
{{ trans('email.new_ip_warning') }}
@endcomponent

View File

@ -1,13 +0,0 @@
{% include 'emails.header-html' %}
<p style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;font-size:13px;">
{{ trans('email.oauth_created_body', { name:client.name, url: client.redirect })|raw }}
</p>
<p style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;font-size:13px;">
{{ trans('email.oauth_created_explanation')|raw }}
</p>
<p style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;font-size:13px;">
{{ trans('email.oauth_created_undo', { url:route('profile.index')}) }}
</p>
{% include 'emails.footer-html' %}

View File

@ -1,7 +0,0 @@
{% include 'emails.header-text' %}
{{ trans('email.oauth_created_body', {name: client.name, url: client.redirect })|striptags|raw }}
{{ trans('email.oauth_created_explanation')|striptags|raw }}
{{ trans('email.oauth_created_undo', { url:route('profile.index')})|raw }}
{% include 'emails.footer-text' %}

View File

@ -0,0 +1,8 @@
@component('mail::message')
{{ trans('email.oauth_created_body', ['name' => $client->name, 'url' => $client->redirect]) }}
{{ trans('email.oauth_created_explanation') }}
{{ trans('email.oauth_created_undo', ['url' => route('profile.index')] ) }}
@endcomponent

View File

@ -1,13 +0,0 @@
{% include 'emails.header-html' %}
<p style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;font-size:13px;">
{{ trans('email.reset_pw_instructions') }}
</p>
<p style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;font-size:13px;">
{{ trans('email.reset_pw_warning')|raw }}
</p>
<p style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;font-size:13px;">
<a href="{{ url }}">{{ url }}</a>
</p>
{% include 'emails.footer-html' %}

View File

@ -1,7 +0,0 @@
{% include 'emails.header-text' %}
{{ trans('email.reset_pw_instructions')|raw }}
{{ trans('email.reset_pw_warning')|striptags|raw }}
{{ url }}
{% include 'emails.footer-text' %}

View File

@ -0,0 +1,8 @@
@component('mail::message')
{{ trans('email.reset_pw_instructions') }}
{{ trans('email.reset_pw_warning') }}
{{ $url }}
@endcomponent

View File

@ -1,20 +0,0 @@
{% include 'emails.header-html' %}
<p style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;font-size:13px;">
{{ trans('email.registered_welcome', {address: address})|raw }}
</p>
<ul>
<li style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;font-size:13px;">
{{ trans('email.registered_pw', {address: address})|raw }}
</li>
<li style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;font-size:13px;">
{{ trans('email.registered_help')}}
</li>
<li style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;font-size:13px;">
{{ trans('email.registered_doc_html')|raw }}
</li>
</ul>
<p style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;font-size:13px;">
{{ trans('email.registered_closing')}}
</p>
{% include 'emails.footer-html' %}

View File

@ -1,21 +0,0 @@
{% include 'emails.header-text' %}
{{ trans('email.registered_welcome')|striptags|raw }}
* {{ trans('email.registered_pw')|striptags|raw }}
* {{ trans('email.registered_help')|raw }}
* {{ trans('email.registered_doc_text')|raw }}
{{ trans('email.registered_closing')|raw }}
{{ trans('email.registered_firefly_iii_link')|raw }}
{{ address }}
{{ trans('email.registered_pw_reset_link')|raw }}
{{ address }}/password/reset
{{ trans('email.registered_doc_link')}}
https://github.com/firefly-iii/firefly-iii
https://firefly-iii.org/
{% include 'emails.footer-text' %}

View File

@ -0,0 +1,14 @@
@component('mail::message')
{{ trans('email.registered_welcome') }}
* {{ trans('email.registered_pw', ['address' => $address]) }}
* {{ trans('email.registered_help') }}
* {{ trans('email.registered_doc_text') }}
{{ trans('email.registered_closing') }}
* {{ trans('email.registered_firefly_iii_link')}} [{{$address }}]({{$address }})
* {{ trans('email.registered_pw_reset_link')}} [{{ $address }}/password/reset]({{ $address }}/password/reset)
* {{ trans('email.registered_doc_link')}} [https://docs.firefly-iii.org/](https://docs.firefly-iii.org/)
@endcomponent

View File

@ -1,78 +0,0 @@
{% include 'emails.header-html' %}
<p style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;font-size:13px;">
{{ trans_choice('email.new_journals_header', transformed|length ) }}
</p>
<!-- loop groups -->
<ol>
{% for group in transformed %}
<li>
{% set count = group.transactions|length %}
<!-- if journals === 1, skip straight to journals. -->
{% if 1 == count %}
{% set journal = group.transactions[0] %}
<a href="{{ route('transactions.show', [group.id]) }}">{{ journal.description }}</a>,
<!-- amount -->
{% if journal.type == 'deposit' %}
<span style="color:#3c763d;">
{{ formatAmountBySymbol((journal.amount*-1)|floatval, journal.currency_symbol, journal.currency_decimal_places, false) }}
{% if null != journal.foreign_amount*-1 %}
({{ formatAmountBySymbol(journal.foreign_amount|floatval, journal.foreign_currency_symbol, journal.foreign_currency_decimal_places, false) }})
{% endif %}
</span>
{% elseif journal.type == 'transfer' %}
<span style="color:#31708f">
{{ formatAmountBySymbol((journal.amount*-1)|floatval, journal.currency_symbol, journal.currency_decimal_places, false) }}
{% if null != journal.foreign_amount %}
({{ formatAmountBySymbol((journal.foreign_amount*-1)|floatval, journal.foreign_currency_symbol, journal.foreign_currency_decimal_places, false) }})
{% endif %}
</span>
{% else %}
<span style="color:#a94442">
{{ formatAmountBySymbol((journal.amount*-1)|floatval, journal.currency_symbol, journal.currency_decimal_places, false) }}
{% if null != journal.foreign_amount %}
({{ formatAmountBySymbol((journal.foreign_amount*-1)|floatval, journal.foreign_currency_symbol, journal.foreign_currency_decimal_places, false) }})
{% endif %}
</span>
{% endif %}
<!-- / amount -->
{% else %}
<a href="{{ route('transactions.show', [group.id]) }}">{{ group.group_title }}</a>
<ol>
{% for journal in group.transactions %}
<li>
{{ journal.description }},
<!-- amount -->
{% if journal.type == 'deposit' %}
<span style="color:#3c763d;">
{{ formatAmountBySymbol((journal.amount*-1)|floatval, journal.currency_symbol, journal.currency_decimal_places, false) }}
{% if null != journal.foreign_amount*-1 %}
({{ formatAmountBySymbol(journal.foreign_amount|floatval, journal.foreign_currency_symbol, journal.foreign_currency_decimal_places, false) }})
{% endif %}
</span>
{% elseif journal.type == 'transfer' %}
<span style="color:#31708f">
{{ formatAmountBySymbol((journal.amount*-1)|floatval, journal.currency_symbol, journal.currency_decimal_places, false) }}
{% if null != journal.foreign_amount %}
({{ formatAmountBySymbol((journal.foreign_amount*-1)|floatval, journal.foreign_currency_symbol, journal.foreign_currency_decimal_places, false) }})
{% endif %}
</span>
{% else %}
<span style="color:#a94442">
{{ formatAmountBySymbol((journal.amount*-1)|floatval, journal.currency_symbol, journal.currency_decimal_places, false) }}
{% if null != journal.foreign_amount %}
({{ formatAmountBySymbol((journal.foreign_amount*-1)|floatval, journal.foreign_currency_symbol, journal.foreign_currency_decimal_places, false) }})
{% endif %}
</span>
{% endif %}
</li>
{% endfor %}
</ol>
{% endif %}
</li>
{% endfor %}
</ol>
{% include 'emails.footer-html' %}

View File

@ -1,16 +0,0 @@
{% include 'emails.header-text' %}
{{ trans_choice('email.new_journals_header', transformed|length )|raw }}
{% for group in transformed %}
{% set count = group.transactions|length %}
{% if 1 == count %}{% set journal = group.transactions[0] %}
- {{ journal.description }}, {% if journal.type == 'deposit' %}{{ formatAmountBySymbol((journal.amount*-1)|floatval, journal.currency_symbol, journal.currency_decimal_places, false) }}{% if null != journal.foreign_amount*-1 %} ({{ formatAmountBySymbol(journal.foreign_amount|floatval, journal.foreign_currency_symbol, journal.foreign_currency_decimal_places, false) }}){% endif %}{% elseif journal.type == 'transfer' %}{{ formatAmountBySymbol((journal.amount*-1)|floatval, journal.currency_symbol, journal.currency_decimal_places, false) }}{% if null != journal.foreign_amount %} ({{ formatAmountBySymbol(journal.foreign_amount|floatval*-1, journal.foreign_currency_symbol, journal.foreign_currency_decimal_places, false) }}){% endif %}{% else %}{{ formatAmountBySymbol((journal.amount*-1)|floatval, journal.currency_symbol, journal.currency_decimal_places, false) }}{% if null != journal.foreign_amount %} ({{ formatAmountBySymbol(journal.foreign_amount|floatval*-1, journal.foreign_currency_symbol, journal.foreign_currency_decimal_places, false) }}){% endif %}{% endif %}
{% else %}- {{ group.group_title }}
{% for journal in group.transactions %}-- {{ journal.description }}, {% if journal.type == 'deposit' %}{{ formatAmountBySymbol((journal.amount*-1)|floatval, journal.currency_symbol, journal.currency_decimal_places, false) }}{% if null != journal.foreign_amount*-1 %} ({{ formatAmountBySymbol(journal.foreign_amount|floatval, journal.foreign_currency_symbol, journal.foreign_currency_decimal_places, false) }}){% endif %}{% elseif journal.type == 'transfer' %}{{ formatAmountBySymbol((journal.amount*-1)|floatval, journal.currency_symbol, journal.currency_decimal_places, false) }}{% if null != journal.foreign_amount %} ({{ formatAmountBySymbol(journal.foreign_amount|floatval*-1, journal.foreign_currency_symbol, journal.foreign_currency_decimal_places, false) }}){% endif %}{% else %}{{ formatAmountBySymbol((journal.amount*-1)|floatval, journal.currency_symbol, journal.currency_decimal_places, false) }}{% if null != journal.foreign_amount %} ({{ formatAmountBySymbol(journal.foreign_amount|floatval*-1, journal.foreign_currency_symbol, journal.foreign_currency_decimal_places, false) }}){% endif %}{% endif %}
{% endfor %}
{% endif %}
{% endfor %}
{% include 'emails.footer-text' %}

View File

@ -0,0 +1,17 @@
@component('mail::message')
{{ trans_choice('email.new_journals_header', count($transformed)) }}
@foreach($transformed as $group)
- [{{ $group['transactions'][0]['description'] }}]({{ route('transactions.show', [$group['id']]) }})
@if('withdrawal' === $group['transactions'][0]['type'])
{{ $group['transactions'][0]['currency_code']}} {{ round((float)bcmul($group['transactions'][0]['amount'], '-1'), $group['transactions'][0]['currency_decimal_places']) }}
@endif
@if('deposit' === $group['transactions'][0]['type'])
{{ $group['transactions'][0]['currency_code']}} {{ round((float)bcmul($group['transactions'][0]['amount'], '1'), $group['transactions'][0]['currency_decimal_places']) }}
@endif
@if('transfer' === $group['transactions'][0]['type'])
{{ $group['transactions'][0]['currency_code']}} {{ round((float)bcmul($group['transactions'][0]['amount'], '1'), $group['transactions'][0]['currency_decimal_places']) }}
@endif
@endforeach
@endcomponent

View File

@ -0,0 +1,7 @@
@component('mail::message')
{{ trans('email.access_token_created_body') }}
{{ trans('email.access_token_created_explanation') }}
{{ trans('email.access_token_created_revoke', ['url' => route('profile.index')]) }}
@endcomponent

View File

@ -1,17 +0,0 @@
{% include 'emails.header-html' %}
<p style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;font-size:13px;">
{{ trans('email.email_change_body_to_old')|raw }}
</p>
<p style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;font-size:13px;">
{{ trans('email.email_change_ignore') }}
</p>
<p style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;font-size:13px;">
{{trans('email.email_change_old_strong', { email: oldEmail })|raw }}
</p>
<p style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;font-size:13px;">
{{trans('email.email_change_new', { email: newEmail }) }}
</p>
<p style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;font-size:13px;">
{{trans('email.email_change_undo_link')}} <a href="{{ uri }}">{{ uri }}</a>
</p>
{% include 'emails.footer-html' %}

View File

@ -1,11 +0,0 @@
{% include 'emails.header-text' %}
{{ trans('email.email_change_body_to_old')|striptags|raw }}
{{ trans('email.email_change_ignore')|raw }}
{{trans('email.email_change_old', { email: oldEmail })|raw }}
{{trans('email.email_change_new', { email: newEmail })|raw }}
{{ trans('email.email_change_undo_link')|raw }} {{ uri }}
{% include 'emails.footer-text' %}

View File

@ -0,0 +1,11 @@
@component('mail::message')
{{ trans('email.email_change_body_to_old') }}
{{ trans('email.email_change_ignore')}}
{{trans('email.email_change_old', ['email' => $oldEmail]) }}
{{trans('email.email_change_new', ['email' => $newEmail]) }}
{{ trans('email.email_change_undo_link') }} {{ $url }}
@endcomponent

View File

@ -0,0 +1,19 @@
<table class="action" align="center" width="100%" cellpadding="0" cellspacing="0" role="presentation">
<tr>
<td align="center">
<table width="100%" border="0" cellpadding="0" cellspacing="0" role="presentation">
<tr>
<td align="center">
<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>
</td>
</tr>
</table>
</td>
</tr>
</table>
</td>
</tr>
</table>

View File

@ -0,0 +1,11 @@
<tr>
<td>
<table class="footer" align="center" width="570" cellpadding="0" cellspacing="0" role="presentation">
<tr>
<td class="content-cell" align="center">
{{ Illuminate\Mail\Markdown::parse($slot) }}
</td>
</tr>
</table>
</td>
</tr>

View File

@ -0,0 +1,7 @@
<tr>
<td class="header">
<a href="#" style="display: inline-block;">
Firefly III
</a>
</td>
</tr>

View File

@ -0,0 +1,56 @@
<!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>
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<meta name="color-scheme" content="light">
<meta name="supported-color-schemes" content="light">
<style>
@media only screen and (max-width: 600px) {
.inner-body {
width: 100% !important;
}
.footer {
width: 100% !important;
}
}
@media only screen and (max-width: 500px) {
.button {
width: 100% !important;
}
}
</style>
</head>
<body>
<table class="wrapper" width="100%" cellpadding="0" cellspacing="0" role="presentation">
<tr>
<td align="center">
<table class="content" width="100%" cellpadding="0" cellspacing="0" role="presentation">
{{ $header ?? '' }}
<!-- Email Body -->
<tr>
<td class="body" width="100%" cellpadding="0" cellspacing="0">
<table class="inner-body" align="center" width="570" cellpadding="0" cellspacing="0" role="presentation">
<!-- Body content -->
<tr>
<td class="content-cell">
{{ Illuminate\Mail\Markdown::parse($slot) }}
{{ $subcopy ?? '' }}
</td>
</tr>
</table>
</td>
</tr>
{{ $footer ?? '' }}
</table>
</td>
</tr>
</table>
</body>
</html>

View File

@ -0,0 +1,33 @@
@component('mail::layout')
{{-- Header --}}
@slot('header')
@component('mail::header', ['url' => config('app.url')])
{{ config('app.name') }}
@endcomponent
@endslot
{{-- Body --}}
{{ trans('email.greeting') }}
{{ $slot }}
{{ trans('email.closing') }}
{{ trans('email.signature')}}
{{-- Subcopy --}}
@isset($subcopy)
@slot('subcopy')
@component('mail::subcopy')
{{ $subcopy }}
@endcomponent
@endslot
@endisset
{{-- Footer --}}
@slot('footer')
@component('mail::footer')
{{ trans('email.footer_ps', ['ipAddress' => request()?->ip() ?? '']) }}
@endcomponent
@endslot
@endcomponent

View File

@ -0,0 +1,14 @@
<table class="panel" width="100%" cellpadding="0" cellspacing="0" role="presentation">
<tr>
<td class="panel-content">
<table width="100%" cellpadding="0" cellspacing="0" role="presentation">
<tr>
<td class="panel-item">
{{ Illuminate\Mail\Markdown::parse($slot) }}
</td>
</tr>
</table>
</td>
</tr>
</table>

View File

@ -0,0 +1,7 @@
<table class="subcopy" width="100%" cellpadding="0" cellspacing="0" role="presentation">
<tr>
<td>
{{ Illuminate\Mail\Markdown::parse($slot) }}
</td>
</tr>
</table>

View File

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

View File

@ -0,0 +1,290 @@
/* Base */
body,
body *:not(html):not(style):not(br):not(tr):not(code) {
box-sizing: border-box;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif,
'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol';
position: relative;
}
body {
-webkit-text-size-adjust: none;
background-color: #ffffff;
color: #718096;
height: 100%;
line-height: 1.4;
margin: 0;
padding: 0;
width: 100% !important;
}
p,
ul,
ol,
blockquote {
line-height: 1.4;
text-align: left;
}
a {
color: #3869d4;
}
a img {
border: none;
}
/* Typography */
h1 {
color: #3d4852;
font-size: 18px;
font-weight: bold;
margin-top: 0;
text-align: left;
}
h2 {
font-size: 16px;
font-weight: bold;
margin-top: 0;
text-align: left;
}
h3 {
font-size: 14px;
font-weight: bold;
margin-top: 0;
text-align: left;
}
p {
font-size: 16px;
line-height: 1.5em;
margin-top: 0;
text-align: left;
}
p.sub {
font-size: 12px;
}
img {
max-width: 100%;
}
/* Layout */
.wrapper {
-premailer-cellpadding: 0;
-premailer-cellspacing: 0;
-premailer-width: 100%;
background-color: #edf2f7;
margin: 0;
padding: 0;
width: 100%;
}
.content {
-premailer-cellpadding: 0;
-premailer-cellspacing: 0;
-premailer-width: 100%;
margin: 0;
padding: 0;
width: 100%;
}
/* Header */
.header {
padding: 25px 0;
text-align: center;
}
.header a {
color: #3d4852;
font-size: 19px;
font-weight: bold;
text-decoration: none;
}
/* Logo */
.logo {
height: 75px;
max-height: 75px;
width: 75px;
}
/* Body */
.body {
-premailer-cellpadding: 0;
-premailer-cellspacing: 0;
-premailer-width: 100%;
background-color: #edf2f7;
border-bottom: 1px solid #edf2f7;
border-top: 1px solid #edf2f7;
margin: 0;
padding: 0;
width: 100%;
}
.inner-body {
-premailer-cellpadding: 0;
-premailer-cellspacing: 0;
-premailer-width: 570px;
background-color: #ffffff;
border-color: #e8e5ef;
border-radius: 2px;
border-width: 1px;
box-shadow: 0 2px 0 rgba(0, 0, 150, 0.025), 2px 4px 0 rgba(0, 0, 150, 0.015);
margin: 0 auto;
padding: 0;
width: 570px;
}
/* Subcopy */
.subcopy {
border-top: 1px solid #e8e5ef;
margin-top: 25px;
padding-top: 25px;
}
.subcopy p {
font-size: 14px;
}
/* Footer */
.footer {
-premailer-cellpadding: 0;
-premailer-cellspacing: 0;
-premailer-width: 570px;
margin: 0 auto;
padding: 0;
text-align: center;
width: 570px;
}
.footer p {
color: #b0adc5;
font-size: 12px;
text-align: center;
}
.footer a {
color: #b0adc5;
text-decoration: underline;
}
/* Tables */
.table table {
-premailer-cellpadding: 0;
-premailer-cellspacing: 0;
-premailer-width: 100%;
margin: 30px auto;
width: 100%;
}
.table th {
border-bottom: 1px solid #edeff2;
margin: 0;
padding-bottom: 8px;
}
.table td {
color: #74787e;
font-size: 15px;
line-height: 18px;
margin: 0;
padding: 10px 0;
}
.content-cell {
max-width: 100vw;
padding: 32px;
}
/* Buttons */
.action {
-premailer-cellpadding: 0;
-premailer-cellspacing: 0;
-premailer-width: 100%;
margin: 30px auto;
padding: 0;
text-align: center;
width: 100%;
}
.button {
-webkit-text-size-adjust: none;
border-radius: 4px;
color: #fff;
display: inline-block;
overflow: hidden;
text-decoration: none;
}
.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;
}
.button-green,
.button-success {
background-color: #48bb78;
border-bottom: 8px solid #48bb78;
border-left: 18px solid #48bb78;
border-right: 18px solid #48bb78;
border-top: 8px solid #48bb78;
}
.button-red,
.button-error {
background-color: #e53e3e;
border-bottom: 8px solid #e53e3e;
border-left: 18px solid #e53e3e;
border-right: 18px solid #e53e3e;
border-top: 8px solid #e53e3e;
}
/* Panels */
.panel {
border-left: #2d3748 solid 4px;
margin: 21px 0;
}
.panel-content {
background-color: #edf2f7;
color: #718096;
padding: 16px;
}
.panel-content p {
color: #718096;
}
.panel-item {
padding: 0;
}
.panel-item p:last-of-type {
margin-bottom: 0;
padding-bottom: 0;
}
/* Utilities */
.break-all {
word-break: break-all;
}

View File

@ -0,0 +1 @@
{{ $slot }}: {{ $url }}

View File

@ -0,0 +1 @@
{{ $slot }}

View File

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

View File

@ -0,0 +1,9 @@
{!! strip_tags($header) !!}
{!! strip_tags($slot) !!}
@isset($subcopy)
{!! strip_tags($subcopy) !!}
@endisset
{!! strip_tags($footer) !!}

View File

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

View File

@ -0,0 +1 @@
{{ $slot }}

View File

@ -0,0 +1 @@
{{ $slot }}

View File

@ -0,0 +1 @@
{{ $slot }}