How to Implement Email Forword functionality in Laravel 9

142 Views Asked by At

I have store the Gmail inbox in my database and listed on admin panel, now I want to Forword the received mail to another, how to do that in Laravel.

I have use laminas/laminas-mail package to store, send and reply.

Please Provide suitable solution.

2

There are 2 best solutions below

0
lordisp On

Depending on how you recognize, a email has been reseived (eg some sort of events), you could create an (queue) listener and dispatch the mail over:

  1. Register an event and listener in the EventServiceProvider by opening the app/Providers/EventServiceProvider.php file and adding the following code in the listen array:
protected $listen = [
    ReceivedEmailEvent::class => [
        ForwardEmailListener::class,
    ],
];

After registering listeners in your EventServiceProvider, use the event:generate Artisan command to quickly generate listener classes.

  1. Open the app/Events/ReceivedEmailEvent.php file and update its contents with the following code:
<?php

namespace App\Events;

use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;

class ReceivedEmailEvent
{
    use Dispatchable, InteractsWithSockets, SerializesModels;

    public $fromEmail;
    public $subject;
    public $body;

    /**
     * Create a new event instance.
     *
     * @param string $fromEmail
     * @param string $subject
     * @param string $body
     * @return void
     */
    public function __construct($fromEmail, $subject, $body)
    {
        $this->fromEmail = $fromEmail;
        $this->subject = $subject;
        $this->body = $body;
    }
}

  1. Open the app/Listeners/ForwardEmailListener.php file and update its contents with the following code:
<?php

namespace App\Listeners;

use App\Events\ForwardEmailEvent;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Support\Facades\Http;

class ForwardEmailListener implements ShouldQueue
{
    /**
     * Handle the event.
     *
     * @param  ForwardEmailEvent  $event
     * @return void
     */
    public function handle(ReceivedEmailEvent $event)
    {
        $data = [
            'from' => $event->fromEmail,
            'subject' => $event->subject,
            'body' => $event->body,
        ];

        Http::post('/forward-email', $data);
    }
}

  1. Create a controller that does the actual forwarding
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Mail;

class EmailForwardingController extends Controller
{
    public function forward(Request $request)
    {
        // You may want to add some validation, too

        $toEmail = '[email protected]'; // Replace with the email address you want to forward the emails to

        $fromEmail = $request->input('from');
        $subject = $request->input('subject');
        $body = $request->input('body');

        // Forward the email
        Mail::raw($body, function ($message) use ($fromEmail, $toEmail, $subject) {
            $message->from($fromEmail);
            $message->to($toEmail);
            $message->subject($subject);
        });

        return response()->json(['message' => 'Email forwarded successfully']);
    }
}
  1. To use this controller, you need to define a route that points to the forward method of the EmailForwardingController. For example, in your routes/web.php file, you can add the following route:
use App\Http\Controllers\EmailForwardingController;

Route::post('/forward-email', [EmailForwardingController::class, 'forward']);

  1. Now, you can fire the ReceivedEmailEvent event whenever you receive an email. For example, you can add the following code in your controller method that receives the email:
use App\Events\ReceivedEmailEvent;

// ...

public function receiveEmail(Request $request)
{
    // Process the received email

    // Fire the ReceivedEmailEvent
    $fromEmail = $request->input('from');
    $subject = $request->input('subject');
    $body = $request->input('body');

    event(new ReceivedEmailEvent($fromEmail, $subject, $body));

    // Return response
}

This is untested and should give you a rough idea of how you might implement such a solution

0
lordisp On

Another solution might be the job scheduler using an artisan command:

  1. Create a new Laravel command to handle the forwarding of emails. Run the following command to generate the command file:
php artisan make:command ForwardEmails
  1. Open the generated ForwardEmails command file located in app/Console/Commands/ and modify the handle method to include the logic for forwarding emails:
<?php

namespace App\Console\Commands;

use Illuminate\Console\Command;
use Laminas\Mail\Storage\Imap;
use Laminas\Mail\Transport\Smtp;
use Laminas\Mail\Message;

class ForwardEmails extends Command
{
    protected $signature = 'emails:forward';

    protected $description = 'Forward received emails to another address';

    public function handle()
    {
        $imap = new Imap([
            'host'     => 'imap.gmail.com',
            'user'     => '[email protected]',
            'password' => 'your-password',
            'ssl'      => 'ssl',
        ]);

        foreach ($imap as $message) {
            $forwardedMessage = new Message();
            $forwardedMessage->setEncoding('UTF-8');

            $forwardedMessage->addFrom('[email protected]', 'Your Name');
            $forwardedMessage->addTo('[email protected]', 'Recipient Name');

            $headers = $message->getHeaders();

            foreach ($headers as $header) {
                $forwardedMessage->getHeaders()->addHeader($header);
            }

            $forwardedMessage->setSubject('Fwd: ' . $message->getSubject());

            $body = $message->getBody();
            $forwardedMessage->setBody($body);

            $transport = new Smtp([
                'host'              => 'smtp.gmail.com',
                'port'              => 587,
                'connection_class'  => 'login',
                'connection_config' => [
                    'username' => '[email protected]',
                    'password' => 'your-password',
                    'ssl'      => 'tls',
                ],
            ]);

            $transport->send($forwardedMessage);
        }
    }
}

In this example, we're using the Imap class from the laminas-mail package to connect to your Gmail account and retrieve the emails. We then loop through the messages and create a new Message instance for each forwarded email. We copy the necessary headers and content from the original email and send it using the Smtp transport provided by the package.

Note: Replace '[email protected]' with your actual Gmail address, 'your-password' with your Gmail account password, and '[email protected]' with the email address you want to forward the messages to.

You may want to create a configuration file for the credentials and use environment variables, which are ignored from any version control.

  1. Next, register the command in the app/Console/Kernel.php file by adding it to the $commands array:
protected $commands = [
    // Other commands...
    \App\Console\Commands\ForwardEmails::class,
];
  1. You can now schedule the command to run automatically at specific intervals. Open the app/Console/Kernel.php file and locate the schedule method. Add the following code to schedule the ForwardEmails command to run every minute:
protected function schedule(Schedule $schedule)
{
    // Other scheduled tasks...
    $schedule->command('emails:forward')->everyMinute();
}

You can modify the schedule according to your requirements. For more details on scheduling commands in Laravel, refer to the official Laravel documentation.

  1. Finally, to run the scheduled commands, you need to set up the Laravel scheduler. Open the server's crontab by running crontab -e in your terminal and add the following line at the end of the file
* * * * * cd /path/to/your/laravel/project && php artisan schedule:run >> /dev/null 2>&1

If you do not know how to add cron entries to your server, consider using a service such as Laravel Forge which can manage the cron entries for you