What is the best way to sent out email in Laravel 5? - php

I have a problem sending out email in my Laravel 5 Application.
Here is my mail function
email = test#gmail.com
Mail::send('emails.activation', array(
'username'=>$user->username,
'name'=>$user->name,
'code'=>$user->code,
'email'=>$user->email
),
function($message){
$message->from(env('MAIL_USERNAME'),'Site');
$message->to('email', 'name' )->subject('Site Activation ');
});
I keep getting
Update
Mail Configuration in .env file
MAIL_DRIVER=smtp
MAIL_HOST=smtp.gmail.com
MAIL_PORT=465
MAIL_USERNAME=donotreply#site.com
MAIL_PASSWORD=***********
New Error
I'm very curios on what is going on.
What did I do wrong ?

This means there is something wrong in email address fields such as From, Sender or Reply-To fields.
Swift Mailer strictly follow RFC standard to avoid emails being caught by spam checker tools.
test#gmail.com doesn't look like a normal email address or does not even exist.
Try with a different email address example send to me
Mail::send('emails.activation', array(
'username'=>$user->username,
'name'=>$user->name,
'code'=>$user->code,
'email'=>$user->email
),
function($message){
$message->from('siteEmailaddress#domain.com'),'Site');
$message->to('avalidEmailaddress#domain.com', 'name' )->subject('Site Activation ');
});
Also if you wish to use gmail as SMTP server below:
'driver' => 'smtp',
'host' => 'smtp.gmail.com',
'port' => 465,
'encryption' => 'ssl',
'username' => 'your-email#gmail.com',
'password' => 'your-password',
EDITED
NB: MAIL_USERNAME must be your #gmail.com email address e.g. myname#gmail.com else you will get Connection could not be established with host smtp.gmail.com error
To handle this exception if you can't resolve it, go to open app\Exceptions\handler.php
add this inside render method:
/**
* Render an exception into an HTTP response.
*
* #param \Illuminate\Http\Request $request
* #param \Exception $e
* #return \Illuminate\Http\Response
*/
public function render($request, Exception $e)
{
if ($e instanceof Swift_RfcComplianceException){
//redirect to form
//You can also delete the user account here if already created or do other stuffs
return redirect($request->fullUrl())->with('error',"We have issue sending you an email");
}
.......
}
NB: Remember to add use Swift_RfcComplianceException; at the top of handler.php

It looks like the 'from' address is not valid, you're using an env call currently without knowing 100% what it returns.
Try changing the from address to a real email address for testing purposes.

Related

Email verification does not seem to be sending anymore

I want to send email verification when a user signs up with a new Email Address. So at the Register Controller I added this:
public function register(Request $request)
{
if(Session::has('email')){
return Redirect::back()->withErrors(['msg' => 'Email was already sent to you, please check the spam folder too.']);
}else{
$validatedEmail = $request->validate([
'user_input' => 'required|unique:users,usr_email|regex:/(.+)#(.+)\.(.+)/i|max:125|min:3',
],[
'user_input.required' => 'You must enter this field',
'user_input.unique' => 'This email is already registered',
'user_input.regex' => 'This email is not correct',
'user_input.max' => 'Maximum length must be 125 characters',
'user_input.min' => 'Minimum length must be 3 characters',
]);
$register = new NewRegisterMemberWithEmail();
return $register->register();
}
}
So if the email was valid, it will call a helper class NewRegisterMemberWithEmail which goes like this:
class NewRegisterMemberWithEmail
{
public function register()
{
try{
$details = [
'title' => 'Verify email'
];
Mail::to(request()->all()['user_input'])->send(new AuthMail($details));
Session::put('email',request()->all()['user_input']);
return redirect()->route('login.form');
}catch(\PDOException $e){
dd($e);
}
}
}
So it used to work fine and correctly sends the email for verification, but I don't know why it does not send email nowadays.
In fact I have tested this with different mail service providers and for both Yahoo & Gmail the email did not received somehow!
But for local mail service provider based in my country the email was sent properly!
I don't know really what's going on here because the logic seems to be fine...
So if you know, please let me know... I would really really appreciate any idea or suggestion from you guys.
Also here is my AuthMail Class if you want to take a look at:
class AuthMail extends Mailable
{
use Queueable, SerializesModels;
public $details;
/**
* Create a new message instance.
*
* #return void
*/
public function __construct($details)
{
$this->details = $details;
}
/**
* Build the message.
*
* #return $this
*/
public function build()
{
return $this->subject('Sitename')->view('emails.AuthMail');
}
}
Once I was faced same problem when I was used Gmail as smtp.
Reason:
when we used our Gmail password directly in smtp settings then due to some Gmail policies it'll be blocked after sometime (months) and stopped email sending.
Solution:
we need to create an app-password from our Gmail security and use that password in smtp settings. below google article will guide:
How to create app-password on gmail
.env smtp setting for laravel:
MAIL_MAILER=smtp
MAIL_HOST=smtp.gmail.com
MAIL_PORT=587
MAIL_USERNAME=<your-email>
MAIL_PASSWORD=<app-password>
MAIL_ENCRYPTION=tls
I hope that'll help you.
If you use google mail to send email then we have the same problem.
On May 30, 2022 Google stop supporting less secure applications or third party application.
This is I think the reason why your send mail does not work (consider this answer if you use google mail as mail sender)
I was having issues when sending email, especially to gmail accounts. So I have changed my approach and overcome that issue.
Please check my answer below
Laravel Email
Example Mail Class
<?php
namespace App\Mail;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
use Symfony\Component\Mime\Email;
class OrderInfoMail extends Mailable
{
use Queueable, SerializesModels;
/**
* Create a new message instance.
*
* #return void
*/
public $data;
public function __construct($data)
{
$this->data = $data;
}
/**
* Build the message.
*
* #return $this
*/
public function build()
{
$this
->subject('Order Confirmation')
->from('noreply#app.xxx.co.uk', 'XXX Portal')
->view('orders.templates.order-form')
->with([
'name' => $this->data->name,
'sales_representative_name' => $this->data->sales_representative_name,
'sales_representative_phone' => $this->data->sales_representative_phone,
"items" => $this->data->items,
"address" => $this->data->address,
"net" => $this->data->net,
"payment" => $this->data->payment,
"balance" => $this->data->balance,
]);
$this->withSymfonyMessage(function (Email $message) {
$message->getHeaders()->addTextHeader(
'X-Mailer', 'PHP/' . phpversion()
);
});
return $this;
}
}
Usage
$email = 'a#b.com'; // pls change
$name = 'ab';// pls change
$data = new \stdClass();
$data->name = $name;
$data->sales_representative_name = \App\User::find(Auth::user()->id)->name;
$data->sales_representative_phone = \App\User::find(Auth::user()->id)->phones->first()->number;
$data->items = $order_items;
$data->address = $address;
$data->net = $net;
$data->payment = $payment;
$data->balance = $balance;
Mail::to($email)->send(new \App\Mail\OrderInfoMail($data));
I don't think the issue is your code. I think it is related to you sending practices. A solution is to use a service that is designed to send emails like SparkPost (full disclosure I work for SparkPost). There are many others. These services can help you make sure you are following email best practices.
You can make this work without an email service but at the very least you should verify you are following the best practices presented by MAAWG: https://www.m3aawg.org/published-documents

How to make users send mails with it's SMTP in laravel [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 1 year ago.
Improve this question
I need to make users send emails with it's own SMTP Data in laravel
i tried to set the new env variables of SMTP like this
env('MAIL_USERNAME', $smtp->smtp_username);
and tried this also
config(['MAIL_USERNAME' => $smtp->smtp_username]);
and nothing updated
then tried to set the SMTP data in mail.php
but i got errors while deploying
This works at least in laravel 8+ and not overide default mailer nor config (so no problem with cache)
<?php
namespace App\Services;
use Illuminate\Mail\Mailer;
use Swift_Mailer;
use Swift_SmtpTransport;
class CustomMailer
{
private array $config;
public function __construct(array $config)
{
$this->config = $config;
}
public function make(): Mailer
{
$transport = (new Swift_SmtpTransport($this->getConfigValue('host'), $this->getConfigValue('port')))
->setEncryption($this->getConfigValue('encryption'))
->setUsername($this->getConfigValue('username'))
->setPassword($this->getConfigValue('password'));
$mailer = new Mailer(
'customMailer',
app()->get('view'),
new Swift_Mailer($transport),
app()->get('events')
);
$mailer->alwaysFrom(
$this->getConfigValue('from_email', $this->getConfigValue('username')),
$this->getConfigValue('from_name', $this->getConfigValue('username')),
);
return $mailer;
}
private function getConfigValue(string $key, mixed $default = null): mixed
{
return data_get($this->config, $key, $default);
}
}
#Usage
(new CustomMailer([
'host' => '****',
'port' => 465,
'encryption' => 'ssl',
'username' => '****',
'password' => '****',
]))
->make()
->to('****#***.**')
->send(new someEmail());
This worked for me.
// backup mailing configuration
$backup = Mail::getSwiftMailer();
// set mailing configuration
$transport = new Swift_SmtpTransport(
getUserActiveEmailDetails()->host,
getUserActiveEmailDetails()->port,
getUserActiveEmailDetails()->encryption
);
$transport->setUsername(getUserActiveEmailDetails()->username);
$transport->setPassword(getUserActiveEmailDetails()->password);
$maildoll = new Swift_Mailer($transport);
// set mailtrap mailer
Mail::setSwiftMailer($maildoll);
Mail::send('testing.mail', [], function($message)
{
$message->from(getUserActiveEmailDetails()->from)
->to(org('test_connection_email'),
Str::ucfirst(activeEmailService()) . ' Test Connection')
->subject(Str::ucfirst(activeEmailService()) . ' Test
Connection');
});
// reset to default configuration
Mail::setSwiftMailer($backup);
This is definitely the wrong approach in my opinion. You can't set env or config dynamically and you would also overwrite it for every single user in the page. Also queuing mail is not possible that way..
Have a look at this:
https://laravel-news.com/allowing-users-to-send-email-with-their-own-smtp-settings-in-laravel
This seems like a pretty complete approach to get what you need.

Laravel Notifications not sending

I set up a contact form which sends an email on completion using Laravel notifications, however it doesn't look like anything is being sent.
ROUTES
Route::post('/contact', 'ContactController#store');
CONTROLLER
public function store()
{
request()->validate([
'name' => 'required|max:255',
'email' => 'required|email|unique:contacts|max:255',
'message' => 'required|max:2000',
]);
$contact = Contact::create(
request()->only([
'name',
'email',
'message',
])
);
User::first()->notify(new SendContactNotification($contact));
return back()->with('success', 'Thank you, I will be in touch as soon as I can');
}
NOTIFICATION
protected $contact;
public function __construct($contact)
{
$this->contact = $contact;
}
public function toMail($notifiable)
{
return (new MailMessage)
->line($this->contact->name)
->line($this->contact->email)
->line($this->contact->message);
}
I do get the success message when I run it. However, nothing appears in my Mailtrap. Here's the mail section of the sanitised .env file:
MAIL_DRIVER=smtp
MAIL_HOST=smtp.mailtrap.io
MAIL_PORT=2525
MAIL_USERNAME=username
MAIL_PASSWORD=password
MAIL_ENCRYPTION=null
MAIL_FROM_ADDRESS='admin#test.com'
MAIL_FROM_NAME='admin'
I can't see what I have done wrong. I also tried type hinting the contact in the notification like so:
public function __construct(Contact $contact)
{
$this->contact = $contact;
}
That didn't work unfortunately. I also thought it might be something to do with my computer not being set up to send emails using php, but I was under the impression that the env file would take care of that.
The contacts are being stored in the database ok, but no emails are being sent. Would anyone be able to help?
It was the port in the env file, I changed it to:
MAIL_PORT=465
and it worked!
I knew port 2525 wasn't working because of this answer: https://stackoverflow.com/a/45418259/5497241

Override Auth Forgot Password in Laravel 5.3

I am using built in laravel auth functionality.Its working fine.I am trying to override following two functionality.
1.send forgot password email using mandrill.
2.send verification email while registering account.
Can any one help me to solve this issue
My aim is to use mandril instead of default email
I can see auth built in methods but i didnt got idea how i can override that
trait ResetsPasswords
{
use RedirectsUsers;
/**
* Display the password reset view for the given token.
*
* If no token is present, display the link request form.
*
* #param \Illuminate\Http\Request $request
* #param string|null $token
* #return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
*/
public function showResetForm(Request $request, $token = null)
{
return view('auth.passwords.reset')->with(
['token' => $token, 'email' => $request->email]
);
}
/**
* Reset the given user's password.
*
* #param \Illuminate\Http\Request $request
* #return \Illuminate\Http\Response
*/
public function reset(Request $request)
{
$this->validate($request, $this->rules(), $this->validationErrorMessages());
// Here we will attempt to reset the user's password. If it is successful we
// will update the password on an actual user model and persist it to the
// database. Otherwise we will parse the error and return the response.
$response = $this->broker()->reset(
$this->credentials($request), function ($user, $password) {
$this->resetPassword($user, $password);
}
);
// If the password was successfully reset, we will redirect the user back to
// the application's home authenticated view. If there is an error we can
// redirect them back to where they came from with their error message.
return $response == Password::PASSWORD_RESET
? $this->sendResetResponse($response)
: $this->sendResetFailedResponse($request, $response);
}
As answered by Mahfuzal, Laravel comes with a bunch of mail drivers out of the box. So just update your .env file to use the right driver.
As for sending a verification email when creating an account, you just need to override the postRegister() function inside the Auth/AuthController like so:
public function postRegister(Request $request)
{
$validator = $this->validator($request->all());
if ($validator->fails()) {
$this->throwValidationException(
$request, $validator
);
}
$confirmation_code = str_random(30);
$newUser = new User;
$newUser->username = $request->username;
$newUser->email = $request->email;
$newUser->password = bcrypt($request->password);
$newUser->confirmation_code = $confirmation_code;
$newUser->save();
$data = array('confirmation_code' => $confirmation_code, 'username' => $request->username);
Mail::send('emails.verify', $data, function ($message) use ($newUser){
$message->to($newUser->email, $newUser->username);
$message->subject('Please verify your email address');
});
return redirect('/auth/login');
}
This will execute the above code when registering a user rather than what Laravel does default out of the box so just tweak it to your needs.
You then just need to create a function that will check the token and verify their account when they click the link. For that, I use something similar to what is explained here.
Laravel provides drivers for SMTP, Mailgun, Mandrill, Amazon SES,
PHP's mail function, and sendmail, allowing you to quickly get started
sending mail through a local or cloud based service of your choice.
Open your .env file and change following by your Mandrill credentials and then you're good to go.
MAIL_DRIVER=mandrill
MAIL_HOST=
MAIL_PORT=2525
MAIL_USERNAME=null
MAIL_PASSWORD=null
MAIL_ENCRYPTION=null
You can create your own reset method in the controller that uses the trait to override the method in the trait.

PHP Laravel 5 User class properties not accessible for sending Email after account creation

I have a problem where I can't put in the variables into the Mail::send() function in laravel. Please see the following code:
$first_name = $request->input('first_name'),
$email = $request->input('email'),
//Create account
User::create([
'first_name' => $first_name,
'last_name' => $request->input('last_name'),
'email' => $email,
'password' => bcrypt($request->input('password')),
]);
//Send email to user
Mail::send('emails.test', ['fname' => $first_name], function($message)
{
$message->to($email)
->subject('Welcome!');
});
return redirect()
->route('home')
->with('info', 'Your account has been created and an authentication link has been sent to the email address that you provided. Please go to your email inbox and click on the link in order to complete the registration.');
For some reason the code breaks when it gets to the send email because I receive the error and the data is sent to the database. Why is the variable no longer accessible afterwards?
Any help would be greatly appreciated. Thank you
Closures may also inherit variables from the parent scope. Any such variables must be passed to the use language construct.
Source: http://php.net/manual/en/functions.anonymous.php
In other words, $email has to be inherited like this:
Mail::send('emails.test', ['fname' => $first_name], function($message) use ($email)
{
$message->to($email)
->subject('Welcome!');
});
Note: use ($email) in the first line.

Categories