diff --git a/src/app/Console/Development/TemplateRender.php b/src/app/Console/Development/TemplateRender.php
index 2e9f5856..2f9c68bb 100644
--- a/src/app/Console/Development/TemplateRender.php
+++ b/src/app/Console/Development/TemplateRender.php
@@ -1,59 +1,61 @@
argument('template');
$template = str_replace("/", "\\", $template);
$class = "\\App\\{$template}";
// Invalid template, list all templates
if (!class_exists($class)) {
$this->info("Invalid template name. Available templates:");
foreach (glob(app_path() . '/Documents/*.php') as $file) {
$file = basename($file, '.php');
$this->info("Documents/$file");
}
foreach (glob(app_path() . '/Mail/*.php') as $file) {
$file = basename($file, '.php');
$this->info("Mail/$file");
}
return 1;
}
$mode = 'html';
if (!empty($this->option('pdf'))) {
$mode = 'pdf';
+ } elseif (!empty($this->option('text'))) {
+ $mode = 'text';
}
echo $class::fakeRender($mode);
}
}
diff --git a/src/app/Documents/Receipt.php b/src/app/Documents/Receipt.php
index 4fc11e4d..b00504a8 100644
--- a/src/app/Documents/Receipt.php
+++ b/src/app/Documents/Receipt.php
@@ -1,241 +1,245 @@
wallet = $wallet;
$this->year = $year;
$this->month = $month;
}
/**
* Render the mail template with fake data
*
+ * @param string $type Output format ('html' or 'pdf')
+ *
* @return string HTML or PDF output
*/
public static function fakeRender(string $type = 'html'): string
{
$wallet = new Wallet();
$wallet->id = \App\Utils::uuidStr();
$wallet->owner = new User(['id' => 123456789]); // @phpstan-ignore-line
$receipt = new self($wallet, date('Y'), date('n'));
self::$fakeMode = true;
if ($type == 'pdf') {
return $receipt->pdfOutput();
+ } elseif ($type !== 'html') {
+ throw new \Exception("Unsupported output format");
}
return $receipt->htmlOutput();
}
/**
* Render the receipt in HTML format.
*
* @return string HTML content
*/
public function htmlOutput(): string
{
return $this->build()->render();
}
/**
* Render the receipt in PDF format.
*
* @return string PDF content
*/
public function pdfOutput(): string
{
// Parse ther HTML template
$html = $this->build()->render();
// Link fonts from public/fonts to storage/fonts so DomPdf can find them
if (!is_link(storage_path('fonts/Roboto-Regular.ttf'))) {
symlink(
public_path('fonts/Roboto-Regular.ttf'),
storage_path('fonts/Roboto-Regular.ttf')
);
symlink(
public_path('fonts/Roboto-Bold.ttf'),
storage_path('fonts/Roboto-Bold.ttf')
);
}
// Fix font and image paths
$html = str_replace('url(/fonts/', 'url(fonts/', $html);
$html = str_replace('src="/images/', 'src="images/', $html);
// TODO: The output file is about ~200KB, we could probably slim it down
// by using separate font files with small subset of languages when
// there are no Unicode characters used, e.g. only ASCII or Latin.
// Load PDF generator
$pdf = \PDF::loadHTML($html)->setPaper('a4', 'portrait');
return $pdf->output();
}
/**
* Build the document
*
* @return \Illuminate\View\View The template object
*/
protected function build()
{
$appName = \config('app.name');
$start = Carbon::create($this->year, $this->month, 1, 0, 0, 0);
$end = $start->copy()->endOfMonth();
$month = \trans('documents.month' . intval($this->month));
$title = \trans('documents.receipt-title', ['year' => $this->year, 'month' => $month]);
$company = $this->companyData();
if (self::$fakeMode) {
$customer = [
'id' => $this->wallet->owner->id,
'wallet_id' => $this->wallet->id,
'customer' => 'Freddie Krüger
7252 Westminster Lane
Forest Hills, NY 11375',
];
$items = collect([
(object) [
'amount' => 1234,
'updated_at' => $start->copy()->next(Carbon::MONDAY),
],
(object) [
'amount' => 10000,
// @phpstan-ignore-next-line
'updated_at' => $start->copy()->next()->next(),
],
(object) [
'amount' => 1234,
// @phpstan-ignore-next-line
'updated_at' => $start->copy()->next()->next()->next(Carbon::MONDAY),
],
(object) [
'amount' => 99,
// @phpstan-ignore-next-line
'updated_at' => $start->copy()->next()->next()->next(),
],
]);
} else {
$customer = $this->customerData();
$items = $this->wallet->payments()
->where('status', PaymentProvider::STATUS_PAID)
->where('updated_at', '>=', $start)
->where('updated_at', '<', $end)
->where('amount', '>', 0)
->orderBy('updated_at')
->get();
}
$total = 0;
$items = $items->map(function ($item) use (&$total, $appName) {
$total += $item->amount;
return [
'amount' => sprintf('%.2f %s', $item->amount / 100, $this->wallet->currency),
'description' => \trans('documents.receipt-item-desc', ['site' => $appName]),
'date' => $item->updated_at->toDateString(),
];
});
$total = sprintf('%.2f %s', $total / 100, $this->wallet->currency);
// Load the template
$view = view('documents.receipt')
->with([
'site' => $appName,
'title' => $title,
'company' => $company,
'customer' => $customer,
'items' => $items,
'total' => $total,
]);
return $view;
}
/**
* Prepare customer data for the template
*
* @return array Customer data for the template
*/
protected function customerData(): array
{
$user = $this->wallet->owner;
$name = $user->name();
$organization = $user->getSetting('organization');
$address = $user->getSetting('billing_address');
$customer = trim(($organization ?: $name) . "\n$address");
$customer = str_replace("\n", '
', htmlentities($customer));
return [
'id' => $this->wallet->owner->id,
'wallet_id' => $this->wallet->id,
'customer' => $customer,
];
}
/**
* Prepare company data for the template
*
* @return array Company data for the template
*/
protected function companyData(): array
{
$header = \config('app.company.name') . "\n" . \config('app.company.address');
$header = str_replace("\n", '
', htmlentities($header));
$footerLineLength = 110;
$footer = \config('app.company.details');
$contact = \config('app.company.email');
$logo = \config('app.company.logo');
if ($contact) {
$length = strlen($footer) + strlen($contact) + 3;
$contact = htmlentities($contact);
$footer .= ($length > $footerLineLength ? "\n" : ' | ')
. sprintf('%s', $contact, $contact);
}
return [
'logo' => $logo ? "" : '',
'header' => $header,
'footer' => $footer,
];
}
}
diff --git a/src/app/Mail/Helper.php b/src/app/Mail/Helper.php
new file mode 100644
index 00000000..756b6b8b
--- /dev/null
+++ b/src/app/Mail/Helper.php
@@ -0,0 +1,33 @@
+build(); // @phpstan-ignore-line
+
+ $mailer = \Illuminate\Container\Container::getInstance()->make('mailer');
+
+ return $mailer->render(['text' => $mail->textView], $mail->buildViewData());
+ } elseif ($type != 'html') {
+ throw new \Exception("Unsupported output format");
+ }
+
+ // HTML output
+ return $mail->build()->render(); // @phpstan-ignore-line
+ }
+}
diff --git a/src/app/Mail/NegativeBalance.php b/src/app/Mail/NegativeBalance.php
index 54ff3371..dfac7f47 100644
--- a/src/app/Mail/NegativeBalance.php
+++ b/src/app/Mail/NegativeBalance.php
@@ -1,69 +1,72 @@
account = $account;
}
/**
* Build the message.
*
* @return $this
*/
public function build()
{
$user = $this->account;
$subject = \trans('mail.negativebalance-subject', ['site' => \config('app.name')]);
- $this->view('emails.negative_balance')
+ $this->view('emails.html.negative_balance')
+ ->text('emails.plain.negative_balance')
->subject($subject)
->with([
'site' => \config('app.name'),
'subject' => $subject,
'username' => $user->name(true),
'supportUrl' => \config('app.support_url'),
'walletUrl' => Utils::serviceUrl('/wallet'),
]);
return $this;
}
/**
* Render the mail template with fake data
*
- * @return string HTML output
+ * @param string $type Output format ('html' or 'text')
+ *
+ * @return string HTML or Plain Text output
*/
- public static function fakeRender(): string
+ public static function fakeRender(string $type = 'html'): string
{
$user = new User();
$mail = new self($user);
- return $mail->build()->render();
+ return Helper::render($mail, $type);
}
}
diff --git a/src/app/Mail/PasswordReset.php b/src/app/Mail/PasswordReset.php
index 24549869..4544a192 100644
--- a/src/app/Mail/PasswordReset.php
+++ b/src/app/Mail/PasswordReset.php
@@ -1,78 +1,81 @@
code = $code;
}
/**
* Build the message.
*
* @return $this
*/
public function build()
{
$href = Utils::serviceUrl(
sprintf('/login/reset/%s-%s', $this->code->short_code, $this->code->code)
);
- $this->view('emails.password_reset')
+ $this->view('emails.html.password_reset')
+ ->text('emails.plain.password_reset')
->subject(__('mail.passwordreset-subject', ['site' => \config('app.name')]))
->with([
'site' => \config('app.name'),
'code' => $this->code->code,
'short_code' => $this->code->short_code,
'link' => sprintf('%s', $href, $href),
'username' => $this->code->user->name(true)
]);
return $this;
}
/**
* Render the mail template with fake data
*
- * @return string HTML output
+ * @param string $type Output format ('html' or 'text')
+ *
+ * @return string HTML or Plain Text output
*/
- public static function fakeRender(): string
+ public static function fakeRender(string $type = 'html'): string
{
$code = new VerificationCode([
'code' => Str::random(VerificationCode::CODE_LENGTH),
'short_code' => VerificationCode::generateShortCode(),
]);
$code->user = new User([
'email' => 'test@' . \config('app.domain'),
]);
$mail = new self($code);
- return $mail->build()->render();
+ return Helper::render($mail, $type);
}
}
diff --git a/src/app/Mail/PaymentFailure.php b/src/app/Mail/PaymentFailure.php
index 56f36d4c..9bb8e700 100644
--- a/src/app/Mail/PaymentFailure.php
+++ b/src/app/Mail/PaymentFailure.php
@@ -1,82 +1,81 @@
payment = $payment;
$this->user = $user;
}
/**
* Build the message.
*
* @return $this
*/
public function build()
{
$user = $this->user;
$subject = \trans('mail.paymentfailure-subject', ['site' => \config('app.name')]);
- $this->view('emails.payment_failure')
+ $this->view('emails.html.payment_failure')
+ ->text('emails.plain.payment_failure')
->subject($subject)
->with([
'site' => \config('app.name'),
'subject' => $subject,
'username' => $user->name(true),
'walletUrl' => Utils::serviceUrl('/wallet'),
'supportUrl' => \config('app.support_url'),
]);
return $this;
}
/**
* Render the mail template with fake data
*
- * @return string HTML output
+ * @param string $type Output format ('html' or 'text')
+ *
+ * @return string HTML or Plain Text output
*/
- public static function fakeRender(): string
+ public static function fakeRender(string $type = 'mail'): string
{
$payment = new Payment();
$user = new User([
'email' => 'test@' . \config('app.domain'),
]);
- if (!\config('app.support_url')) {
- \config(['app.support_url' => 'https://not-configured-support.url']);
- }
-
$mail = new self($payment, $user);
- return $mail->build()->render();
+ return Helper::render($mail, $type);
}
}
diff --git a/src/app/Mail/PaymentMandateDisabled.php b/src/app/Mail/PaymentMandateDisabled.php
index 78014170..a5e5fccc 100644
--- a/src/app/Mail/PaymentMandateDisabled.php
+++ b/src/app/Mail/PaymentMandateDisabled.php
@@ -1,82 +1,81 @@
wallet = $wallet;
$this->user = $user;
}
/**
* Build the message.
*
* @return $this
*/
public function build()
{
$user = $this->user;
$subject = \trans('mail.paymentmandatedisabled-subject', ['site' => \config('app.name')]);
- $this->view('emails.payment_mandate_disabled')
+ $this->view('emails.html.payment_mandate_disabled')
+ ->text('emails.plain.payment_mandate_disabled')
->subject($subject)
->with([
'site' => \config('app.name'),
'subject' => $subject,
'username' => $user->name(true),
'walletUrl' => Utils::serviceUrl('/wallet'),
'supportUrl' => \config('app.support_url'),
]);
return $this;
}
/**
* Render the mail template with fake data
*
- * @return string HTML output
+ * @param string $type Output format ('html' or 'text')
+ *
+ * @return string HTML or Plain Text output
*/
- public static function fakeRender(): string
+ public static function fakeRender(string $type = 'html'): string
{
$wallet = new Wallet();
$user = new User([
'email' => 'test@' . \config('app.domain'),
]);
- if (!\config('app.support_url')) {
- \config(['app.support_url' => 'https://not-configured-support.url']);
- }
-
$mail = new self($wallet, $user);
- return $mail->build()->render();
+ return Helper::render($mail, $type);
}
}
diff --git a/src/app/Mail/PaymentSuccess.php b/src/app/Mail/PaymentSuccess.php
index 2ba3a661..c211e73c 100644
--- a/src/app/Mail/PaymentSuccess.php
+++ b/src/app/Mail/PaymentSuccess.php
@@ -1,82 +1,81 @@
payment = $payment;
$this->user = $user;
}
/**
* Build the message.
*
* @return $this
*/
public function build()
{
$user = $this->user;
$subject = \trans('mail.paymentsuccess-subject', ['site' => \config('app.name')]);
- $this->view('emails.payment_success')
+ $this->view('emails.html.payment_success')
+ ->text('emails.plain.payment_success')
->subject($subject)
->with([
'site' => \config('app.name'),
'subject' => $subject,
'username' => $user->name(true),
'walletUrl' => Utils::serviceUrl('/wallet'),
'supportUrl' => \config('app.support_url'),
]);
return $this;
}
/**
* Render the mail template with fake data
*
- * @return string HTML output
+ * @param string $type Output format ('html' or 'text')
+ *
+ * @return string HTML or Plain Text output
*/
- public static function fakeRender(): string
+ public static function fakeRender(string $type = 'html'): string
{
$payment = new Payment();
$user = new User([
'email' => 'test@' . \config('app.domain'),
]);
- if (!\config('app.support_url')) {
- \config(['app.support_url' => 'https://not-configured-support.url']);
- }
-
$mail = new self($payment, $user);
- return $mail->build()->render();
+ return Helper::render($mail, $type);
}
}
diff --git a/src/app/Mail/SignupVerification.php b/src/app/Mail/SignupVerification.php
index 397c0f41..039263a1 100644
--- a/src/app/Mail/SignupVerification.php
+++ b/src/app/Mail/SignupVerification.php
@@ -1,85 +1,87 @@
code = $code;
}
/**
* Build the message.
*
* @return $this
*/
public function build()
{
$href = Utils::serviceUrl(
sprintf('/signup/%s-%s', $this->code->short_code, $this->code->code)
);
$username = $this->code->data['first_name'] ?? '';
if (!empty($this->code->data['last_name'])) {
$username .= ' ' . $this->code->data['last_name'];
}
$username = trim($username);
- $this->view('emails.signup_code')
+ $this->view('emails.html.signup_code')
+ ->text('emails.plain.signup_code')
->subject(__('mail.signupcode-subject', ['site' => \config('app.name')]))
->with([
'site' => \config('app.name'),
'username' => $username ?: 'User',
'code' => $this->code->code,
'short_code' => $this->code->short_code,
- 'link' => sprintf('%s', $href, $href),
+ 'href' => $href,
]);
return $this;
}
/**
* Render the mail template with fake data
*
- * @return string HTML output
+ * @param string $type Output format ('html' or 'text')
+ *
+ * @return string HTML or Plain Text output
*/
- public static function fakeRender(): string
+ public static function fakeRender(string $type = 'html'): string
{
$code = new SignupCode([
'code' => Str::random(SignupCode::CODE_LENGTH),
'short_code' => SignupCode::generateShortCode(),
'data' => [
'email' => 'test@' . \config('app.domain'),
'first_name' => 'Firstname',
'last_name' => 'Lastname',
],
]);
-
$mail = new self($code);
- return $mail->build()->render();
+ return Helper::render($mail, $type);
}
}
diff --git a/src/app/Mail/SuspendedDebtor.php b/src/app/Mail/SuspendedDebtor.php
index 45b268b5..4ffb1803 100644
--- a/src/app/Mail/SuspendedDebtor.php
+++ b/src/app/Mail/SuspendedDebtor.php
@@ -1,89 +1,83 @@
account = $account;
}
/**
* Build the message.
*
* @return $this
*/
public function build()
{
$user = $this->account;
$subject = \trans('mail.suspendeddebtor-subject', ['site' => \config('app.name')]);
- $moreInfo = null;
+ $moreInfoHtml = null;
+ $moreInfoText = null;
if ($moreInfoUrl = \config('app.kb.account_suspended')) {
- $moreInfo = \trans('mail.more-info-html', ['href' => $moreInfoUrl]);
+ $moreInfoHtml = \trans('mail.more-info-html', ['href' => $moreInfoUrl]);
+ $moreInfoText = \trans('mail.more-info-text', ['href' => $moreInfoUrl]);
}
- $this->view('emails.suspended_debtor')
+ $this->view('emails.html.suspended_debtor')
+ ->text('emails.plain.suspended_debtor')
->subject($subject)
->with([
'site' => \config('app.name'),
'subject' => $subject,
'username' => $user->name(true),
'cancelUrl' => \config('app.kb.account_delete'),
'supportUrl' => \config('app.support_url'),
'walletUrl' => Utils::serviceUrl('/wallet'),
- 'moreInfo' => $moreInfo,
+ 'moreInfoHtml' => $moreInfoHtml,
+ 'moreInfoText' => $moreInfoText,
'days' => 14 // TODO: Configurable
]);
return $this;
}
/**
* Render the mail template with fake data
*
- * @return string HTML output
+ * @param string $type Output format ('html' or 'text')
+ *
+ * @return string HTML or Plain Text output
*/
- public static function fakeRender(): string
+ public static function fakeRender(string $type = 'html'): string
{
$user = new User();
- if (!\config('app.support_url')) {
- \config(['app.support_url' => 'https://not-configured-support.url']);
- }
-
- if (!\config('app.kb.account_delete')) {
- \config(['app.kb.account_delete' => 'https://not-configured-kb.url']);
- }
-
- if (!\config('app.kb.account_suspended')) {
- \config(['app.kb.account_suspended' => 'https://not-configured-kb.url']);
- }
-
$mail = new self($user);
- return $mail->build()->render();
+ return Helper::render($mail, $type);
}
}
diff --git a/src/composer.json b/src/composer.json
index 6a50c33e..8bf0793e 100644
--- a/src/composer.json
+++ b/src/composer.json
@@ -1,87 +1,88 @@
{
"name": "laravel/laravel",
"type": "project",
"description": "The Laravel Framework.",
"keywords": [
"framework",
"laravel"
],
"license": "MIT",
"repositories": [
{
"type": "vcs",
"url": "https://git.kolab.org/diffusion/PNL/php-net_ldap3.git"
}
],
"require": {
"php": "^7.1.3",
"barryvdh/laravel-dompdf": "^0.8.6",
"doctrine/dbal": "^2.9",
"fideloper/proxy": "^4.0",
"geoip2/geoip2": "^2.9",
"iatstuti/laravel-nullable-fields": "*",
"kolab/net_ldap3": "dev-master",
"laravel/framework": "6.*",
- "laravel/tinker": "^1.0",
+ "laravel/tinker": "^2.4",
"mollie/laravel-mollie": "^2.9",
"morrislaptop/laravel-queue-clear": "^1.2",
"silviolleite/laravelpwa": "^1.0",
"spatie/laravel-translatable": "^4.2",
"spomky-labs/otphp": "~4.0.0",
"stripe/stripe-php": "^7.29",
"swooletw/laravel-swoole": "^2.6",
"torann/currency": "^1.0",
"torann/geoip": "^1.0",
"tymon/jwt-auth": "^1.0"
},
"require-dev": {
"beyondcode/laravel-dump-server": "^1.0",
"beyondcode/laravel-er-diagram-generator": "^1.3",
"filp/whoops": "^2.0",
"fzaninotto/faker": "^1.4",
+ "kirschbaum-development/mail-intercept": "^0.2.4",
"laravel/dusk": "~5.11.0",
"mockery/mockery": "^1.0",
"nunomaduro/larastan": "^0.5",
- "phpstan/phpstan": "^0.12",
+ "phpstan/phpstan": "0.12.25",
"phpunit/phpunit": "^8"
},
"config": {
"optimize-autoloader": true,
"preferred-install": "dist",
"sort-packages": true
},
"extra": {
"laravel": {
"dont-discover": []
}
},
"autoload": {
"psr-4": {
"App\\": "app/"
},
"classmap": [
"database/seeds",
"database/factories",
"include"
]
},
"autoload-dev": {
"psr-4": {
"Tests\\": "tests/"
}
},
"minimum-stability": "dev",
"prefer-stable": true,
"scripts": {
"post-autoload-dump": [
"Illuminate\\Foundation\\ComposerScripts::postAutoloadDump",
"@php artisan package:discover --ansi"
],
"post-root-package-install": [
"@php -r \"file_exists('.env') || copy('.env.example', '.env');\""
],
"post-create-project-cmd": [
"@php artisan key:generate --ansi"
]
}
}
diff --git a/src/resources/lang/en/mail.php b/src/resources/lang/en/mail.php
index df5a67d6..fc49baa9 100644
--- a/src/resources/lang/en/mail.php
+++ b/src/resources/lang/en/mail.php
@@ -1,63 +1,64 @@
"Dear :name,",
'footer' => "Best regards,\nYour :site Team",
'more-info-html' => "See here for more information.",
+ 'more-info-text' => "See :href for more information.",
'negativebalance-subject' => ":site Payment Reminder",
'negativebalance-body' => "It has probably skipped your attention that you are behind on paying for your :site account. "
- . "Consider setting up auto-payment to avoid messages like this in the future.\n\n"
- . "Settle up to keep your account running.",
+ . "Consider setting up auto-payment to avoid messages like this in the future.",
+ 'negativebalance-body-extd' => "Settle up to keep your account running.",
'passwordreset-subject' => ":site Password Reset",
'passwordreset-body' => "Someone recently asked to change your :site password.\n"
. "If this was you, use this verification code to complete the process: :code.\n"
. "You can also click the link below.\n"
. "If you did not make such a request, you can either ignore this message or get in touch with us about this incident.",
'paymentmandatedisabled-subject' => ":site Auto-payment Problem",
'paymentmandatedisabled-body' => "Your :site account balance is negative "
. "and the configured amount for automatically topping up the balance does not cover "
- . "the costs of subscriptions consumed.\n\n"
- . "Charging you multiple times for the same amount in short succession "
+ . "the costs of subscriptions consumed.",
+ 'paymentmandatedisabled-body-ext' => "Charging you multiple times for the same amount in short succession "
. "could lead to issues with the payment provider. "
. "In order to not cause any problems, we suspended auto-payment for your account. "
. "To resolve this issue, login to your account settings and adjust your auto-payment amount.",
'paymentfailure-subject' => ":site Payment Failed",
'paymentfailure-body' => "Something went wrong with auto-payment for your :site account.\n"
- . "We tried to charge you via your preferred payment method, but the charge did not go through.\n\n"
- . "In order to not cause any further issues, we suspended auto-payment for your account. "
+ . "We tried to charge you via your preferred payment method, but the charge did not go through.",
+ 'paymentfailure-body-ext' => "In order to not cause any further issues, we suspended auto-payment for your account. "
. "To resolve this issue, login to your account settings at",
'paymentfailure-body-rest' => "There you can pay manually for your account and "
. "change your auto-payment settings.",
'paymentsuccess-subject' => ":site Payment Succeeded",
'paymentsuccess-body' => "The auto-payment for your :site account went through without issues. "
. "You can check your new account balance and more details here:",
- 'support' => "Special circumstances? Something wrong with a charge?\n"
- . " :site Support is here to help:",
+ 'support' => "Special circumstances? Something is wrong with a charge?\n"
+ . ":site Support is here to help.",
'signupcode-subject' => ":site Registration",
'signupcode-body' => "This is your verification code for the :site registration process: :code.\n"
. "You can also click the link below to continue the registration process:",
'suspendeddebtor-subject' => ":site Account Suspended",
'suspendeddebtor-body' => "You have been behind on paying for your :site account "
."for over :days days. Your account has been suspended.",
'suspendeddebtor-middle' => "Settle up now to reactivate your account.",
'suspendeddebtor-cancel' => "Don't want to be our customer anymore? "
. "Here is how you can cancel your account:",
];
diff --git a/src/resources/views/documents/receipt.blade.php b/src/resources/views/documents/receipt.blade.php
index f920df64..bdded528 100644
--- a/src/resources/views/documents/receipt.blade.php
+++ b/src/resources/views/documents/receipt.blade.php
@@ -1,56 +1,56 @@
{!! $company['header'] !!} | {!! $company['logo'] !!} |
{!! $customer['customer'] !!} |
{{ __('documents.account-id') }} {{ $customer['wallet_id'] }} {{ __('documents.customer-no') }} {{ $customer['id'] }} |
{{ __('documents.date') }} | {{ __('documents.description') }} | {{ __('documents.amount') }} |
---|---|---|
{{ $item['date'] }} | {{ $item['description'] }} | {{ $item['amount'] }} |
{{ __('documents.total') }} | {{ $total }} |
{{ __('mail.header', ['name' => $username]) }}
{{ __('mail.negativebalance-body', ['site' => $site]) }}
+{{ __('mail.negativebalance-body-ext', ['site' => $site]) }}
@if ($supportUrl){{ __('mail.support', ['site' => $site]) }}
@endif -{{ __('mail.footer', ['site' => $site, 'appurl' => config('app.url')]) }}
+{{ __('mail.footer', ['site' => $site]) }}
diff --git a/src/resources/views/emails/password_reset.blade.php b/src/resources/views/emails/html/password_reset.blade.php similarity index 79% rename from src/resources/views/emails/password_reset.blade.php rename to src/resources/views/emails/html/password_reset.blade.php index 85751758..31ee02ae 100644 --- a/src/resources/views/emails/password_reset.blade.php +++ b/src/resources/views/emails/html/password_reset.blade.php @@ -1,15 +1,15 @@{{ __('mail.header', ['name' => $username]) }}
{{ __('mail.passwordreset-body', ['code' => $short_code, 'site' => $site]) }}
{!! $link !!}
-{{ __('mail.footer', ['site' => $site, 'appurl' => config('app.url')]) }}
+{{ __('mail.footer', ['site' => $site]) }}
diff --git a/src/resources/views/emails/payment_failure.blade.php b/src/resources/views/emails/html/payment_failure.blade.php similarity index 81% rename from src/resources/views/emails/payment_failure.blade.php rename to src/resources/views/emails/html/payment_failure.blade.php index 4bf28128..3a272320 100644 --- a/src/resources/views/emails/payment_failure.blade.php +++ b/src/resources/views/emails/html/payment_failure.blade.php @@ -1,20 +1,21 @@{{ __('mail.header', ['name' => $username]) }}
{{ __('mail.paymentfailure-body', ['site' => $site]) }}
+{{ __('mail.paymentfailure-body-ext', ['site' => $site]) }}
{{ __('mail.paymentfailure-body-rest', ['site' => $site]) }}
@if ($supportUrl){{ __('mail.support', ['site' => $site]) }}
@endif -{{ __('mail.footer', ['site' => $site, 'appurl' => config('app.url')]) }}
+{{ __('mail.footer', ['site' => $site]) }}
diff --git a/src/resources/views/emails/payment_mandate_disabled.blade.php b/src/resources/views/emails/html/payment_mandate_disabled.blade.php similarity index 80% rename from src/resources/views/emails/payment_mandate_disabled.blade.php rename to src/resources/views/emails/html/payment_mandate_disabled.blade.php index 16b24e71..22dfd114 100644 --- a/src/resources/views/emails/payment_mandate_disabled.blade.php +++ b/src/resources/views/emails/html/payment_mandate_disabled.blade.php @@ -1,20 +1,21 @@{{ __('mail.header', ['name' => $username]) }}
{{ __('mail.paymentmandatedisabled-body', ['site' => $site]) }}
+{{ __('mail.paymentmandatedisabled-body-ext', ['site' => $site]) }}
{{ __('mail.paymentfailure-body-rest', ['site' => $site]) }}
@if ($supportUrl){{ __('mail.support', ['site' => $site]) }}
@endif -{{ __('mail.footer', ['site' => $site, 'appurl' => config('app.url')]) }}
+{{ __('mail.footer', ['site' => $site]) }}
diff --git a/src/resources/views/emails/payment_success.blade.php b/src/resources/views/emails/html/payment_success.blade.php similarity index 85% rename from src/resources/views/emails/payment_success.blade.php rename to src/resources/views/emails/html/payment_success.blade.php index 543987bd..1def7c9d 100644 --- a/src/resources/views/emails/payment_success.blade.php +++ b/src/resources/views/emails/html/payment_success.blade.php @@ -1,19 +1,19 @@{{ __('mail.header', ['name' => $username]) }}
{{ __('mail.paymentsuccess-body', ['site' => $site]) }}
@if ($supportUrl){{ __('mail.support', ['site' => $site]) }}
@endif -{{ __('mail.footer', ['site' => $site, 'appurl' => config('app.url')]) }}
+{{ __('mail.footer', ['site' => $site]) }}
diff --git a/src/resources/views/emails/signup_code.blade.php b/src/resources/views/emails/html/signup_code.blade.php similarity index 72% rename from src/resources/views/emails/signup_code.blade.php rename to src/resources/views/emails/html/signup_code.blade.php index e14af11a..eab5c98b 100644 --- a/src/resources/views/emails/signup_code.blade.php +++ b/src/resources/views/emails/html/signup_code.blade.php @@ -1,15 +1,15 @@{{ __('mail.header', ['name' => $username]) }}
{{ __('mail.signupcode-body', ['code' => $short_code, 'site' => $site]) }}
-{!! $link !!}
+ -{{ __('mail.footer', ['site' => $site, 'appurl' => config('app.url')]) }}
+{{ __('mail.footer', ['site' => $site]) }}
diff --git a/src/resources/views/emails/suspended_debtor.blade.php b/src/resources/views/emails/html/suspended_debtor.blade.php similarity index 84% rename from src/resources/views/emails/suspended_debtor.blade.php rename to src/resources/views/emails/html/suspended_debtor.blade.php index ead7fc12..5c116e59 100644 --- a/src/resources/views/emails/suspended_debtor.blade.php +++ b/src/resources/views/emails/html/suspended_debtor.blade.php @@ -1,24 +1,24 @@{{ __('mail.header', ['name' => $username]) }}
-{{ __('mail.suspendeddebtor-body', ['site' => $site, 'days' => $days]) }} {!! $moreInfo !!}
+{{ __('mail.suspendeddebtor-body', ['site' => $site, 'days' => $days]) }} {!! $moreInfoHtml !!}
{{ __('mail.suspendeddebtor-middle') }}
@if ($supportUrl){{ __('mail.support', ['site' => $site]) }}
@endif @if ($cancelUrl){{ __('mail.suspendeddebtor-cancel') }}
@endif -{{ __('mail.footer', ['site' => $site, 'appurl' => config('app.url')]) }}
+{{ __('mail.footer', ['site' => $site]) }}
diff --git a/src/resources/views/emails/plain/negative_balance.blade.php b/src/resources/views/emails/plain/negative_balance.blade.php new file mode 100644 index 00000000..f243c17b --- /dev/null +++ b/src/resources/views/emails/plain/negative_balance.blade.php @@ -0,0 +1,16 @@ +{!! __('mail.header', ['name' => $username]) !!} + +{!! __('mail.negativebalance-body', ['site' => $site]) !!} + +{!! __('mail.negativebalance-body-ext', ['site' => $site]) !!} + +{!! $walletUrl !!} + +@if ($supportUrl) +{!! __('mail.support', ['site' => $site]) !!} + +{!! $supportUrl !!} +@endif + +-- +{!! __('mail.footer', ['site' => $site]) !!} diff --git a/src/resources/views/emails/plain/password_reset.blade.php b/src/resources/views/emails/plain/password_reset.blade.php new file mode 100644 index 00000000..5e458ed9 --- /dev/null +++ b/src/resources/views/emails/plain/password_reset.blade.php @@ -0,0 +1,8 @@ +{!! __('mail.header', ['name' => $username]) !!} + +{!! __('mail.passwordreset-body', ['code' => $short_code, 'site' => $site]) !!} + +{!! $link !!} + +-- +{!! __('mail.footer', ['site' => $site]) !!} diff --git a/src/resources/views/emails/plain/payment_failure.blade.php b/src/resources/views/emails/plain/payment_failure.blade.php new file mode 100644 index 00000000..0994c119 --- /dev/null +++ b/src/resources/views/emails/plain/payment_failure.blade.php @@ -0,0 +1,18 @@ +{!! __('mail.header', ['name' => $username]) !!} + +{!! __('mail.paymentfailure-body', ['site' => $site]) !!} + +{!! __('mail.paymentfailure-body-ext', ['site' => $site]) !!} + +{!! $walletUrl !!} + +{!! __('mail.paymentfailure-body-rest', ['site' => $site]) !!} + +@if ($supportUrl) +{!! __('mail.support', ['site' => $site]) !!} + +{!! $supportUrl !!} +@endif + +-- +{!! __('mail.footer', ['site' => $site]) !!} diff --git a/src/resources/views/emails/plain/payment_mandate_disabled.blade.php b/src/resources/views/emails/plain/payment_mandate_disabled.blade.php new file mode 100644 index 00000000..40bfde85 --- /dev/null +++ b/src/resources/views/emails/plain/payment_mandate_disabled.blade.php @@ -0,0 +1,18 @@ +{!! __('mail.header', ['name' => $username]) !!} + +{!! __('mail.paymentmandatedisabled-body', ['site' => $site]) !!} + +{!! __('mail.paymentmandatedisabled-body-ext', ['site' => $site]) !!} + +{!! $walletUrl !!} + +{!! __('mail.paymentfailure-body-rest', ['site' => $site]) !!} + +@if ($supportUrl) +{!! __('mail.support', ['site' => $site]) !!} + +{!! $supportUrl !!} +@endif + +-- +{!! __('mail.footer', ['site' => $site]) !!} diff --git a/src/resources/views/emails/plain/payment_success.blade.php b/src/resources/views/emails/plain/payment_success.blade.php new file mode 100644 index 00000000..72e29786 --- /dev/null +++ b/src/resources/views/emails/plain/payment_success.blade.php @@ -0,0 +1,14 @@ +{!! __('mail.header', ['name' => $username]) !!} + +{!! __('mail.paymentsuccess-body', ['site' => $site]) !!} + +{!! $walletUrl !!} + +@if ($supportUrl) +{!! __('mail.support', ['site' => $site]) !!} + +{!! $supportUrl !!} +@endif + +-- +{!! __('mail.footer', ['site' => $site]) !!} diff --git a/src/resources/views/emails/plain/signup_code.blade.php b/src/resources/views/emails/plain/signup_code.blade.php new file mode 100644 index 00000000..38ccd283 --- /dev/null +++ b/src/resources/views/emails/plain/signup_code.blade.php @@ -0,0 +1,8 @@ +{!! __('mail.header', ['name' => $username]) !!} + +{!! __('mail.signupcode-body', ['code' => $short_code, 'site' => $site]) !!} + +{!! $href !!} + +-- +{!! __('mail.footer', ['site' => $site]) !!} diff --git a/src/resources/views/emails/plain/suspended_debtor.blade.php b/src/resources/views/emails/plain/suspended_debtor.blade.php new file mode 100644 index 00000000..2dccacc8 --- /dev/null +++ b/src/resources/views/emails/plain/suspended_debtor.blade.php @@ -0,0 +1,22 @@ +{!! __('mail.header', ['name' => $username]) !!} + +{!! __('mail.suspendeddebtor-body', ['site' => $site, 'days' => $days]) !!} {!! $moreInfoText !!} + +{!! __('mail.suspendeddebtor-middle') !!} + +{!! $walletUrl !!} + +@if ($supportUrl) +{!! __('mail.support', ['site' => $site]) !!} + +{!! $supportUrl !!} +@endif +@if ($cancelUrl) + +{!! __('mail.suspendeddebtor-cancel') !!} + +{!! $cancelUrl !!} +@endif + +-- +{!! __('mail.footer', ['site' => $site]) !!} diff --git a/src/tests/MailInterceptTrait.php b/src/tests/MailInterceptTrait.php new file mode 100644 index 00000000..544d88ad --- /dev/null +++ b/src/tests/MailInterceptTrait.php @@ -0,0 +1,79 @@ +interceptMail(); + + Mail::send($mail); + + $message = $this->interceptedMail()->first(); + + // SwiftMailer does not have methods to get the bodies, we'll parse the message + list($plain, $html) = $this->extractMailBody($message->toString()); + + return [ + 'plain' => $plain, + 'html' => $html, + 'message' => $message, + ]; + } + + /** + * Simple message parser to extract plain and html body + * + * @param string $message Email message as string + * + * @return array Plain text and HTML body + */ + protected function extractMailBody(string $message): array + { + // Note that we're not supporting every message format, we only + // support what Laravel/SwiftMailer produces + // TODO: It may stop working if we start using attachments + $plain = ''; + $html = ''; + + if (preg_match('/[\s\t]boundary="([^"]+)"/', $message, $matches)) { + // multipart message assume plain and html parts + $split = preg_split('/--' . preg_quote($matches[1]) . '/', $message); + + list($plain_head, $plain) = explode("\r\n\r\n", $split[1], 2); + list($html_head, $html) = explode("\r\n\r\n", $split[2], 2); + + if (strpos($plain_head, 'Content-Transfer-Encoding: quoted-printable') !== false) { + $plain = quoted_printable_decode($plain); + } + + if (strpos($html_head, 'Content-Transfer-Encoding: quoted-printable') !== false) { + $html = quoted_printable_decode($html); + } + } else { + list($header, $html) = explode("\r\n\r\n", $message, 2); + if (strpos($header, 'Content-Transfer-Encoding: quoted-printable') !== false) { + $html = quoted_printable_decode($html); + } + } + + return [$plain, $html]; + } +} diff --git a/src/tests/Unit/Mail/NegativeBalanceTest.php b/src/tests/Unit/Mail/NegativeBalanceTest.php index 1e173a29..5089511a 100644 --- a/src/tests/Unit/Mail/NegativeBalanceTest.php +++ b/src/tests/Unit/Mail/NegativeBalanceTest.php @@ -1,43 +1,53 @@ 'https://kolab.org/support', ]); - $mail = new NegativeBalance($user); - $html = $mail->build()->render(); + $mail = $this->fakeMail(new NegativeBalance($user)); + + $html = $mail['html']; + $plain = $mail['plain']; $walletUrl = \App\Utils::serviceUrl('/wallet'); $walletLink = sprintf('%s', $walletUrl, $walletUrl); $supportUrl = \config('app.support_url'); $supportLink = sprintf('%s', $supportUrl, $supportUrl); - $appName = \config('app.name'); - $this->assertSame("$appName Payment Reminder", $mail->subject); + $this->assertMailSubject("$appName Payment Reminder", $mail['message']); + $this->assertStringStartsWith('', $html); $this->assertTrue(strpos($html, $user->name(true)) > 0); $this->assertTrue(strpos($html, $walletLink) > 0); $this->assertTrue(strpos($html, $supportLink) > 0); $this->assertTrue(strpos($html, "behind on paying for your $appName account") > 0); $this->assertTrue(strpos($html, "$appName Support") > 0); $this->assertTrue(strpos($html, "$appName Team") > 0); + + $this->assertStringStartsWith('Dear ' . $user->name(true), $plain); + $this->assertTrue(strpos($plain, $walletUrl) > 0); + $this->assertTrue(strpos($plain, $supportUrl) > 0); + $this->assertTrue(strpos($plain, "behind on paying for your $appName account") > 0); + $this->assertTrue(strpos($plain, "$appName Support") > 0); + $this->assertTrue(strpos($plain, "$appName Team") > 0); } } diff --git a/src/tests/Unit/Mail/PasswordResetTest.php b/src/tests/Unit/Mail/PasswordResetTest.php index 5e8b7df4..99be9a14 100644 --- a/src/tests/Unit/Mail/PasswordResetTest.php +++ b/src/tests/Unit/Mail/PasswordResetTest.php @@ -1,43 +1,50 @@ 123456789, 'mode' => 'password-reset', 'code' => 'code', 'short_code' => 'short-code', ]); - // @phpstan-ignore-next-line $code->user = new User([ 'name' => 'User Name', ]); - $mail = new PasswordReset($code); - $html = $mail->build()->render(); + $mail = $this->fakeMail(new PasswordReset($code)); + + $html = $mail['html']; + $plain = $mail['plain']; $url = Utils::serviceUrl('/login/reset/' . $code->short_code . '-' . $code->code); $link = "$url"; + $appName = \config('app.name'); + + $this->assertMailSubject("$appName Password Reset", $mail['message']); - $this->assertSame(\config('app.name') . ' Password Reset', $mail->subject); $this->assertStringStartsWith('', $html); $this->assertTrue(strpos($html, $link) > 0); $this->assertTrue(strpos($html, $code->user->name(true)) > 0); + + $this->assertStringStartsWith("Dear " . $code->user->name(true), $plain); + $this->assertTrue(strpos($plain, $link) > 0); } } diff --git a/src/tests/Unit/Mail/PaymentFailureTest.php b/src/tests/Unit/Mail/PaymentFailureTest.php index 2f721536..6cf8f46f 100644 --- a/src/tests/Unit/Mail/PaymentFailureTest.php +++ b/src/tests/Unit/Mail/PaymentFailureTest.php @@ -1,44 +1,54 @@ amount = 123; \config(['app.support_url' => 'https://kolab.org/support']); - $mail = new PaymentFailure($payment, $user); - $html = $mail->build()->render(); + $mail = $this->fakeMail(new PaymentFailure($payment, $user)); + + $html = $mail['html']; + $plain = $mail['plain']; $walletUrl = \App\Utils::serviceUrl('/wallet'); $walletLink = sprintf('%s', $walletUrl, $walletUrl); $supportUrl = \config('app.support_url'); $supportLink = sprintf('%s', $supportUrl, $supportUrl); $appName = \config('app.name'); - $this->assertSame("$appName Payment Failed", $mail->subject); + $this->assertMailSubject("$appName Payment Failed", $mail['message']); + $this->assertStringStartsWith('', $html); $this->assertTrue(strpos($html, $user->name(true)) > 0); $this->assertTrue(strpos($html, $walletLink) > 0); $this->assertTrue(strpos($html, $supportLink) > 0); $this->assertTrue(strpos($html, "$appName Support") > 0); $this->assertTrue(strpos($html, "Something went wrong with auto-payment for your $appName account") > 0); $this->assertTrue(strpos($html, "$appName Team") > 0); + + $this->assertStringStartsWith('Dear ' . $user->name(true), $plain); + $this->assertTrue(strpos($plain, $walletUrl) > 0); + $this->assertTrue(strpos($plain, $supportUrl) > 0); + $this->assertTrue(strpos($plain, "$appName Support") > 0); + $this->assertTrue(strpos($plain, "Something went wrong with auto-payment for your $appName account") > 0); + $this->assertTrue(strpos($plain, "$appName Team") > 0); } } diff --git a/src/tests/Unit/Mail/PaymentMandateDisabledTest.php b/src/tests/Unit/Mail/PaymentMandateDisabledTest.php index 7ae936fb..4e43f475 100644 --- a/src/tests/Unit/Mail/PaymentMandateDisabledTest.php +++ b/src/tests/Unit/Mail/PaymentMandateDisabledTest.php @@ -1,43 +1,53 @@ 'https://kolab.org/support']); - $mail = new PaymentMandateDisabled($wallet, $user); - $html = $mail->build()->render(); + $mail = $this->fakeMail(new PaymentMandateDisabled($wallet, $user)); + + $html = $mail['html']; + $plain = $mail['plain']; $walletUrl = \App\Utils::serviceUrl('/wallet'); $walletLink = sprintf('%s', $walletUrl, $walletUrl); $supportUrl = \config('app.support_url'); $supportLink = sprintf('%s', $supportUrl, $supportUrl); $appName = \config('app.name'); - $this->assertSame("$appName Auto-payment Problem", $mail->subject); + $this->assertMailSubject("$appName Auto-payment Problem", $mail['message']); + $this->assertStringStartsWith('', $html); $this->assertTrue(strpos($html, $user->name(true)) > 0); $this->assertTrue(strpos($html, $walletLink) > 0); $this->assertTrue(strpos($html, $supportLink) > 0); $this->assertTrue(strpos($html, "$appName Support") > 0); $this->assertTrue(strpos($html, "Your $appName account balance") > 0); $this->assertTrue(strpos($html, "$appName Team") > 0); + + $this->assertStringStartsWith('Dear ' . $user->name(true), $plain); + $this->assertTrue(strpos($plain, $walletUrl) > 0); + $this->assertTrue(strpos($plain, $supportUrl) > 0); + $this->assertTrue(strpos($plain, "$appName Support") > 0); + $this->assertTrue(strpos($plain, "Your $appName account balance") > 0); + $this->assertTrue(strpos($plain, "$appName Team") > 0); } } diff --git a/src/tests/Unit/Mail/PaymentSuccessTest.php b/src/tests/Unit/Mail/PaymentSuccessTest.php index 14656169..e155d520 100644 --- a/src/tests/Unit/Mail/PaymentSuccessTest.php +++ b/src/tests/Unit/Mail/PaymentSuccessTest.php @@ -1,44 +1,54 @@ amount = 123; \config(['app.support_url' => 'https://kolab.org/support']); - $mail = new PaymentSuccess($payment, $user); - $html = $mail->build()->render(); + $mail = $this->fakeMail(new PaymentSuccess($payment, $user)); + + $html = $mail['html']; + $plain = $mail['plain']; $walletUrl = \App\Utils::serviceUrl('/wallet'); $walletLink = sprintf('%s', $walletUrl, $walletUrl); $supportUrl = \config('app.support_url'); $supportLink = sprintf('%s', $supportUrl, $supportUrl); $appName = \config('app.name'); - $this->assertSame("$appName Payment Succeeded", $mail->subject); + $this->assertMailSubject("$appName Payment Succeeded", $mail['message']); + $this->assertStringStartsWith('', $html); $this->assertTrue(strpos($html, $user->name(true)) > 0); $this->assertTrue(strpos($html, $walletLink) > 0); $this->assertTrue(strpos($html, $supportLink) > 0); $this->assertTrue(strpos($html, "$appName Support") > 0); $this->assertTrue(strpos($html, "The auto-payment for your $appName account") > 0); $this->assertTrue(strpos($html, "$appName Team") > 0); + + $this->assertStringStartsWith('Dear ' . $user->name(true), $plain); + $this->assertTrue(strpos($plain, $walletUrl) > 0); + $this->assertTrue(strpos($plain, $supportUrl) > 0); + $this->assertTrue(strpos($plain, "$appName Support") > 0); + $this->assertTrue(strpos($plain, "The auto-payment for your $appName account") > 0); + $this->assertTrue(strpos($plain, "$appName Team") > 0); } } diff --git a/src/tests/Unit/Mail/SignupVerificationTest.php b/src/tests/Unit/Mail/SignupVerificationTest.php index a6a843e8..c7796658 100644 --- a/src/tests/Unit/Mail/SignupVerificationTest.php +++ b/src/tests/Unit/Mail/SignupVerificationTest.php @@ -1,40 +1,48 @@ 'code', 'short_code' => 'short-code', 'data' => [ 'email' => 'test@email', 'first_name' => 'First', 'last_name' => 'Last', ], ]); - $mail = new SignupVerification($code); - $html = $mail->build()->render(); + $mail = $this->fakeMail(new SignupVerification($code)); + + $html = $mail['html']; + $plain = $mail['plain']; $url = Utils::serviceUrl('/signup/' . $code->short_code . '-' . $code->code); $link = "$url"; + $appName = \config('app.name'); + + $this->assertMailSubject("$appName Registration", $mail['message']); - $this->assertSame(\config('app.name') . ' Registration', $mail->subject); $this->assertStringStartsWith('', $html); $this->assertTrue(strpos($html, $link) > 0); $this->assertTrue(strpos($html, 'First Last') > 0); + + $this->assertStringStartsWith('Dear First Last', $plain); + $this->assertTrue(strpos($plain, $url) > 0); } } diff --git a/src/tests/Unit/Mail/SuspendedDebtorTest.php b/src/tests/Unit/Mail/SuspendedDebtorTest.php index a823bd71..746fddd5 100644 --- a/src/tests/Unit/Mail/SuspendedDebtorTest.php +++ b/src/tests/Unit/Mail/SuspendedDebtorTest.php @@ -1,52 +1,65 @@ 'https://kolab.org/support', 'app.kb.account_suspended' => 'https://kb.kolab.org/account-suspended', 'app.kb.account_delete' => 'https://kb.kolab.org/account-delete', ]); - $mail = new SuspendedDebtor($user); - $html = $mail->build()->render(); + $mail = $this->fakeMail(new SuspendedDebtor($user)); + + $html = $mail['html']; + $plain = $mail['plain']; $walletUrl = \App\Utils::serviceUrl('/wallet'); $walletLink = sprintf('%s', $walletUrl, $walletUrl); $supportUrl = \config('app.support_url'); $supportLink = sprintf('%s', $supportUrl, $supportUrl); $deleteUrl = \config('app.kb.account_delete'); $deleteLink = sprintf('%s', $deleteUrl, $deleteUrl); $moreUrl = \config('app.kb.account_suspended'); $moreLink = sprintf('here', $moreUrl); - $appName = \config('app.name'); - $this->assertSame("$appName Account Suspended", $mail->subject); + $this->assertMailSubject("$appName Account Suspended", $mail['message']); + $this->assertStringStartsWith('', $html); $this->assertTrue(strpos($html, $user->name(true)) > 0); $this->assertTrue(strpos($html, $walletLink) > 0); $this->assertTrue(strpos($html, $supportLink) > 0); $this->assertTrue(strpos($html, $deleteLink) > 0); $this->assertTrue(strpos($html, "You have been behind on paying for your $appName account") > 0); $this->assertTrue(strpos($html, "over 14 days") > 0); $this->assertTrue(strpos($html, "See $moreLink for more information") > 0); $this->assertTrue(strpos($html, "$appName Support") > 0); $this->assertTrue(strpos($html, "$appName Team") > 0); + + $this->assertStringStartsWith('Dear ' . $user->name(true), $plain); + $this->assertTrue(strpos($plain, $walletUrl) > 0); + $this->assertTrue(strpos($plain, $supportUrl) > 0); + $this->assertTrue(strpos($plain, $deleteUrl) > 0); + $this->assertTrue(strpos($plain, "You have been behind on paying for your $appName account") > 0); + $this->assertTrue(strpos($plain, "over 14 days") > 0); + $this->assertTrue(strpos($plain, "See $moreUrl for more information") > 0); + $this->assertTrue(strpos($plain, "$appName Support") > 0); + $this->assertTrue(strpos($plain, "$appName Team") > 0); } }