I use the instructions https://laravel.com/docs/5.8/mail
to send an email later than expected, but I get an error when I try to send it:
ErrorException (E_ERROR)
Only mailables may be queued. (View: ....
Please for help.
My methods to send:
public static function sent_info_email_later ($data_f, $minuts) {
$data = json_decode($data_f);
$when = now()->addMinutes($minuts);
return Mail::later($when,'emails.message', ['title' => $data->subject, 'body' => $data->body], function ($message) use ($data, $when)
{
$message->from(env('MAIL_USERNAME'), 'NETPlatform24');
if(gettype($data->to) == 'array') {
$dest_to = $data->to;
} else {
$dest_to = explode(', ', $data->to)[0];
}
$message->to($dest_to);
$message->subject($data->subject);
return true;
});
}
and calling index.php
$data = json_encode(array('to' => 'my email', 'subject' => 'This email was send 1 min after run', 'body' => 'time now'.now().'<br> time send: '.now()->addMinutes(1)));
$send_mail = \App\Http\Controllers\Backend\Auth\Mail\MailController::sent_info_email_later($data, 1);
I wrote this code long time ago. I hope this will help to clarify. For each Cargo I send a email using queue.
<?php
public function mails_meeting($meeting, $group, $place, $date, $message, $user)
{
$subject = "meeting " . $group;
$cargos = Cargo::where('comision_id', '=', $meeting->comision_id)->where('active', '=', '1')->get();
foreach ($cargos as $cargo) {
$mail_reciever = $cargo->asambleista->user->email;
Mail::queue('correos.comision_mail', ['group' => $group, 'place' => $place,
'date' => $date, 'message' => $message, 'user' => $user],
function ($mail) use ($subject, $mail_reciever) {
$mail->from('siarcaf#gmail.com', 'Automatic mail system');
$mail->to($mail_reciever);
$mail->subject($subject);
});
}
return 0;
}
In your_app/config/mail.php .
'sendmail' => '/usr/sbin/sendmail -bs',
'stream' => [
'ssl' => [
'allow_self_signed' => true,
'verify_peer' => false,
'verify_peer_name' => false,
],
],
.env file
MAIL_DRIVER=smtp
MAIL_HOST=mailtrap.io
MAIL_PORT=2525
MAIL_USERNAME=your_username
MAIL_PASSWORD=your_password
MAIL_ENCRYPTION=your_conf
The error you're getting (and the docs) indicate that the second argument passed to the later method must be an instance of Illuminate\Mail\Mailable.
Where you currently have the string 'emails.message', you will need to replace this with an instance of Mailable that represents the email message that you're trying to send.
For example, create this file in /app/Mail (create the folder if it doesn't exist):
<?php
namespace App\Mail;
use Illuminate\Mail\Mailable;
use Illuminate\Contracts\Queue\ShouldQueue;
class InfoEmail extends Mailable implements ShouldQueue
{
public $subject;
public $body;
/**
* Create a new message instance.
*
* #return void
*/
public function __construct($subject, $body)
{
$this->subject = $subject;
$this->body = $body;
}
/**
* Build the message.
*
* #return $this
*/
public function build()
{
return $this->from(env('MAIL_USERNAME'), 'NETPlatform24')
->subject($this->subject)
->view('emails.message', ['title' => $this->subject, 'body' => $this->body]);
}
}
This assumes that 'emails.message' is the view file you intend to use for this email, located at /resources/views/emails/message.blade.php relative to your project's root. I'd actually recommend changing this to something a bit more descriptive.
You'll then need to change your sent_info_email_later method to something like this:
public static function sent_info_email_later ($data_f, $minuts) {
$data = json_decode($data_f);
$when = now()->addMinutes($minuts);
$recipients = is_array($data->to) ? $data->to : explode(', ', $data->to);
$recipients = array_filter(array_map('trim', $recipients));
$first_recipient = array_shift($recipients);
return Mail::to($first_recipient)
->cc($recipients)
->later($when, new InfoEmail($data->subject, $data->body));
}
I've taken the liberty of tidying up your recipients by extracting out the first recipient for the to and moving the rest to cc as this may play better with more email service providers.
Hope this helps!
Related
I find out that the Pdf I attached to my email does not show when delivered to my email in Mailtrap but it shows in the RAW data section.
My Controller Method to send an email:
public function store(Request $request)
{
$this->validate($request, [
'name' => 'required',
'email' => 'required|email',
'quantity' => 'required|numeric|digits:1',
]);
if ($request->quantity > 5) {
toastr()->error('Only 5 tickets per booking is allowed');
return redirect()->back();
}
$a = 0;
$file = array();
while ($a < $request->quantity) {
$ordercode = substr(md5(time() . mt_rand(1, 1000000)), 0, 22);
$qrcodepath = 'assets/payments/qrcodes/'.str_slug($request->name).time().'.png';
$qrcode = QrCode::format('png')->size(400)->generate($ordercode, $qrcodepath);
$data["name"] = $request->name;
$data["email"] = $request->email;
$data["qrcode"] = $qrcodepath;
$data["ordercode"] = $ordercode;
$pdf = PDF::loadView('pdf.payment', $data);
$pdfpath = 'assets/payments/pdf/'.str_slug($request->name).time().'.pdf';
$pdf->save($pdfpath);
$payment = Payment::create([
'fullname' => $request->name,
'qrcode' => $qrcodepath,
'ordercode' => $ordercode,
'email' => $request->email,
'quantity' => 1,
'pdfticket' => $pdfpath
]);
$file[] = $payment->pdfticket;
$a++;
sleep(1);
}
$data = array(
'name' => $payment->fullname,
'tickets' => $file,
);
Mail::to($payment->email)->send(new PurchaseComplete($data));
dd($payment->email);
toastr()->success('Payment created successfully');
return redirect()->back();
}
My Mailable:
namespace App\Mail;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Contracts\Queue\ShouldQueue;
class PurchaseComplete extends Mailable
{
use Queueable, SerializesModels;
public $data;
/**
* Create a new message instance.
*
* #return void
*/
public function __construct($data)
{
$this->data = $data;
}
/**
* Build the message.
*
* #return $this
*/
public function build()
{
$message = $this->subject('Ticket Purchase - CodeRed')->markdown('emails.purchase.complete')->with('data', $this->data);
$count = 0;
foreach ($this->data['tickets'] as $ticket) {
$count++;
$message->attach(asset($ticket), array(
'as' => 'ticket'.$count.'.pdf',
'mime' => 'application/pdf',
));
}
return $message;
}
}
My Email Markdown:
#component('mail::message')
# Hello {{ $data['name'] }}
Your Ticket Purchase: Please find attached files below.
Ensure you download the ticket and load it on your phone when you arrive!
You can also Login to your profile to download the Qrcode for a quick scan and copies of your tickets!
#component('mail::button', ['url' => route('login')])
Login
#endcomponent
If you have any further questions: contact us through the contact section on our website.
Thanks,<br>
{{ config('app.name') }}
#endcomponent
Mailtraps HTML output of the mail:
But in the RAW section: it shows that a pdf was attached:
I have searched the web and implemented practically every solution I found to try solving this problem but no success. I have tried using public_path(), storage_path(), attachData() and more! I just don't know how to proceed and make this work.
My bad for this: I didn't know Mailtrap displays attachments differently from other mail service providers...
I am trying to create a simple contact us form email and use the existing default email template that comes shipped with laravel.
In my form I collect the following inputs from my users:
first_name
last_name
email
subject
message
I use the following FormRequest rules called SendEmailRequest to validate the input:
public function rules()
{
return [
'first_name' => ['required', 'string', 'min:3'],
'last_name' => ['required', 'string', 'min:3'],
'email' => ['required', 'email'],
'subject' => ['required', 'in:' . implode(',', config('contact-us-subjects'))],
'message' => ['required', 'string', 'min:10'],
];
}
This is the function on my controller that receives the request and attempts to send the email:
public function sendEmail(SendEmailRequest $sendEmailRequest)
{
$validated = $sendEmailRequest->validated();
$data['slot'] = view('mail.contact-us', $validated)->render();
Mail::send('vendor.mail.html.message', $data, function($message) use($validated) {
$message->from($validated['email'], $validated['first_name'] . ' ' . $validated['last_name']);
$message->subject($validated['subject']);
$message->to(config('mail.from.address'), config('mail.from.name'));
});
return redirect()
->back()
->with('status', 'Thanks, your email has been successfully sent to us');
}
When I run this; I am getting the following error:
Facade\Ignition\Exceptions\ViewException
No hint path defined for [mail]. (View: C:\xampp\htdocs\MyApp\src\resources\views\vendor\mail\html\message.blade.php)
I am using Laravel 6.x with PHP 7.x. Any ideas what I might be doing wrong here?
I've solved the issue slightly differently. I had to build the mailable as markdown.
Step 1. Create a new mailable using this artisan command: php artisan make:mail ContactUs
Step 2. Ensure default to (similar to from address/name) is set on config/mail.php, for example:
'to' => [
'address' => env('MAIL_FROM_ADDRESS', 'hello#example.com'),
'name' => env('MAIL_FROM_NAME', 'Example'),
],
Step 3. Modify the app/Mail/ContactUs.php like this:
<?php
namespace App\Mail;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
class ContactUs extends Mailable
{
use Queueable, SerializesModels;
/**
* #var array $data
*/
private $data;
/**
* Create a new message instance.
*
* #param array $data
*/
public function __construct(array $data)
{
$this->data = $data;
}
/**
* Build the message.
*
* #return $this
*/
public function build()
{
return $this
->from($this->data['email'], $this->data['first_name'] . ' ' . $this->data['last_name'])
->subject($this->data['subject'])
->markdown('mail.contact-us', [
'messageBody' => $this->data['message'],
]);
}
}
Step 4. Use the new mailable like this:
public function sendEmail(SendEmailRequest $sendEmailRequest)
{
$validated = $sendEmailRequest->validated();
Mail::send(new ContactUs($validated));
return redirect()
->back()
->with('status', 'Thanks, your email has been successfully sent to us');
}
This appears to have achieved what I was originally after. The email was sent using the default template laravel ships with.
I wonder how to write proper unit test for my email sending method. It's a problem because inside method I get data from Auth object. Should I send id of user in Request?
public function sendGroupInvite(Request $request){
foreach ($request->get('data') as $item){
$invitations = new \App\Models\Invitations();
$invitations->user_id = Auth::id();
$invitations->name = $item["name"];
$invitations->email = $item["email"];
$invitations->status = 0;
$invitations->token = \UUID::getToken(20);
$invitations->username = Auth::user()->name;
$invitations->save();
$settings = UserSettings::where('user_id', Auth::id())->first();
$email = $item["email"];
$url = 'https://example.com/invite/accept/'.$invitations->token;
$urlreject = 'https://example.com/invite/reject/'.$invitations->token;
$mailproperties = ['token' => $invitations->token,
'name' => $invitations->name,
'url' => $url,
'email' => $email,
'urlreject' => $urlreject,
'userid' => Auth::id(),
'username' => Auth::user()->name,
'user_name' => $settings->name,
'user_lastname' => $settings->lastname,
'user_link' => $settings->user_link,
];
$this->dispatch(new SendMail(new Invitations($mailproperties)));
}
return json_encode(array('msg' => 'ok'));
}
I'm using Auth to get username and user id. When I testing it it's not works, because Auth it's null.
I would go with mocking the queue, something similar to this. Mock Documentation
class MailTester extends TestCase{
/**
* #test
*/
public function test_mail(){
Queue::fake();
// call your api or method
Queue::assertPushed(SendMail, function(SendMail $job) {
return $job->something = $yourProperties;
});
}
You could try "acting as" to deal with the Auth::user().
...
class MyControllerTest extends TestCase{
/**
* #test
*/
public function foo(){
$user = App\Users::find(env('TEST_USER_ID')); //from phpunit.xml
$route = route('foo-route');
$post = ['foo' => 'bar'];
$this->actingAs($user)//a second param is opitonal here for api
->post($route, $post)
->assertStatus(200);
}
}
I am trying to send two emails at the same time when the user submits contact form. One email to the website owner and other to the user as autoresponse. I have been trying to do this for about last 4 hours and tried different solutions on internet but I am totally lost. Here is my code to send an email
public function contactForm(Request $request)
{
$parameters = Input::get();
$email = Input::get('email');
$inquiryType = Input::get('type_inquiry');
foreach ([
'contactmessage' => 'Message',
'email' => 'Email',
'phone' => 'Phone',
'first_name' => 'Contact Name',
'g-recaptcha-response' => 'Captcha',
] as $key => $label) {
if (!isset($parameters[$key]) || empty($parameters[$key])) {
return response()->json(
[
'success' => false,
'error' => "{$label} cannot be empty",
]
);
}
}
$recipients = 'abc#gmail.com';
// if page set, try to get recipients from the page settings
if (Input::get('page_id')) {
$page = Page::find(Input::get('page_id'));
if ($page && !empty($page->recipients)) {
$recipients = explode(',', $page->recipients);
}
}
try {
$res = Mail::send(
'emails.contact',
$parameters,
function (Message $message) use ($recipients) {
$message->subject('Contact message');
if (is_array($recipients)) {
// email to first address
$message->to(array_shift($recipients));
// cc others
$message->cc($recipients);
} else {
$message->to($recipients);
}
}
);
} catch (\Exception $e) {
return response()->json(
[
'success' => false,
'error' => $e->getMessage(),
]
);
}
if($inquiryType == 'Rental Inquiry'){
Mail::send(
'emails.autoresponse',
'',
function (Message $message) use ($email) {
$message->subject('Thank you for inquiring');
if (is_array($email) {
// email to first address
$message->to(array_shift($email);
// cc others
$message->cc($email);
} else {
$message->to($email);
}
}
);
}
return response()->json(
[
'success' => $res,
]
);
}
I have tried to do the same thing by different methods but none of them are working. Please help me. This is the first time I am sending multiple emails using laravel. I think I am doing a big and silly mistake somewhere.
Thank you.
You have a missing closing parenthesis near is_array($email)
$message->subject('Thank you for inquiring');
if (is_array($email)) {
Also i would you use laravel's validator to check for required input. Another suggestion would be to use queues for mails. Sending two mails in a single request might cause your page load time to increase significantly.
The best way is create one Laravel Jobs
php artisan queue:table
php artisan migrate
php artisan make:job SendEmail
Edit your .env
QUEUE_DRIVER=database
Edit your app /Jobs/SendEmail.php
namespace App\Jobs;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Contracts\Mail\Mailer;
class SendEmail extends Job implements ShouldQueue
{
use InteractsWithQueue, SerializesModels;
protected $subject;
protected $view;
protected $data;
protected $email;
/**
* SendEmail constructor.
* #param $subject
* #param $data
* #param $view
* #param $email
*/
public function __construct($subject, $data, $view, $email)
{
$this->subject = $subject;
$this->data = $data;
$this->email = $email;
$this->view = $view;
}
/**
* Execute the job.
* #param $mailer
* #return void
*/
public function handle(Mailer $mailer)
{
$email = $this->email;
$subject = $this->subject;
$view = $this->view;
$mailer->send($view, $this->data,
function ($message) use ($email, $subject) {
$message->to($email)
->subject($subject);
}
);
}
}
And handle in your controller
use App\Jobs\SendEmail;
public function contactForm(Request $request) {
//TODO Configure Subject
$subjectOwner = 'Your Email Subject For Owner';
$subjectUser = 'Your Email Subject For User';
//TODO Configure Email
$ownerEmail = 'ownerEmail#gmail.com';
$userEmail = 'userEmail#gmail.com';
//TODO Configure Data Email send to email blade viewer
$dataEmail = [
'lang' => 'en',
'user_name' => 'User Name'
];
//emails.owner mean emails/owner.blade.php
//emails.admin mean emails/admin.blade.php
$jobOwner = (new SendEmail($subjectOwner, $dataEmail, "emails.owner" , $ownerEmail))->onQueue('emails');
dispatch($jobOwner);
$jobUser = (new SendEmail($subjectUser, $dataEmail, "emails.admin" , $userEmail))->onQueue('emails');
dispatch($jobUser);
}
And try command
//IF You using Laravel 5.2
php artisan queue:listen --queue=emails
//IF You using Laravel >5.3
php artisan queue:work
I am trying to send mails to multiple recipients,But i got an error like
Swift_RfcComplianceException in MailboxHeader.php line 345: Address in
mailbox given [exmple1#gmail.com, example2#gmail.com,
ex3#gmail.com] does not comply with RFC 2822, 3.6.2.
but the code does however work when I only specify one recipient.
Here is my code:
Controller :
$myEmail='exmple1#gmail.com, exmple2#gmail.com';
$dataArray['name'] ='name';
$dataArray['E_id'] = 011;
$dataArray['password'] = '1234';
$dataArray['username'] = 'test';
Mail::to($myEmail)->send(new HeadMail($dataArray));
HeadMail.php(inside app folder)
public function build() {
$address = 'abc#gmail.com';
$name = 'test TEAM';
$subject = 'USER CREDENTIALS';
return $this->view('emails.index')
->from($address, $name)
->cc($address, $name)
->bcc($address, $name)
->replyTo($address, $name)
->subject($subject)
->with([
'name' => $this->dataArray['name'],
'password' => $this->dataArray['password'],
'E_id' => $this->dataArray['E_id'],
'email' => $this->dataArray['username'],
]);
}
How can I send the email to all recipients?Please help me.
Separate emails with a comma and use a simpler solution. At least, this is what I do:
Mail::send(['blade.view.html', 'blade.view.txt'], ['title' => $subject, 'content' => $content], function ($message) {
$message->from('it#example.com', 'IT Serviss');
$message->to(explode(",", $client_email_array));
$message->subject($subject);
});