I have a laravel 5 app and need to send a reset password link through a service sendinblue. How can I change the core functionality to use sendinblue in PasswordBroker.php?
public function emailResetLink(
CanResetPasswordContract $user,
$token,
Closure $callback = null
) {
$mailin = new Mailin(
'https://api.sendinblue.com/v2.0',
'0TYSSJBSKERNDKW'
);
$view = $this->emailView;
return $this->mailer->send(
$view,
compact('token', 'user'),
function($m) use ($user, $token, $callback)
{
$m->to($user->getEmailForPasswordReset());
if ( ! is_null($callback))
{
call_user_func($callback, $m, $user, $token);
}
});
}
Did you try to add Sendinblue as a mail driver? This github repo can help (https://github.com/agence-webup/laravel-sendinblue)
Here all your emails will be sent by Sendinblue and you will send as a regular mail in Laravel (https://laravel.com/docs/5.1/mail)
If is just for this, you can change the driver just for this kind of mail, i think that you can change the driver on runtime like this
Config::set('mail.driver', 'driver_name');
(new Illuminate\Mail\MailServiceProvider(app()))->register();
Also, you can try to listen to 'mailer.sending' event that is fired just before sending mail messages, but this is not a good approach.
Related
I would like to manually send a password reset request to a specific user (not the one currently logged in) from within a controller. I did some digging around in the Laravel code and I searched many articles but I do not get output.
//...
use Illuminate\Support\Facades\Password;
//...
public function sendResetEmail(Request $request)
{
// I will assueme that you already have $email variable
$response = Password::sendResetLink(['email' => $email], function (Message $message) {
$message->subject($this->getEmailSubject());
});
switch ($response) {
case Password::RESET_LINK_SENT:
dump('We have e-mailed your password reset link!');
case Password::INVALID_USER:
dump('We can\'t find a user with that e-mail address.');
}
}
You can do it using the Password facade
$email = 'example#domain.com';
$response = \Illuminate\Support\Facades\Password::broker()->sendResetLink($email);
$ok = $response == \Illuminate\Support\Facades\Password::RESET_LINK_SENT;
I am using Laravel's "reset password".
There is something particular in our architecture: several accounts can have the same email address, the login is the unique key.
I would like to change the password reset controller so that, in password reset view:
- if the user put its email, the password is set for all accounts with this email (should I do it in a middleware? now only a random account is set, the first one I guess)
- if the user put its login, we change the password of its login only
Do you think this is possible? (for new accounts it will be impossible to create a new account with an existing email, but now we have about 8000 users with double email accounts, so this cannot be changed unfortunately).
thanks a lot in advance for your advices!
here is my code and I don't know where to start
[EDIT]
Here is my code after Mostakim Billah's suggestion:
I rewrote the existing resetPassword et reset function (let them as they were) and added the //HERE part
public function reset(Request $request)
{
$request->validate($this->rules(), $this->validationErrorMessages());
$response = $this->broker()->reset(
$this->credentials($request), function ($user, $password) {
$this->resetPassword($user, $password);
}
);
return $response == Password::PASSWORD_RESET
? $this->sendResetResponse($request, $response)
: $this->sendResetFailedResponse($request, $response);
}
protected function resetPassword($user, $password)
{
$user->password = Hash::make($password);
$user->setRememberToken(Str::random(60));
$user->save();
// HERE: set passwords for other users with the same email
**User::where('email', $user->email)
->where('login', '!=', $user->login)
->where('password', null)
->update(['password' => Hash::make($password)]);**
event(new PasswordReset($user));
$this->guard()->login($user);
}
You can override reset method(which is in ResetsPasswords trait) in ResetPasswordController class and do whatever you want in this method.
I am developing a Laravel application. I am doing unit testing to my application. Now I am having a trouble with testing the verification process.
What I am trying to do now is that I am registering a user, then test if the verification email is sent, then I will get the verification link for that registration, then I will do something with that link.
The first issue is that the email is not sent.
The second issue is that I do not know how to retrieve the
verification email link?
This is my test
public function test_user_can_be_verified_and_redirected_based_on_role()
{
Notification::fake();
$user = $this->registerUser();
Notification::assertSentTo($user, SendEmailVerificationNotification::class);
}
protected function registerUser()
{
$user = factory(User::class)->make();
$this->post(route('register'), [
'name' => $user->name,
'email' => $user->email,
'password' => 'testing',
'password_confirmation' => 'testing',
])->assertRedirect();
return User::whereEmail($user->email)->first();
}
But the issue is that the notification is not sent even if it is sent when I register from the browser. I also like to retrieve the verification link and do something. How can I do that?
Not a perfect solution but it does the trick, if somebody breaks this functionality somehow I'll know about it. :)
First overwrite the protected method verificationUri of the VerifyEmail notification and make it public
class EmailVerificationNotification extends VerifyEmail
{
public function verificationUrl($notifiable) {
return parent::verificationUrl($notifiable);
}
}
Then use it to generate a link and assert against it..
/** #test */
public function an_user_can_verify_his_email_address()
{
$notification = new EmailVerificationNotification();
$user = factory(User::class)->create(['email_verified_at' => null]);
$uri = $notification->verificationUrl($user);
$this->assertSame(null, $user->email_verified_at);
$this->actingAs($user)->get($uri);
$this->assertNotNull($user->email_verified_at);
}
A verification URL can be generated outside of the VerifyEmail notification easily by simply running:
$verificationUrl = URL::temporarySignedRoute(
'verification.verify',
now()->addMinutes(60),
['id' => $user->id, 'hash' => sha1($user->email)]
);
No need to make the verificationUrl() method public.
Here is my solution:
public function testVerifyEmailValidatesUser(): void
{
// VerifyEmail extends Illuminate\Auth\Notifications\VerifyEmail in this example
$notification = new VerifyEmail();
$user = factory(User::class)->create();
// New user should not has verified their email yet
$this->assertFalse($user->hasVerifiedEmail());
$mail = $notification->toMail($user);
$uri = $mail->actionUrl;
// Simulate clicking on the validation link
$this->actingAs($user)
->get($uri);
// User should have verified their email
$this->assertTrue(User::find($user->id)->hasVerifiedEmail());
}
when i am trying to send Mail through Contact Us Form receiving this Error
"Address in mailbox given [] does not comply with RFC 2822, 3.6.2."
I try search to find solution but I cannot find one. I edited config/mail.php
public function sendContactInfo(ContactMeRequest $request)
{
$data = $request->only('name', 'email');
$emailto="******#gmail.com";
$data['messageLines'] = explode("\n", $request->get('message'));
Mail::send('publicPages.contactus', $data, function ($message) use ($emailto) {
$message->subject('Contact Us Form: ')
->to(config('blog.contact_email'))
->replyTo($data['email']);
});
return back()
->withSuccess("Thank you for your message. It has been sent.");
}
with configuration file
i am following this tutorial
Laravel Send Mail
use $data['email']
Mail::send('publicPages.contactus', $data, function ($message) use ($emailto,$data['email']) {
$message->subject('Contact Us Form: ')
->to(config('blog.contact_email'))
->replyTo($data['email']);
});
I'm using the authentication included with laravel 5.2
I have a problem at reset password form.
When I submit email, it returns this error:
Call to a member function getEmailForPasswordReset() on null
I found this cause by the following code:
$user->getEmailForPasswordReset()
the $user is null
In addition, I try to change Illuminate\Auth\Passwords\PasswordBroker at function emailResetLink
return $this->mailer->send($view, compact('token', 'user'), function ($m) use ($user, $token, $callback) {
$m->to($user->getEmailForPasswordReset());
if (! is_null($callback)) {
call_user_func($callback, $m, $user, $token);
}
});
I change: compact('token', 'user') -> ['token'=>$token, 'user2'=>$user]
And $user->getEmailForPasswordReset() -> $user2->getEmailForPasswordReset()
It works well!
Can you help me figure out what I did wrong?
Thanks.
The problem is definitely not in laravel files, so stop looking there and messing with the code, because you risk breaking more stuff than you will fix and also it will be overwritten once you do composer update.
The $user is null because the system cannot find the user you want to send a password reset link to. It would be more helpful to see your controller that implements the password resetting (submitting). Laravel comes with a pretty good starting point and you should not overengineer it unless needed: https://laravel.com/docs/5.2/authentication#resetting-routing
So the method for sending reset links would look something like this:
public function postEmail(Request $request)
{
$this->validate($request, ['email' => 'required|email']);
$response = Password::sendResetLink($request->only('email'), function (Message $message) {
$message->subject($this->getEmailSubject());
});
switch ($response) {
case Password::RESET_LINK_SENT:
return redirect()->back()->with('message', 'Password reset link sent');
case Password::INVALID_USER:
return redirect()->back()->with('message', 'User not found');
}
}
As you see there's no User objects involved for you to handle.