At the moment I currently use laravel-snappy to generate my PDFs from pages, I do this primarily because it plays really nice with some JavaScript scripts I have on a few of my generated pages.
I know it's possible to attach an attachment of sorts to a mailable, which is what I have been using at the suggestions of others until the notifiables get a few more things worked on with them.
But I am stuck as to whether or not it's possible to attach a generated PDF to a mailable.
At the moment, I send the PDFs to generate through a route:
Route::get('/shipments/download/{shipment}','ShipmentController#downloadPDF');
Which is then sent to here in the controller:
public function downloadPDF(Shipment $shipment){
$shipment_details = $shipment->shipment_details;
$pdf = PDF::loadView('shipments.pdf', compact('shipment','shipment_details'))
->setOption('images', true)
->setOption('enable-javascript', true)
->setOption('javascript-delay', 100);
return $pdf->download('shipment'.$shipment->url_string.'.pdf');
}
My mailable is defined as such:
<?php
namespace App\Mail;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Contracts\Queue\ShouldQueue;
use App\Shipment;
class newFreightBill extends Mailable
{
use Queueable, SerializesModels;
/**
* Create a new message instance.
*
* #return void
*/
public $shipment;
public function __construct(Shipment $shipment)
{
$this->shipment = $shipment;
$this->attachmentURL = $shipment->url_string;
$this->proNumber = $shipment->pro_number;
}
/**
* Build the message.
*
* #return $this
*/
public function build()
{
return $this->from('billing#cmxtrucking.com')
->subject('New Freight Bill Created - '. $this->proNumber)
->view('emails.shipments.created');
}
}
So, is it possible to attach a generated PDF?
You can use attach to send files via mail. For example:-
public function build()
{
return $this->from('billing#cmxtrucking.com')
->subject('New Freight Bill Created - '. $this->proNumber)
->view('emails.shipments.created')
->attach($your_pdf_file_path_goes_here);
}
This worked for me while i was trying. Hope it works for you too.
Here i am using laravel package "vsmoraes/laravel-pdf" for pdf generation
steps :
1) render view with dynamic data
2) load this view to pdf
3) attach pdf data to the mail
$html = view('pdf',compact('result','score'))->render();
$pdf = PDF::Load($html);
\Mail::send('mail.analysis',['user'=>$data],function($message) use($pdf,$user){
$message->to($user->email)->subject("Page Speed Aanlysis Generated");
$message->attachData($pdf->output(),'pdf_name.pdf');
});
Related
Sending email with
\Mail::to(
method in laravel 8 app
I have html tags in im my email template
#component('mail::message')
<h3 >
You registered at {{ $site_mame }}
</h3>
Best regards, <br>
...
#endcomponent
and code in my app/Mail/UserRegistered.php :
<?php
namespace App\Mail;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
class UserRegistered extends Mailable
{
use Queueable, SerializesModels;
public $site_mame;
public $user;
public $confirmation_code;
public function __construct( $site_mame, $user, $confirmation_code )
{
$this->site_mame = $site_mame;
$this->user = $user;
$this->confirmation_code = $confirmation_code;
}
/**
* Build the message.
*
* #return $this
*/
public function build()
{
return $this->markdown('email.UserRegisteredEmail')
->with('site_mame', $this->site_mame)
->with('user', $this->user)
->with('confirmation_code', $this->confirmation_code);
}
}
With sendgrid options in my .env file I got valid emaul at my google account, but html tags are not rendered.
If there is a way to render all html tags? Does it depend on laravel app/emailing options
or setting in my google(or some other account).
What can I do from my side?
UPDATED :
Modified :
$this->view(
I got error :
No hint path defined for [mail]. (View: project/resources/views/email/UserRegisteredEmail.blade.php)
Pointing to my blade file.
Searching in net I found as possible decision :
php artisan vendor:publish --tag=laravel-mail
and clearing all cache
But I still got the same error.
Did I miss some options ?
Thanks in advance!
You are using the markdown() method, which is a method to utilize the pre-built templates and components of mail notifications in your mailables.
This offers a multitude of advantages:
instead of wrapping headings in h1, h2, etc. tags, you can just put a #, ##, etc. at the beginning of the line
no need to wrap lists in <ul>, and list items in <li> tags. In markdown, you can just use a dash (-) for listing elements
italic/bold font can be achieved by putting */** around the text you want to emphasize
You can read more about this on the official Laravel documentation.
https://laravel.com/docs/8.x/mail#markdown-mailables
If you want to use HTML, you can just render a view:
/**
* Build the message.
*
* #return $this
*/
public function build()
{
return $this->view('email.UserRegisteredEmail')
->with('site_mame', $this->site_mame)
->with('user', $this->user)
->with('confirmation_code', $this->confirmation_code);
}
I want to pass the variables in my mail body how can I do that.
I am doing.
I want to send the mail template which is coming from DB, In that template, I have defined the variables to be get replaced when it is sent.
`$record = DB::table('email_templates')->select('content','em_temp_id')->where('em_temp_id',
$request->select_temp)->where('is_active', 1)->first();
$body = htmlspecialchars_decode($record->content);' //the html body
and my mail function
'Mail::send([],[], function($message) use ($Toarray, $ToCCarray, $ToBCCarray, $subject, $body,
$is_plainOrHtml){
$message->to($Toarray, '');
$message->cc($ToCCarray, '');
$message->bcc($ToBCCarray, '');
$message->subject($subject);
$message->setBody($body, 'text/html'); //for plain text email
});'
Template in DB is like:
`<p>Dear {{$userName}},</p>
<p>The {{$service_provider}}, requesting you to join <strong>{{$channel}}</strong> service.
</p>`
Array to pass:
`$arr_pass['userName'] = 'John';
$arr_pass['service_provider'] = 'abc.com';
$arr_pass['channel'] = 'Tom';`
How can i pass this array in the mail body?
You can use Blade::compileString, which will translate the blade template that you read from the database. There is one tricky part when you do so - how to send the variables' data.
Here are some hints:
You could use this library: https://github.com/TerrePorter/StringBladeCompiler
You could use a BladeCompiler similar to Is there any way to compile a blade template from a string?
Roll your own compiler by checking the implementation of https://laravel.com/api/8.x/Illuminate/View/Compilers/BladeCompiler.html
You can create a new Mail class by extending Mailable class and pass your array to the constructor of the Mail class.
Here in the below example, RFIRequestMail is a Mail class created in App\Mail Directory.
RFIRequestMail.php
<?php
namespace App\Mail;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Contracts\Queue\ShouldQueue;
class RFIRequestMail extends Mailable
{
use Queueable, SerializesModels;
public $verifierData;
/**
* Create a new message instance.
*
* #return void
*/
public function __construct($data)
{
$this->data = $data;
}
/**
* Build the message.
*
* #return $this
*/
public function build()
{
return $this->view('mail-view-template');
}
}
MailController
$sendData = User::find($id);
$data = User::find($company_id);
$sendData["link"] = env("APP_URL");
$sendData["year"] = $request->get("year");
$sendData["user"] = $data->first_name.' '.$data->last_name;
Mail::to($data->email)->send(new RFIRequestMail($sendData));
I would like to send a telegram message to a specific user at 17:00 using laravel's Telegram notification channel, I however can't seem to get it going. I currently use a cmd command for testing, but keep getting errors and don't know what to do.
Here are my files for the command and notification:
SendNotification.php
<?php
namespace Rogier\Lab\Console;
use Illuminate\Console\Command;
use Rogier\Lab\Notifications\DailyTelegram;
class SendNotifications extends Command
{
protected $name = 'lab:notifications:send';
protected $description = 'Send notifications';
protected $userid = 919871501;
/**
* Execute the console command.
* #return void
*/
public function handle()
{
$this->output->writeln('Sending notifications');
$notification = new DailyTelegram($this->userid);
$notification->via()->toTelegram();
$this->output->writeln('Done');
}
}
and DailyTelegram.php
<?php
namespace Rogier\Lab\Notifications;
use NotificationChannels\Telegram\TelegramChannel;
use NotificationChannels\Telegram\TelegramMessage;
use Illuminate\Notifications\Notification;
use Illuminate\Notifications\Notifiable;
class DailyTelegram extends Notification
{
protected $userid = 919871501;
public function via()
{
return [TelegramChannel::class];
}
public function toTelegram()
{
return TelegramMessage::create()
// Optional recipient user id.
->to($this->userid)
// Markdown supported.
->content("Hello there!\nYour invoice has been *PAID*");
}
}
I currently get the error "Call to a member function toTelegram() on array", but I feel like I tried everything, maybe I'm doing it completely wrong. Does anyone know how I should do it?
thanks in advance
Yes, you are doing it wrong. Notifiables have notify() method, you should use it:
$user->notify(new DailyTelegram);
In this example $user is App\User instance (which is notifiable out of the box).
You should check out both Laravel's sending notifications and laravel-notification-channels/telegram docs.
So I need to store my blade email templates in database.
And now I am having problem to use db content with view, because dynamic informations are not rendered.
Here is the code to elaborate a bit more problem which I am facing:
Mailable class:
namespace App\Mail;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Contracts\Queue\ShouldQueue;
use App\User;
class activateUser extends Mailable
{
public $html;
public $user;
use Queueable, SerializesModels;
/**
* Create a new message instance.
*
* #return void
*/
public function __construct(User $user)
{
//this actually is much longer text coming from the DB - basicly coopied blade email template into the db
$this->html = 'Hi {{ $user->first_name }},<br /><br /> Your profile on our site has been activated.<br /><br />';
$this->user = $user;
}
/**
* Build the message.
*
* #return $this
*/
public function build()
{
return $this->view('emails.activateUser')->subject('Your account is activated');
}
}
Then the view emails.activateUser.blade.php looks like this:
{{ $html }}
And Inside of my controller I am calling this:
Mail::to($user->email)->send(new activateUser($user));
Problem is that actual username of the user will not be printed in the email and {{ }} will stay as well in email content.
Any ideas how to solve this, since my email template content needs to come from DB
You can use the Blade template compiler to compile a string:
public function compileBladeString(string $template, $data = []): string
{
$bladeCompiler = app('blade.compiler');
ob_start() && extract($data, EXTR_SKIP);
eval('?>' . $bladeCompiler->compileString($template));
$compiled = ob_get_contents();
ob_end_clean();
return $compiled;
}
You can then simply invoke this method with a string containing your template from the database.
I have a command in my code that is run daily by cron that sends emails to all new users. It used to work ok, but after I have swithched the queue driver to SQS and upgraded Laravel 5.2 to 5.3 it started throwing an error.
InvalidArgumentExceptionvendor/laravel/framework/src/Illuminate/Mail/Mailer.php:379
Invalid view.
I don't know what might cause the error, because I have not deleted the view. Also when I run the command manually it does not throw any errors.
Here is the command code:
public function handle()
{
$subscriptions = Purchase::where('created_at', '>=', Carbon::now()->subDay())
->groupBy('user_id')
->get();
$bar = $this->output->createProgressBar(count($subscriptions));
foreach ($subscriptions as $subscription) {
$user = $subscription->user;
// if ($user->is_active_customer) {
Mail::to($user)->bcc(env('BCC_RECEIPTS_EMAIL'))->send(new NeedHelp());
// }
$bar->advance();
}
$bar->finish();
$this->info("\nSuccess! " . number_format(count($subscriptions)) . ' emails were sent.');
}
Here is the NeedHelp class code (I have changed the email and sender name for this thread):
<?php
namespace App\Mail;
use App\User;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Contracts\Queue\ShouldQueue;
class NeedHelp extends Mailable
{
use Queueable, SerializesModels;
/**
* Create a new message instance.
*
*/
public function __construct(){
}
/**
* Build the message.
*
* #return $this
*/
public function build()
{
return $this->subject('Need help?')
->from('default#mail.com', 'Sender')
->view('emails.need-help');
}
}
I have found the error. The reason was that I have accidentally connected two applications to the same queue, which caused them to process jobs and emails of each other which resulted in this error.