#6: Updated the mailing config to use Markdown. Converted the current e-mail templates to Markdown.

This commit is contained in:
Andy Heathershaw 2017-09-12 20:23:48 +01:00
parent 5bb6c9145e
commit 9b13120c41
29 changed files with 547 additions and 36 deletions

View File

@ -94,7 +94,9 @@ class AppInstallation
{
Log::info('Upgrading database', ['new_version' => $appVersionNumber]);
Artisan::call('config:cache');
Artisan::call('cache:clear');
Artisan::call('view:clear');
Artisan::call('migrate', ['--force' => true]);
Artisan::call('db:seed', ['--force' => true]);

View File

@ -37,7 +37,7 @@ class TestMailConfig extends Mailable
return $this
->subject($subject)
->view(Theme::viewName('email.test_email'))
->markdown(Theme::viewName('email.test_email'))
->with(['subject' => $subject]);
}
}

View File

@ -37,7 +37,7 @@ class UserActivationRequired extends Mailable
return $this
->subject($subject)
->view(Theme::viewName('email.user_activation_required'))
->markdown(Theme::viewName('email.user_activation_required'))
->with([
'subject' => $subject,
'user' => $this->user

View File

@ -118,4 +118,20 @@ return [
'sendmail' => '',
/*
|--------------------------------------------------------------------------
| Markdown Mail Settings
|--------------------------------------------------------------------------
|
| If you are using Markdown based email rendering, you may configure your
| theme and component paths here, allowing you to customize the design
| of the emails. Or, you may simply stick with the Laravel defaults!
|
*/
'markdown' => [
'theme' => 'default',
'paths' => [
resource_path('views/vendor/mail'),
],
],
];

View File

@ -1,5 +1,6 @@
<?php
return [
'activate_action' => 'Activate your account',
'activate_user_label' => 'Manually activate this account',
'admin_user_label' => 'User is an administrator',
'album_label' => 'Album:',

View File

@ -1,9 +1,9 @@
@extends('themes.base.email_layout')
@component('mail::message')
Hi {{ Auth::user()->name }},
@section('title', $subject)
@section('content')
<p>Hi {{ Auth::user()->name }},</p>
<p>This e-mail confirms your e-mail settings are correct.</p>
<p>You can now press &quot;Save Settings&quot; on the Settings screen to save these settings.</p>
<p>Regards,<br/>{{ UserConfig::get('app_name') }}</p>
@endsection
This e-mail confirms your e-mail settings are correct.<br/>
You can now press &quot;Save Settings&quot; on the Settings screen to save these settings.
Regards,<br/>
{{ UserConfig::get('app_name') }}
@endcomponent

View File

@ -1,15 +1,17 @@
@extends('themes.base.email_layout')
@component('mail::message')
@lang('email.generic_intro', ['user_name' => $user->name])
@section('title', $subject)
@section('content')
<p>@lang('email.generic_intro', ['user_name' => $user->name])</p>
<p>@lang('email.activation_required_p1', ['app_name' => UserConfig::get('app_name')])</p>
<p>@lang('email.activation_required_p2')</p>
<p><a href="{{ route('auth.activate', ['token' => $user->activation_token]) }}">{{ route('auth.activate', ['token' => $user->activation_token]) }}</a></p>
<p>
-- <br/>
@lang('email.generic_regards')<br/>
{{ UserConfig::get('app_name') }}<br/>
<a href="{{ route('home') }}">{{ route('home') }}</a>
</p>
@endsection
@lang('email.activation_required_p1', ['app_name' => UserConfig::get('app_name')])
@lang('email.activation_required_p2')
@component('mail::button', ['url' => route('auth.activate', ['token' => $user->activation_token]), 'color' => 'green'])
@lang('forms.activate_action')
@endcomponent
@lang('email.generic_regards')<br/>
{{ UserConfig::get('app_name') }}<br/>
<a href="{{ route('home') }}">{{ route('home') }}</a>
@endcomponent

View File

@ -1,56 +1,56 @@
<form role="form" method="POST" action="{{ url('/register') }}">
{{ csrf_field() }}
<div class="form-group row{{ $errors->has('name') ? ' has-danger' : '' }}">
<div class="form-group row">
<label for="name" class="col-md-4 col-form-label text-md-right">@lang('forms.realname_label')</label>
<div class="col-md-6">
<input id="name" type="text" class="form-control" name="name" value="{{ old('name') }}" autofocus>
<input id="name" type="text" class="form-control{{ $errors->has('name') ? ' is-invalid' : '' }}" name="name" value="{{ old('name') }}" autofocus>
@if ($errors->has('name'))
<div class="form-control-feedback">
<div class="invalid-feedback">
<strong>{{ $errors->first('name') }}</strong>
</div>
@endif
</div>
</div>
<div class="form-group row{{ $errors->has('email') ? ' has-danger' : '' }}">
<div class="form-group row">
<label for="email" class="col-md-4 col-form-label text-md-right">@lang('forms.email_label')</label>
<div class="col-md-6">
<input id="email" type="email" class="form-control" name="email" value="{{ old('email') }}">
<input id="email" type="email" class="form-control{{ $errors->has('email') ? ' is-invalid' : '' }}" name="email" value="{{ old('email') }}">
@if ($errors->has('email'))
<div class="form-control-feedback">
<div class="invalid-feedback">
<strong>{{ $errors->first('email') }}</strong>
</div>
@endif
</div>
</div>
<div class="form-group row{{ $errors->has('password') ? ' has-danger' : '' }}">
<div class="form-group row">
<label for="password" class="col-md-4 col-form-label text-md-right">@lang('forms.password_label')</label>
<div class="col-md-6">
<input id="password" type="password" class="form-control" name="password">
<input id="password" type="password" class="form-control{{ $errors->has('password') ? ' is-invalid' : '' }}" name="password">
@if ($errors->has('password'))
<div class="form-control-feedback">
<div class="invalid-feedback">
<strong>{{ $errors->first('password') }}</strong>
</div>
@endif
</div>
</div>
<div class="form-group row{{ $errors->has('password_confirmation') ? ' has-danger' : '' }}">
<div class="form-group row">
<label for="password-confirm" class="col-md-4 col-form-label text-md-right">@lang('forms.password_confirm_label')</label>
<div class="col-md-6">
<input id="password-confirm" type="password" class="form-control" name="password_confirmation">
<input id="password-confirm" type="password" class="form-control{{ $errors->has('password_confirmation') ? ' is-invalid' : '' }}" name="password_confirmation">
@if ($errors->has('password_confirmation'))
<div class="form-control-feedback">
<div class="invalid-feedback">
<strong>{{ $errors->first('password_confirmation') }}</strong>
</div>
@endif

View File

@ -0,0 +1,19 @@
<table class="action" align="center" width="100%" cellpadding="0" cellspacing="0">
<tr>
<td align="center">
<table width="100%" border="0" cellpadding="0" cellspacing="0">
<tr>
<td align="center">
<table border="0" cellpadding="0" cellspacing="0">
<tr>
<td>
<a href="{{ $url }}" class="button button-{{ $color or 'blue' }}" target="_blank">{{ $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">
<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="{{ $url }}">
{{ $slot }}
</a>
</td>
</tr>

View File

@ -0,0 +1,54 @@
<!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" />
</head>
<body>
<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>
<table class="wrapper" width="100%" cellpadding="0" cellspacing="0">
<tr>
<td align="center">
<table class="content" width="100%" cellpadding="0" cellspacing="0">
{{ $header or '' }}
<!-- Email Body -->
<tr>
<td class="body" width="100%" cellpadding="0" cellspacing="0">
<table class="inner-body" align="center" width="570" cellpadding="0" cellspacing="0">
<!-- Body content -->
<tr>
<td class="content-cell">
{{ Illuminate\Mail\Markdown::parse($slot) }}
{{ $subcopy or '' }}
</td>
</tr>
</table>
</td>
</tr>
{{ $footer or '' }}
</table>
</td>
</tr>
</table>
</body>
</html>

View File

@ -0,0 +1,27 @@
@component('mail::layout')
{{-- Header --}}
@slot('header')
@component('mail::header', ['url' => config('app.url')])
{{ UserConfig::get('app_name') }}
@endcomponent
@endslot
{{-- Body --}}
{{ $slot }}
{{-- Subcopy --}}
@isset($subcopy)
@slot('subcopy')
@component('mail::subcopy')
{{ $subcopy }}
@endcomponent
@endslot
@endisset
{{-- Footer --}}
@slot('footer')
@component('mail::footer')
Sent using <a href="http://showmy.photos">Blue Twilight</a>. &copy; 2016-{{ date('Y') }} <a href="https://www.andyheathershaw.uk">Andy Heathershaw</a>.
@endcomponent
@endslot
@endcomponent

View File

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

View File

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

View File

@ -0,0 +1,13 @@
<table width="100%" border="0" cellpadding="0" cellspacing="0">
<tr>
<td align="center">
<table border="0" cellpadding="0" cellspacing="0">
<tr>
<td>
<a href="{{ $url }}" class="button button-green" target="_blank">{{ $slot }}</a>
</td>
</tr>
</table>
</td>
</tr>
</table>

View File

@ -0,0 +1,7 @@
<table class="subcopy" width="100%" cellpadding="0" cellspacing="0">
<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,285 @@
/* Base */
body, body *:not(html):not(style):not(br):not(tr):not(code) {
font-family: Avenir, Helvetica, sans-serif;
box-sizing: border-box;
}
body {
background-color: #f5f8fa;
color: #74787E;
height: 100%;
hyphens: auto;
line-height: 1.4;
margin: 0;
-moz-hyphens: auto;
-ms-word-break: break-all;
width: 100% !important;
-webkit-hyphens: auto;
-webkit-text-size-adjust: none;
word-break: break-all;
word-break: break-word;
}
p,
ul,
ol,
blockquote {
line-height: 1.4;
text-align: left;
}
a {
color: #3869D4;
}
a img {
border: none;
}
/* Typography */
h1 {
color: #2F3133;
font-size: 19px;
font-weight: bold;
margin-top: 0;
text-align: left;
}
h2 {
color: #2F3133;
font-size: 16px;
font-weight: bold;
margin-top: 0;
text-align: left;
}
h3 {
color: #2F3133;
font-size: 14px;
font-weight: bold;
margin-top: 0;
text-align: left;
}
p {
color: #74787E;
font-size: 16px;
line-height: 1.5em;
margin-top: 0;
text-align: left;
}
p.sub {
font-size: 12px;
}
img {
max-width: 100%;
}
/* Layout */
.wrapper {
background-color: #f5f8fa;
margin: 0;
padding: 0;
width: 100%;
-premailer-cellpadding: 0;
-premailer-cellspacing: 0;
-premailer-width: 100%;
}
.content {
margin: 0;
padding: 0;
width: 100%;
-premailer-cellpadding: 0;
-premailer-cellspacing: 0;
-premailer-width: 100%;
}
/* Header */
.header {
padding: 25px 0;
text-align: center;
}
.header a {
color: #bbbfc3;
font-size: 19px;
font-weight: bold;
text-decoration: none;
text-shadow: 0 1px 0 white;
}
/* Body */
.body {
background-color: #FFFFFF;
border-bottom: 1px solid #EDEFF2;
border-top: 1px solid #EDEFF2;
margin: 0;
padding: 0;
width: 100%;
-premailer-cellpadding: 0;
-premailer-cellspacing: 0;
-premailer-width: 100%;
}
.inner-body {
background-color: #FFFFFF;
margin: 0 auto;
padding: 0;
width: 570px;
-premailer-cellpadding: 0;
-premailer-cellspacing: 0;
-premailer-width: 570px;
}
/* Subcopy */
.subcopy {
border-top: 1px solid #EDEFF2;
margin-top: 25px;
padding-top: 25px;
}
.subcopy p {
font-size: 12px;
}
/* Footer */
.footer {
margin: 0 auto;
padding: 0;
text-align: center;
width: 570px;
-premailer-cellpadding: 0;
-premailer-cellspacing: 0;
-premailer-width: 570px;
}
.footer p {
color: #AEAEAE;
font-size: 12px;
text-align: center;
}
/* Tables */
.table table {
margin: 30px auto;
width: 100%;
-premailer-cellpadding: 0;
-premailer-cellspacing: 0;
-premailer-width: 100%;
}
.table th {
border-bottom: 1px solid #EDEFF2;
padding-bottom: 8px;
}
.table td {
color: #74787E;
font-size: 15px;
line-height: 18px;
padding: 10px 0;
}
.content-cell {
padding: 35px;
}
/* Buttons */
.action {
margin: 30px auto;
padding: 0;
text-align: center;
width: 100%;
-premailer-cellpadding: 0;
-premailer-cellspacing: 0;
-premailer-width: 100%;
}
.button {
border-radius: 3px;
box-shadow: 0 2px 3px rgba(0, 0, 0, 0.16);
color: #FFF;
display: inline-block;
text-decoration: none;
-webkit-text-size-adjust: none;
}
.button-blue {
background-color: #3097D1;
border-top: 10px solid #3097D1;
border-right: 18px solid #3097D1;
border-bottom: 10px solid #3097D1;
border-left: 18px solid #3097D1;
}
.button-green {
background-color: #2ab27b;
border-top: 10px solid #2ab27b;
border-right: 18px solid #2ab27b;
border-bottom: 10px solid #2ab27b;
border-left: 18px solid #2ab27b;
}
.button-red {
background-color: #bf5329;
border-top: 10px solid #bf5329;
border-right: 18px solid #bf5329;
border-bottom: 10px solid #bf5329;
border-left: 18px solid #bf5329;
}
/* Panels */
.panel {
margin: 0 0 21px;
}
.panel-content {
background-color: #EDEFF2;
padding: 16px;
}
.panel-item {
padding: 0;
}
.panel-item p:last-of-type {
margin-bottom: 0;
padding-bottom: 0;
}
/* Promotions */
.promotion {
background-color: #FFFFFF;
border: 2px dashed #9BA2AB;
margin: 0;
margin-bottom: 25px;
margin-top: 25px;
padding: 24px;
width: 100%;
-premailer-cellpadding: 0;
-premailer-cellspacing: 0;
-premailer-width: 100%;
}
.promotion h1 {
text-align: center;
}
.promotion p {
font-size: 15px;
text-align: center;
}

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')])
{{ UserConfig::get('app_name') }}
@endcomponent
@endslot
{{-- Body --}}
{{ $slot }}
{{-- Subcopy --}}
@isset($subcopy)
@slot('subcopy')
@component('mail::subcopy')
{{ $subcopy }}
@endcomponent
@endslot
@endisset
{{-- Footer --}}
@slot('footer')
@component('mail::footer')
Sent using [Blue Twilight](http://showmy.photos). © 2016-{{ date('Y') }} [Andy Heathershaw](https://www.andyheathershaw.uk).
@endcomponent
@endslot
@endcomponent

View File

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

View File

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

View File

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

View File

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

View File

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