I am trying send email verification links to user when they register but I get a message Authentication required and mail isn't sent. I tried using mailtrap for demo and sendgrid which I will be using in production but the message was the same. This is how I a going about it
After running composer require guzzlehttp/guzzle I updated my env file like this
# MAIL_DRIVER=smtp
# MAIL_HOST=smtp.mailtrap.io
# MAIL_PORT=2525
# MAIL_USERNAME=mailtrap_username
# MAIL_PASSWORD=mailtrap_password
# MAIL_ENCRYPTION=tls
MAIL_DRIVER=smtp
MAIL_HOST=smtp.sendgrid.net
MAIL_PORT=587
MAIL_USERNAME=sendgrid_username
MAIL_PASSWORD=sendgrid_password
MAIL_ENCRYPTION=tls
In the controller, I want to send the mail after a user is successfully created like this
...
use App\Mail\VerifyEmail;
...
use Illuminate\Support\Facades\Mail;
public function register(Request $request)
{
// create and store new user record
$user = User::create([
'username' => $request->username,
'password' => bcrypt($request->password)
]);
// send user email verification link
Mail::to($user->username)->send(new VerifyEmail());
}
VerifyMail.php
<?php
namespace App\Mail;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Contracts\Queue\ShouldQueue;
class VerifyEmail extends Mailable
{
use Queueable, SerializesModels;
/**
* Create a new message instance.
*
* #return void
*/
public function __construct()
{
//
}
/**
* Build the message.
*
* #return $this
*/
public function build()
{
$from = 'support#fromus.com';
$name = 'custom name';
$subject = 'Welcome! Confirm Your Email';
return $this->from($from, $name)
->subject($subject)
->view('auth.verify');
}
}
Following the documentation for email verification https://laravel.com/docs/5.8/verification#verification-routing I added the Auth::routes(['verify' => true]) to api.php file like this
<?php
// Register routes for email verification
Auth::routes(['verify' => true]);
Route::prefix('v1')->group(function () {
// protected routes
Route::middleware('auth:api')->group(function () {
Route::get('products', 'ProductController#index'); // get products
});
});
Route::fallback(function () {
return response()->json(['error' => 'Not Found'], 404);
});
Why am I getting the Authentication required error message and how can I fix it?
First i removed Auth::routes(['verify' => true]) from the api.php file and added it in the web.php.
Then I ran php artisan config:cache to cache changes made to the env file. Fixed
Related
I want to create a register/login window with Laravel version 8. When I try to register I get the following error message:
Swift_RfcComplianceException
Address in mailbox given [ee3...] does not comply with RFC 2822, 3.6.2.
MailController:
class MailController extends Controller
{
public static function sendSignupEmail($name, $email, $verification_code){
$data = [
'name' => $name,
'verification_code' => $verification_code
];
Mail::to($email)->send(new SignupEmail($data));
}
}
SignupEmail:
public function __construct($data)
{
$this->email_data = $data;
}
/**
* Build the message.
*
* #return $this
*/
public function build()
{
return $this->from(env('MAIL_USERNAME'), 'website')->subject("Welcome to my Website!")->view('mail.signup-email', ['email_data' => $this->email_data]);
}
.env (To test it I use mailtrap)
MAIL_MAILER=smtp
MAIL_HOST=smtp.mailtrap.io
MAIL_PORT=2525
MAIL_USERNAME=ee3...
MAIL_PASSWORD=ddc...
MAIL_ENCRYPTION=tls
I use xampp v.3.2.4.
The problem is I don't understand the error. I don't have a lot of Laravel/PHP experience but I've done similar things before and it always worked.
Could it be a version conflict?
I am creating realtime chat app.
I have set up pusher in my laravel and vue.js project.
But it doesn't work. Though I don't have any error in the console.
Also, I have no error in network tab.
I need to create messenger app, so I need a realtime chat function.
Now, I can push user's comment but in the other user's window, nothing shows up.
But it does, once I refresh the page. I think my pusher setting has something wrong, because in the pusher debug console, any session is not executed.
Here is my code.
.env
BROADCAST_DRIVER=pusher
CACHE_DRIVER=file
QUEUE_CONNECTION=sync
SESSION_DRIVER=file
SESSION_LIFETIME=120
PUSHER_APP_ID=my id
PUSHER_APP_KEY=my app key
PUSHER_APP_SECRET= my secret key
PUSHER_APP_CLUSTER=mt1
broadcasting.php
'pusher' => [
'driver' => 'pusher',
'key' => env('my key'),
'secret' => env('my secret key'),
'app_id' => env('my id'),
'options' => [
'cluster' => 'ap3',
'encrypted' => true,
],
BroadcastServiceProvider.php
Broadcast::routes(['middleware' => ['auth:api']]);
require base_path('routes/channels.php');
bootstrap.js
import Echo from 'laravel-echo'
window.Pusher = require('pusher-js');
window.Echo = new Echo({
broadcaster: 'pusher',
key: 'my key',
cluster: 'ap3',
encrypted: true
});
NewMessage.php
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
class NewMessage implements ShouldBroadcast
{
use Dispatchable, InteractsWithSockets, SerializesModels;
public $message;
/**
* Create a new event instance.
*
* #return void
*/
public function __construct(Message $message)
{
$this->message = $message;
}
/**
* Get the channels the event should broadcast on.
*
* #return \Illuminate\Broadcasting\Channel|array
*/
public function broadcastOn()
{
return new PrivateChannel('messages.' . $this->message->to);
}
public function broadcastWith()
{
$this->message->load('fromContact');
return ["message" => $this->message];
}
}
routes/channel.php
use Illuminate\Support\Facades\Broadcast;
ContactsController.php
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\User;
use App\Message;
class ContactsController extends Controller
{
public function get() {
$contacts = User::where('id', '!=', auth()->id())->get();//全部のcontactをjson経由でgetする
return response()->json($contacts);
}
public function getMessagesFor($id) {
$messages = Message::where('from', $id)->orWhere('to', $id)->get();
return response() -> json($messages);
}
public function send(Request $request) {
$message = Message::create([
'from' => auth()->id(),
'to' => $request->contact_id,
'text' => $request->text
]);
return response()->json($message);
}
}
Here is what I tried.
run all the command according to the laravel document.
php artisan chache:clear
and run the server again.
run php artisan queue:work
in command terminal
Did you write
window.Echo.private('channelName').listen('EventName',function(e){
})
in your application to listen
In your send() function you should write
broadcast(new NewMessage($message));
to broadcast the message.
So I'm gonna use laravel broadcasting for a chat app,
I followed Laravel Broadcasting approach,
Uncommented App\Providers\BroadcastServiceProvider
from providers array inside config/app.php
Registered in pusher website, made a channel
and filled the fields below inside .env file with my pusher channel info
PUSHER_APP_ID
PUSHER_APP_KEY
PUSHER_APP_SECRET
PUSHER_APP_CLUSTER
Inside my broadcast.php config file where I set the default driver to pusher, I also added
'options' => [
'cluster' => 'us2',
'encrypted' => true,
],
to pusher array inside connections array based on my channel info in pusher panel
Installed pusher php package on my laravel project using composer require pusher/pusher-php-server "~3.0" command
Here is my event class
<?php
namespace App\Events;
use App\User;
use App\TherapyMessage;
use Illuminate\Broadcasting\Channel;
use Illuminate\Queue\SerializesModels;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Broadcasting\PresenceChannel;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use App\AppLog;
use Illuminate\Contracts\Broadcasting\ShouldBroadcastNow;
class TherapyMessageSent implements ShouldBroadcastNow
{
use Dispatchable, InteractsWithSockets, SerializesModels;
/**
* User that sent the message
*
* #var User
*/
public $user;
/**
* Message details
*
* #var Message
*/
public $message;
/**
* Create a new event instance.
*
* #return void
*/
public function __construct(User $user, TherapyMessage $message)
{
$this->user = $user;
$this->message = $message;
}
/**
* Get the channels the event should broadcast on.
*
* #return Channel|array
*/
public function broadcastOn()
{
$message_id = $this->message->id;
$user = $this->user;
AppLog::create([
'file_name' => __FILE__,
'message' => "broadcast before send with Message ID of $message_id from $user->full_name"
]);
return new PrivateChannel("therapy-chat.$message_id");
}
}
The AppLog is a model that I use for logging inside the project
I tried implementing ShouldBroadcast interface at first but that didn't work either
I also registered my event inside EventServiceProvider.php file and run php artisan event:generate command, here is the EventServiceProvider $listen array:
protected $listen = [
Registered::class => [
SendEmailVerificationNotification::class,
TherapyMessageSent::class
],
];
I also imported the event namespace next to other namespaces inside the file:
use \App\Events\TherapyMessageSent;
Here is the channel that I defined inside routes/channels.php file:
use App\AppLog;
Broadcast::channel('therapy-chat.{message_id}', function ($user, $message_id) {
AppLog::create([
'file_name' => __FILE__,
'message' => "broadcast sending with Message ID of $message_id to $user->full_name"
]);
if (!Auth::check()) return false;
$message = \App\TherapyMessage::find($message_id);
if (!$message) {
AppLog::create([
'file_name' => __FILE__,
'message' => "Message with ID of $message_id Not Found for broadcasting"
]);
return false;
}
$will_send = false;
if ($therapist = $user->therapist) {
$will_send = $therapist->id === $message->therapist_id;
} else if ($patient = $user->patient) {
$will_send = $message->patient_id === $patient->id;
}
if ($will_send) {
AppLog::create([
'file_name' => __FILE__,
'message' => "Message with ID of $message_id broadcasted to $user->full_name"
]);
}
return $will_send;
});
Finally, this is my controller method:
public function sendToTherapist(Request $request) {
$validation = \Validator::make($request->all(), ['message' => 'required']);
if ($validation->fails()) return $this->validationError($validation);
$user = \Auth::user();
$patient = $user->patient;
$therapist = $patient->therapist;
if (!$therapist) return $this->errorWithMessage('Patient does not have Therapist');
$message = \App\TherapyMessage::create([
'patient_id' => $patient->id,
'therapist_id' => $therapist->id,
'type' => TherapyMessageType::TEXT,
'text' => $request->message,
'sender_role' => TherapyMessageSenderRole::PATIENT
]);
broadcast(new TherapyMessageSent($user, $message))->toOthers();
return $this->success(['id' => $message->id]);
}
My controller class extends from BaseController which is a custom controller class with helper methods such as success(), validationError() and errorWithMessage()
As you see in the code above
I filled $user and $message with correct values and the request works without any error
I think the channel method won't even be fired,
as I check the AppLog table when I call broadcast method, only the log inside TherapyMessageSent event broadcastOn function is saved
and even the log that I save at the beginning of channels.php method, isn't saved so I think this method is never executed.
If anyone could help me with the problem, I'd be thankful.
I have used markdown mailables which is a new feature in laravel 5.4. I have successfully implemented a mail sender. It seems, the subject of the mail is named as the name of the mailable class. I need to change the subject of the mail and it's hard to find any resources regarding this.
There is subject method in laravel mailables.
All of a mailable class' configuration is done in the build method. Within this method, you may call various methods such as from, subject, view, and attach to configure the email's presentation and delivery. : https://laravel.com/docs/5.4/mail#writing-mailables
You can achieve this like this :
/**
* Build the message.
*
* #return $this
*/
public function build()
{
return $this->from('example#example.com')
->subject('Your Subject')
->markdown('emails.orders.shipped');
}
You may need to execute php artisan view:clear after modifying your class.
If the email subject is the same for all emails then just overload the $subject parameter in your extended Mailable class.
/**
* The subject of the message.
*
* #var string
*/
public $subject;
complete code (tested)
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Mail;
class ContactController extends Controller {
public function sendContactMail(Request $request) {
$this->validate($request, [
'name' => 'required',
'email' => 'required|email',
'subject' => 'required',
'user_message' => 'required'
]);
Mail::send('contact_email',
array(
'name' => $request->get('name'),
'email' => $request->get('email'),
'subject' => $request->get('subject'),
'user_message' => $request->get('user_message'),
), function($message) use ($request)
{
$message->from($request->email );
$message->subject("Your Subject");
$message->to('email to');
});
return back()->with('success', 'Your message was sent successfully');
}
}
I'm using Laravel 4, I would like to change the mail configuration (like driver/host/port/...) in the controller as I would like to save profiles in databases with different mail configuration. This is the basic send mail using configuration from config/mail.php
Mail::send(
'emails.responsable.password_lost',
array(),
function($message) use ($responsable){
$message->to($responsable->email, $responsable->getName());
$message->subject(Lang::get('email.password_lost'));
});
I've tried to put something like but it didn't work
$message->port('587');
Thanks for your support!
Jean
You can set/change any configuration on the fly using Config::set:
Config::set('key', 'value');
So, to set/change the port in mail.php you may try this:
Config::set('mail.port', 587); // default
Note: Configuration values that are set at run-time are only set for the
current request, and will not be carried over to subsequent requests. Read more.
Update: A hack for saving the config at runtime.
I know is kind of late but an approach could be providing a swift mailer to the laravel mailer.
<?php
$transport = (new \Swift_SmtpTransport('host', 'port'))
->setEncryption(null)
->setUsername('username')
->setPassword('secret');
$mailer = app(\Illuminate\Mail\Mailer::class);
$mailer->setSwiftMailer(new \Swift_Mailer($transport));
$mail = $mailer
->to('user#laravel.com')
->send(new OrderShipped);
The selected answer didn't work for me, I needed to add the following for the changes to be registered.
Config::set('key', 'value');
(new \Illuminate\Mail\MailServiceProvider(app()))->register();
If you want to create a Laravel 7 application where users are allowed to register and sign in on your application and you intend to enable each user with the ability to send emails through your platform, using their own unique email address and password.
THE SOLUTION:
Laravel Model: first you’ll need to create a database table to store the user’s email configuration data. Next, you’ll need an Eloquent Model to retrieve an authenticated user’s id to fetch their email configuration data dynamically.
Laravel ServiceProvider: next, create a service provider that would query the database for the user’s email configurations using a scope method within your Model class and would set it as their default mail configuration. Do not register this service provider within your config/app.php
Laravel MiddleWare: also create a middleware that would run when a user has been authenticated and register the ServiceProvider.
IMPLEMENTING THE MODEL:
Make a migration. Run these from the command line php artisan make:migration create_user_email_configurations_table. Then:
Schema::create('user_email_configurations', function (Blueprint $table) {
$table->id();
$table->string('user_id');
$table->string('name');
$table->string('address');
$table->string('driver');
$table->string('host');
$table->string('port');
$table->string('encryption');
$table->string('username');
$table->string('password');
$table->timestamps();
});
Finalize and create your model. Runphp artisan migrate and
php artisan make:model userEmailConfiguration. Now add a scope method into your model.
<?php
namespace App;
use Illuminate\Support\Facades\Auth;
use Illuminate\Database\Eloquent\Model;
class userEmailConfiguration extends Model
{
protected $hidden = [
'driver',
'host',
'port',
'encryption',
'username',
'password'
];
public function scopeConfiguredEmail($query) {
$user = Auth::user();
return $query->where('user_id', $user->id);
}
}
IMPLEMENTING THE SERVICEPROVIDER
Run this from the command line - php artisan make:provider MailServiceProvider
<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use App\userEmailConfiguration;
use Config;
class MailServiceProvider extends ServiceProvider
{
public function register()
{
$mail = userEmailConfiguration::configuredEmail()->first();
if (isset($mail->id))
{
$config = array(
'driver' => $mail->driver,
'host' => $mail->host,
'port' => $mail->port,
'from' => array('address' => $mail->address, 'name' => $mail->name),
'encryption' => $mail->encryption,
'username' => $mail->username,
'password' => $mail->password
);
Config::set('mail', $config);
}
}
public function boot()
{
}
}
IMPLEMENTING THE MIDDLEWARE
Run the following command - php artisan make:middleware MailService
<?php
namespace App\Http\Middleware;
use Closure;
use App;
class MailService
{
public function handle($request, Closure $next)
{
$app = App::getInstance();
$app->register('App\Providers\MailServiceProvider');
return $next($request);
}
}
Now that we’ve implemented all that, register your middleware within your $routedMiddleware array in your kennel.php as mail. Then call it up within your authenticated routes middleware:
Sample:
Route::group(['middleware' => [ 'auth:api' ]], function () {
Route::post('send/email', 'Controller#test_mail')->middleware('mail');
});
Here's my original post over medium -
Enable Unique And Dynamic SMTP Mail Settings For Each User — Laravel 7