In this Post “Laravel 12 cron job task scheduling example using email” ,I will show you how to schedule task to send email daily at specific time using cron job in laravel 12 application.
In modern web applications, automation is key. Task scheduling allows you to automatically execute repetitive tasks like sending emails, generating reports, or cleaning up databases. Laravel simplifies task automation with its built-in scheduler.
Step for Laravel 12 Cron Job Task Scheduling Example Tutorial Using Email
- Step 1: Install Laravel 12
- Step 2: Configure Mail Settings
- Step 3: Create Mailable Class
- Step 4: Create a Custom Command
- Step 5: Schedule The Task
- Step 6: Run Scheduler Command Manually For Testing
- Step 7: Laravel 12 Setup Cron Job On Server
Step 1: Install Laravel 12
To get started, you’ll need a Laravel project. If you already have one set up, you can skip this step. Otherwise, run the following command in your terminal to create a new Laravel project:
composer create-project laravel/laravel laravel-12-cron-job-task-scheduling-example-tutorial
Prerequisites
- Laravel 12 or 11 any version project installed
- Basic understanding of Artisan commands
- Mail configuration set up
Step 2: Configure Mail Settings
Open your .env file and add the mail configuration. if you’d like a detailed guide on sending emails in Laravel using Gmail SMTP, click here. Below is an example configuration for Gmail SMTP:
MAIL_MAILER=smtp
MAIL_SCHEME=null
MAIL_HOST=smtp.gmail.com
MAIL_PORT=587
MAIL_USERNAME=your_gmail_username@gmail.com
MAIL_PASSWORD=spvaxqyulyqumrxh
MAIL_FROM_ADDRESS="your_gmail_username@gmail.com"
MAIL_FROM_NAME=itstuffsolutions
Step 3: Create Mailable Class
Use the command below in your terminal to create a SendNewsletterMail class within the App\Mail folder.
php artisan make:mail SendNewsletterMail
To send newsletters to all users, we use the SendNewsletterMail class. It takes a users object through its constructor and sets the email view in the content() method.
<?php
namespace App\Mail;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Mail\Mailable;
use Illuminate\Mail\Mailables\Content;
use Illuminate\Mail\Mailables\Envelope;
use Illuminate\Queue\SerializesModels;
class SendNewsletterMail extends Mailable
{
use Queueable, SerializesModels;
public $users;
/**
* Create a new message instance.
*/
public function __construct($users)
{
$this->users = $users;
}
/**
* Get the message envelope.
*/
public function envelope(): Envelope
{
return new Envelope(
subject: 'Send Newsletter Mail',
);
}
/**
* Get the message content definition.
*/
public function content(): Content
{
return new Content(
view: 'newsletter_mail',
);
}
/**
* Get the attachments for the message.
*
* @return array<int, \Illuminate\Mail\Mailables\Attachment>
*/
public function attachments(): array
{
return [];
}
}
Step 4: Create a Custom Command
To send emails at a specific time in Laravel, you need to create a custom Artisan command. This command will be executed through Laravel’s task scheduling using a cron job. Run the following command to generate the SendEmailCron file inside the App\Console\Commands directory.
php artisan make:command SendEmailCron --command=send:email
Open App\Console\Commands\SendEmailCron.php , Add code to send email
Open the App\Console\Commands\SendEmailCron.php file and add the code to send emails inside the handle() method. In this method, I fetched user data from the User model and used a foreach loop to send the newsletter to each user individually.
<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
Use App\Models\User;
use Illuminate\Support\Facades\Mail;
use App\Mail\SendNewsletterMail;
class SendEmailCron extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'send:email';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Newsletter Sent to Subscribers Daily at 1:00 AM';
/**
* Execute the console command.
*/
public function handle()
{
$users = User::select('email','name','content')->get();
foreach($users as $u){
Mail::to($u->email)->send(new SendNewsletterMail($u));
info('Mail send Successfully '.$u->email);
}
}
}
To send the newsletter email, create a Blade template at resources/views/newsletter_mail.blade.php. This file contains a basic HTML layout for the email content.
Copy and use this code into your newsletter_mail.blade.php file.
<!DOCTYPE html>
<html>
<head>
<title>Newsletter</title>
</head>
<body>
<h1>Hello, {{$users->name}}</h1>
<p>
{!! $users->content !!}
</p>
<p>Regards,<br>{{ config('app.name') }}</p>
</body>
</html>
Step 5: Schedule The Task
In this step, we will learn how to schedule a command in Laravel. Open routes/console.php, remove or comment the existing code, and add the following code to define schedule tasks using the schedule method:
<?php
use Illuminate\Support\Facades\Schedule;
Schedule::command('send:email')->dailyAt("1:00");
In the example code, we’ve used the ->dailyAt(‘1:00’) method, which schedules the task to run every day at 1:00 AM. Laravel provides a variety of expressive methods to define task frequency. For instance:
- Use ->everyMinute() to execute the task every minute.
- Use ->weekly() to run the task once a week—by default, this runs every Sunday at midnight (00:00).
- Use ->twiceDaily(1, 13) to schedule the task twice daily, at 1:00 AM and 1:00 PM.
Laravel’s scheduler includes many more options like ->hourly(), ->monthly(), ->quarterly(), ->yearly(), and even granular ones such as ->everyTwoMinutes() or –>everySecond() .
For a complete list of available scheduling methods, refer to the official Laravel task scheduling documentation.
Read Also : How to Create Middleware with Parameters in Laravel 12
Step 6: Run Scheduler Command Manually For Testing
All the steps have been completed. Now you can manually test the cron job by executing the command given below.
php artisan schedule:run
The output is look like this :

We have used the info() function to print the message to the log file. Open storage/logs/laravel.log to see the printed message, which looks like this:

Step 7: Laravel 12 Laravel 12 Setup Cron Job On Server
In this step we will see how to setup cron job on server
1. Go To Your Laravel Project Path
First, find the full path to your Laravel project.For example, your Laravel path might be:
/var/www/html/laravel-project
2. Open the Crontab File
Open the crontab configuration for the current user:
crontab -e
If it’s your first time, it may ask you to select an editor. Choose nano for simplicity.
3. Add Laravel’s Scheduler Cron Entry
Add the following line to the bottom of the file:
* * * * * cd /full-path-to-your-project && php artisan schedule:run >> /dev/null 2>&1
Replace /full-path-to-your-project with your actual Laravel project path. For example:
* * * * * cd /var/www/home/laravel-12-cron-job-task-scheduling && php artisan schedule:run >> /dev/null 2>&1
Source Code / Demo Link
GitHub repo or download link for readers.
Conclusion
Scheduling emails in Laravel 12 is straightforward with the framework’s built-in task scheduler and a simple cron entry. By configuring mail in .env, creating a Mailable, building a custom Artisan command, and registering it with expressive schedule methods like dailyAt(‘1:00’), automated email workflows can run reliably without manual triggers. Local testing via php artisan schedule:run confirms behavior before production deployment, while a single crontab line ensures the scheduler runs every minute to evaluate due tasks. With clear structure—Mailable for content, Command for orchestration, and Scheduler for timing—this approach scales from simple newsletters to complex periodic jobs with minimal boilerplate.
Frequently Asked Questions (FAQs)
Q1: How can I monitor or debug scheduled tasks?
Start by checking the storage/logs/laravel.log file. You can also add info() or Log::debug() statements inside your commands to track what’s happening. For deeper visibility, consider using external monitoring tools to watch cron exit codes and scheduler status. Some developers even use dedicated monitoring services to keep an eye on scheduled tasks.
Q2: Do I still need system cron if I use Laravel’s scheduler?
Yes. A single system cron entry is still required to trigger Laravel’s scheduler every minute (unless using a managed platform that runs it for you).
Q3: How do I run a scheduled task for different environments or time zones?
Use timezone() on the schedule definition and environment-specific conditionals, or configure the app timezone (config/app.php) so tasks run at intended local times.
Q4: What happens to sub-minute tasks during deployments?
Because schedule:run persists for the whole minute when sub-minute tasks are defined, deployments should include schedule:interrupt to avoid running old code until the minute ends.
Q5: Is there a way to run schedules without crontab (locally or in containers)?
When working locally, you can run scheduled tasks with php artisan schedule:work (available in Laravel 11+) or run schedule:run in a loop using a process manager. In containerized setups, the common approach is to use a sidecar or worker container that either runs schedule:run every minute or keeps schedule:work running continuously.
Q6: Can Laravel schedule tasks more frequently than once per minute?
Yes. Laravel allows sub-minute scheduling with methods like everySecond() and everyTenSeconds(). In this mode, the schedule:run command keeps running for the full minute to trigger those shorter intervals. For heavier workloads, it’s best to push the actual processing into queued jobs or background commands so the scheduler itself stays lightweight.
Q7: How do I stop or interrupt an in-progress schedule:run during deployment?
Invoke php artisan schedule:interrupt at the end of deployment to stop a long-running schedule:run so new code takes effect immediately.
Q8: How do I prevent overlapping task executions?
Chain withoutOverlapping() on scheduled commands or closures to ensure a second instance won’t start if the previous run is still executing.
Q9: What’s the recommended way to handle heavy or slow email jobs?
Queue Mailables (implements ShouldQueue) and schedule queued jobs via Schedule::job(…), or use runInBackground() on commands to avoid blocking the scheduler loop.
Q10: Can I control timing precisely (daily at 1:00, twice daily, weekly, cron syntax)?
Yes. Use helpers like dailyAt(’01:00′), twiceDaily(1, 13), weekly(), hourly(), or cron(‘* * * * *’) for custom expressions; Laravel offers many frequency methods to match scheduling needs.
Q11: Why does schedule:run log output but emails aren’t sent?
Common issues include missing mail configuration or environment values, running the app in a different timezone than expected, misconfigured queues when using ShouldQueue, or not dispatching tasks to the background. To fix this, check your mail settings, confirm the application timezone, and ensure queue workers are running if needed.