Unable to send HTML email in Laravel 5.8 - php

I am having a difficult time sending HTML email through my Laravel application. I have tried to return the view and it returns well but when I send the email to an actual email, it arrives as a plain text email without all the HTML parsing.
My View layout for the email is as follows:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta content="width=device-width, initial-scale=1.0" name="viewport">
<!-- Google Fonts -->
<link href="https://fonts.googleapis.com/css?family=Montserrat&display=swap"
rel="stylesheet">
<link href="https://fonts.googleapis.com/css?family=Roboto&display=swap"
rel="stylesheet">
<!-- Bootstrap CSS File -->
<link href="{{ url('design-assets/lib/bootstrap/css/bootstrap.min.css')}}"
rel="stylesheet">
<!-- Main Stylesheet File -->
<link href="{{ url('design-assets/css/style.css" rel="stylesheet')}}">
<link href="{{ url('design-assets/css/prof-custom.css')}}"
rel="stylesheet">
#yield('styles')
</head>
<body id="body">
#yield('content')
<!-- JavaScript Libraries -->
<script src="{{ url('design-assets/lib/jquery/jquery.min.js')}}"></script>
<script src="{{ url('design-assets/lib/jquery/jquery-migrate.min.js')}}">
</script>
<script src="{{ url('design-assets/lib/bootstrap/js/bootstrap.bundle.min.js') }}/"></script>
<!-- Contact Form JavaScript File -->
<!-- Template Main Javascript File -->
<script src="{{ url('design-assets/js/main.js') }}"></script>
#yield('scripts')
</body>
The actual email view is as follows:
#extends('layouts.mail')
#section('content')
<div class="card montserrat-font">
<div class="card-header">
<div class="card-title">Contact Message from the Website</div>
</div>
<div class="card-body">
<div class="card-text">
Dear Sir,<br /><br />
We have a contact from our events website with the following details<br/><br />
</div>
<div class="table-responsive">
<table class="table table-striped">
<tr>
<th>Name of Sender:</th><td>{{$mail_info['name']}}</td>
</tr>
<tr>
<th>Email of Sender:</th><td>{{$mail_info['email']}}</td>
</tr>
<tr>
<th>Phone number of Sender:</th><td>{{$mail_info['phone']}}</td>
</tr>
<tr>
<th>Subject of Message:</th><td>{{$mail_info['subject']}}</td>
</tr>
{{-- <tr>
<th>Message:</th><td>{{$mail_info['message']}}</td>
</tr> --}}
</table>
</div>
<div class="card-title">Message body</div>
<div class="card-text">
{!! $mail_info['message'] !!}
</div>
</div>
</div>
#endsection
The problem is that when I check the format returned from the email view by returning the view as follows:
return new \App\Mail\ContactMail(['email' => 'testemail#gmail.com', 'name' => 'Testing Name','phone'=>'08033776502', 'subject' => 'Just a test', 'message' => "This is a message returned from testing the view email template"]);
I get a view that represents exactly what I want but when I send the email, it arrives as a plain text email
This is how I call the view through mailable class
<?php
namespace App\Mail;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Contracts\Queue\ShouldQueue;
class ContactMail extends Mailable
{
use Queueable, SerializesModels;
/**
* Create a new message instance.
*
* #return void
*/
public $mail_info;
public function __construct($mail_info_array)
{
$this->mail_info = $mail_info_array;
}
/**
* Build the message.
*
* #return $this
*/
public function build()
{
// return $this->view('view.name');
return $this->view('mails.web-contact', ['mail_info'=>$this->mail_info]);
}
}
and then through the controller as follows:
public function post_contact(Request $request)
{
try
{
$data = $request->all();
$this->validate_recaptcher($data['g-recaptcha-response']);
$this->validator($request->all())->validate();
\Mail::to('uchendukwe#yahoo.com')->send(new \App\Mail\ContactMail(['email' => $request->email, 'name' => $request->name,'phone'=>$request->phone, 'subject' => $request->subject, 'message' => $request->message]));
return redirect()->route('ContactForm')->with('msg',"<div class='alert alert-success'><span class='fa fa-check'></span> Message successfully sent. I will get back to you soon if necessary</div>");
// return new \App\Mail\ContactMail(['email' => $request->email, 'name'=> $request->name,'phone'=>$request->phone, 'subject' => $request->subject, 'message' => $request->message]);
}
catch(Exception $e)
{
return back()->withInputs()->with('msg',"<div class='alert alert-danger'><span class='fa fa-warning'></span> ".$e->getMessage()."</div>");
}
}
I am using smtp email driver and every other thing is working as expected.
I will appreciate any guide to resolve this
Thank you

Add your styles inline in the head portion of your email layout. Mail clients tend to ignore externally referenced css. Example:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta content="width=device-width, initial-scale=1.0" name="viewport">
...
<style type="text/css">
your custom styles here
</style>
...
</head>
</html>
You can accomplish this using Markdown.
Customizing The CSS
After exporting the components, the resources/views/vendor/mail/html/themes directory will contain a default.css file. You may customize the CSS in this file and your styles will automatically be in-lined within the HTML representations of your Markdown mail messages.

Related

laravel livewire click is not triggering

below is my App/Http/Livewire/Test.php file
<?php
namespace App\Http\Livewire;
use Livewire\Component;
class Test extends Component
{
public $name = 'mike';
public function render(){
return view('livewire.test');
}
public function clickTest(){
$this->name = 'Joe';
}
}
below is my resources/views/livewire/test.blade.php
<div>
hello {{$name}}
</div>
and below is my resources/views/test.blade.php
<html>
<head>
<title>test page</title>
#livewireStyles
<script src="{{ asset('js/app.js') }}"></script>
<link rel="stylesheet" href="{{ asset('css/app.css') }}">
</head>
<body>
<div>
<livewire:test /> //this line is working fine
<button wire:click="clickTest">test</button> //this line is not working
</div>
#livewireScripts
</body>
</html>
I am able to get hello mike on page load but when I click on the test button it's not changing to Joe. When I checked on my network tab, it looks like the click event is not even triggered and it's not able to reach clickTest() function
Your button needs to be moved into the component:
<div>
hello {{$name}}
<button wire:click="clickTest">test</button>
</div>

Undefined variable in Laravel trying to post source ID route

Currently Working on building out a news api behind a dashboard. I have just recently started getting the error Undefined variable: sourceId (View: C:\Laravel8Auth\resources\views\dashboard.blade.php).
Ive gone everywhere that has source Id and I cant see to figure out what it could be.
Here are some of the codes necessary, im using Laravel 8.x with JetStream Im fairly new at this just wanted to mess around.
web php
`<?php
use Illuminate\Support\Facades\Route;
use App\Models\Api;
use App\Http\Controllers\ApiController;
///Route::get('/', [ApiController::class,'displayNews']);
///Route::get('/fetchNewsFromSource', [ApiController::class, 'fetchNewsFromSource'])->name('fetchNewsFromSource');
///Route::post('/sourceId', 'ApiController#displayNews');
Route::get('/', 'App\Http\Controllers\ApiController#displayNews');
Route::post('sourceId', 'App\Http\Controllers\ApiController#displayNews');
Route::middleware(['auth:sanctum', 'verified'])->get('/dashboard', function () {
return view('dashboard');
})->name('dashboard');
`
Dashboard php
<!DOCTYPE html>
<html lang="{{ config('app.locale') }}">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>News Application with Laravel</title>
<!-- Fonts -->
<link href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700" rel="stylesheet" type="text/css">
<!-- Styles -->
<link href="{{ asset('css/app.css') }}" rel="stylesheet">
<!-- Latest compiled and minified CSS -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
</head>
<body>
<div id="appendDivNews">
<nav class="navbar fixed-top navbar-light bg-faded" style="background-color: #e3f2fd;">
<a class="navbar-brand" href="#">News Around the World</a>
</nav>
{{ csrf_field() }}
<section id="content" class="section-dropdown">
<p class="select-header"> Select a news source: </p>
<label class="select">
<select name="news_sources" id="news_sources">
<option value="{{$sourceId}} : {{$sourceName}}">{{$sourceName}}</option>
#foreach ($newsSources as $newsSource)
<option value="{{$newsSource['id']}} : {{$newsSource['name'] }}">{{$newsSource['name']}}</option>
#endforeach
</select>
</label>
<object id="spinner" data="spinner.svg" type="image/svg+xml" hidden></object>
</section>
<div id="news">
<p> News Source : {{$sourceName}} </p>
<section class="news">
#foreach($news as $selectedNews)
<article>
<img src="{{$selectedNews['urlToImage']}}" alt=""/>
<div class="text">
<h1>{{$selectedNews['title']}}</h1>
<p style="font-size: 14px">{{$selectedNews['description']}} <a href="{{$selectedNews['url']}}"
target="_blank">
<small>read more...</small>
</a></p>
<div style="padding-top: 5px;font-size: 12px">
Author: {{$selectedNews['author'] ? : "Unknown" }}</div>
#if($selectedNews['publishedAt'] !== null)
<div style="padding-top: 5px;">Date
Published: {{ Carbon\Carbon::parse($selectedNews['publishedAt'])->format('l jS \\of F Y ') }}</div>
#else
<div style="padding-top: 5px;">Date Published: Unknown</div>
#endif
</div>
</article>
#endforeach
</section>
</div>
</div>
</body>
<!-- jQuery library -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.0/jquery.min.js"></script>
<!-- Latest compiled JavaScript -->
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<!-- Scripts -->
<script src="{{ asset('js/site.js') }}"></script>
</html>
apicontroller.php supposed to grab from this to get the news api
<?php
namespace App\Http\Controllers;
use App\Models\Api;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Cache;
class ApiController extends Controller
{
/**
* #param Request $request
* #return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
*/
public function displayNews(Request $request)
{
$response = $this->determineMethodHandler($request);
$apiModel = new Api();
$response['news'] = $apiModel->fetchNewsFromSource($response['sourceId']);
$response['newsSources'] = $this->fetchAllNewsSources();
return view('dashboard', $response);
}
/**
* #param $request
* #return mixed
*/
protected function determineMethodHandler($request)
{
if ($request->isMethod('get')) {
$response['sourceName'] = config('app.default_news_source');
$response['sourceId'] = config('app.default_news_source_id');
} else {
$request->validate([
'source' => 'required|string',
]);
$split_input = explode(':', $request->source);
$response['sourceId'] = trim($split_input[0]);
$response['sourceName'] = trim($split_input[1]);
}
return $response;
}
/**
* #return mixed
*/
public function fetchAllNewsSources()
{
$response = Cache::remember('allNewsSources', 22 * 60, function () {
$api = new Api;
return $api->getAllSources();
});
return $response;
}
}
You should pass an array with variables to views
view('dashboard', ["sourceId" => 1, /* and so on */]);
I can't understand what are you doing there.

Laravel Conflicting Scripts, Bootstrap

With my current Laravel project I am using (attempting) both Bootstrap and MDBoostrap. Currently, I'm getting the error TypeError: $(...).DataTable is not a function and from reading up on this online, this is usually due to jquery being called multiple times. I believe the error has to do with app.js but if I only include the scripts Bootstraps requires for a datatable I get the error that $ is undefined. Note: index.blade.html is extending from app.blade.html. With Laravel, I'm only trying to use MDB to create a datatable. This may be a duplicate from here but this question never got answered. I've been banging my head on this problem for a whole day now, any input is appreciative.
app.blade.html
<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="{{asset('css/app.css')}}">
<title>Laravel Project</title>
</head>
<body>
<div class="container">
#yield('content')
</div>
<script src="{{asset('js/app.js')}}"></script>
<script>
// Material Design example
$(document).ready(function () {
$('#dtMaterialDesignExample').DataTable();
$('#dtMaterialDesignExample_wrapper').find('label').each(function () {
$(this).parent().append($(this).children());
});
$('#dtMaterialDesignExample_wrapper .dataTables_filter').find('input').each(function () {
const $this = $(this);
$this.attr("placeholder", "Search");
$this.removeClass('form-control-sm');
});
$('#dtMaterialDesignExample_wrapper .dataTables_length').addClass('d-flex flex-row');
$('#dtMaterialDesignExample_wrapper .dataTables_filter').addClass('md-form');
$('#dtMaterialDesignExample_wrapper select').removeClass('custom-select custom-select-sm form-control form-control-sm');
$('#dtMaterialDesignExample_wrapper select').addClass('mdb-select');
$('#dtMaterialDesignExample_wrapper .mdb-select').materialSelect();
$('#dtMaterialDesignExample_wrapper .dataTables_filter').find('label').remove();
});
</script>
</body>
</html>
index.blade.html
#extends('layouts.app')
#section('content')
<h1>User Table</h1>
#if(count($users) > 0)
<table id="dtMaterialDesignExample" class="table" cellspacing="0" width="100%">
<thead>
<tr>
<th class="th-sm">ID
</th>
<th class="th-sm">Name
</th>
<th class="th-sm">Occupation
</th>
<th class="th-sm">Location
</th>
<th class="th-sm">Salary
</th>
</tr>
</thead>
<tbody>
#foreach($users as $user)
<tr>
<td>{{$user->id}}</td>
<td>{{$user->name}}</td>
<td>{{$user->occupation}}</td>
<td>{{$user->location}}</td>
<td>{{$user->salary}}</td>
</tr>
#endforeach
</tbody>
</table>
#endif
#endsection
UsersController.php
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\User;
class UsersController extends Controller
{
/**
* Display a listing of the resource.
*
* #return \Illuminate\Http\Response
*/
public function index()
{
$users = User::orderBy('id', 'asc')->paginate(10);
return view('users.index',['users'=>$users]);
}
bootstrap.js
try {
window.Popper = require('popper.js').default;
window.$ = window.jQuery = require('jquery');
require('bootstrap');
require('mdbootstrap');
} catch (e) {}
app.js
require('./bootstrap');
var moment = require('mdbootstrap');
app.scss
// Fonts
#import url('https://fonts.googleapis.com/css?family=Nunito');
// Variables
#import 'variables';
// Bootstrap
#import '~bootstrap/scss/bootstrap';
// MDBootstrap
#import '~mdbootstrap/css/mdb.min.css';
If this is the DataTables.net package I believe you have to include JS and possibly the CSS in order to have $('#dtMaterialDesignExample').DataTable(); succeed. I know those do not come with Bootstrap out of the box. I have a Laravel package using vanilla Bootstrap and I had to include the JS and CSS to render data tables.
I'm not terribly familiar with MDB. They may provide CSS, but I don't know if they provide the JS. It doesn't appear that you should have a duplicate definition so you need to make sure you're app is rendering something like the following to the browser:
<link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/1.10.21/css/jquery.dataTables.min.css"/>
<script src="https://cdn.datatables.net/1.10.21/js/jquery.dataTables.min.js" type="text/javascript"></script>
That would include the JS definition of the DataTable() function.

nested layouts in laravel emails

I am working with a part of my application that sends out emails the moment, I want the emails to use a base layout (branding etc) and then an individual template loaded in within that, that is specific to the email type, I know that you can do layouts in views like this when using a controller and view,
protected $layout = 'layouts.master';
however I cannot find a suitable way to use this when sending an email like this,
Mail::send('emails.organisations.admin_removed', $array, function($message) use ($array) {
$message->to("email#email.com", "Simon Ainley")
->from('sender#email.com', 'Email Sender')
->subject("Email Sender - Subject");
});
Is it possible to have a master email template and then feed in sub views?
Yeah! this is possible.
Your main template (emails.orgainsations.template_layout.blade.php)
<head>
<meta charset="utf-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=edge"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<meta name="description" content=""/>
<meta name="author" content=""/>
<title>{{config('app.project_name')}}</title>
<style>
//your css goes here
</style>
</head>
<body>
<table width="600" cellspacing="0" cellpadding="0" border="0" class="wrap">
<tbody>
<tr>
<td class="header">
<h1 class="logo" title="Logo"><img src="{{ asset('assets/images/logo-mail.png') }}" alt="logo" /></h1>
</td>
</tr>
<tr>
<td style="padding: 20px; border: 1px solid #8a35e1; color: #323232;">
#yield('content')
</td>
</tr>
</tbody>
</table>
</body>
Your child template (emails.organisations.admin_removed)
#extends('emails.orgainsations.template_layout')
#section('content')
<p>
your mail content goes here
</p>
#endsection
And, in mail sending code, call the child template as usual
Mail::send('emails.organisations.admin_removed', $array, function($message) use ($array) {
$message->to("email#email.com", "Simon Ainley")
->from('sender#email.com', 'Email Sender')
->subject("Email Sender - Subject");
});
What you want to do is create a master blade template and the extension is done in the child blade templates. Then you pass the child template to your Mail::send() method.
So you have your master: emails/layouts/master.blade.php
<html>
<head>
<title>Email Master</title>
</head>
<body>
Dear {{ $recipient }}
<div class="container">
#yield('content')
</div>
Kind regards,
#include('emails/signature')
</body>
</html>
Then extend in the child template: emails/layouts/organisations/admin/remove.blade.php
#extends('emails.layouts.master')
#section('content')
<p>You have been removed</p>
#endsection
Then pass the child view to the send method:
Mail::send('emails.layouts.organisations.admin.remove', $array, function($message) use ($array) {
$message->to("email#email.com", "Simon Ainley")
->from('sender#email.com', 'Email Sender')
->subject("Email Sender - Subject");
});
I've glossed over a lot of details here so I highly recommend checking out the docs for further in-depth details: https://laravel.com/docs/5.2/blade
You should also try to familiarise yourself with all the different directives blade offers to take full advantage of all its features.

Passing variable to view by with not working in laravel 5.1

I want to pass my variable to view by with
this is my controller for example :
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Http\Requests;
use App\Http\Controllers\Controller;
use App\Prices ;
class PricesController extends Controller
{
function getIndex()
{
$prices = Prices::orderBy( 'id' , 'desc' )-> paginate(2) ;
return view('home')->nest('content' , 'price', compact('prices') ) ->with( [ 'title' => 'prices page' , 'message' => 'my message text ' ]) ;
}
}
and this is my master.blade.php :
<!doctype html>
<html lang="fa">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title> {{ $title }}</title>
<link rel="stylesheet" href="{{ url() }}/css/bootstrap.css">
<link rel="stylesheet" href="{{ url() }}/css/style.css">
<!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries -->
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
<!--[if lt IE 9]>
<script src="https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script>
<script src="https://oss.maxcdn.com/libs/respond.js/1.4.2/respond.min.js"></script>
<![endif]-->
</head>
<body>
<div class="container">
#yield("main")
</div><!-- container -->
<!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
<script src="{{ url() }}/js/bootstrap.min.js"></script>
<script src="{{ url() }}/js/dropdown.js"></script>
<script src="{{ url() }}/js/collapse.js"></script>
<script src="{{ url() }}/js/transition.js"></script>
<script src="{{ url() }}/js/tab.js"></script>
</body>
</html>
and this is home.blade.php :
#extends('master')
#section('main')
#include('top_menu')
<div class="row">
<section class="col-sm-12 col-md-12 content">
<div class="row">
<section class="col-md-12">
<div class="in">
{!! $content !!}
</div>
</section>
</div>
</section>
</div>
#stop
and this is my price.blade.php :
#if( empty($prices) )
<div class="alert alert-warning">
No result
</div>
#else
#if( ! isset( $message) )
No message
#else
{{ $message }}
#endif
<table class="table table-striped">
<tr>
<th>name</th>
<th>yeat</th>
<th>qnty </th>
</tr>
#foreach( $prices as $price )
<tr>
<td> {{$price->product}} </td>
<td> {{$price->yaer}} </td>
<td> {{$price->quantity}} </td>
</tr>
#endforeach
</table>
<center> {!! $prices->render() !!} </center>
#endif
in Output title in <title> {{ $title }}</title> in master.balde.php
is passed good and it will show : prices page in page title , But in this part in price.blade.php :
#if( ! isset( $message) )
No message
#else
{{ $message }}
#endif
the output is :
No maessage
I can access to $message and $title in home.blade.php , But no in price.blade.php
how can I fix it ?
You have an error in a word - maessage, maybe you sending message, but trying to use maessage. Please check it.
Update:
Your code now looks fine. However, look at #if (empty($prices)) part. If (empty($prices) returns true, your code with $message part will never be executed. Probably that's why you don't see my message text.
Update 2:
return view('home')
->nest('content', 'price', array(
'prices' => $prices,
'title' => 'prices page',
'message' => 'my message text'
))
->with([ 'title' => 'prices page', 'message' => 'my message text']);

Categories