Capture new Email event in PHP-IMAP in laravel - php

I want to fetch all emails in inbox and store them in realtime but the way i m doing it is a little bit wrong :
it's something like this:
class Kernel extends ConsoleKernel
...
$schedule->call(function () {
// connect using credentials
//get all emails
//copy emails
//delete emails when they get copied correctly
})->everyMinute(); // repeat
this Guarantees that the emails in the database will not be copied because the emails are no longer in the inbox .
But now we have a case where we need to keep these messages so we replaced this with :
// connect using credentials
//get all emails
//filter only unseen
//copy emails
//mark these emails as seen
But the problem of all of these solution is that we get emails .
The solution we did is working but added another problem of reloading same emails over and over .
I reread the Documentation and found this
possible solution :
Using events that triggers in the entire package and capture the new event witch gets triggered when a new email is received.
In this example i found some useful methods and classes .
class CustomMessageNewEvent extends Webklex\PHPIMAP\Events\MessageNewEvent {
/**
* Create a new event instance.
* #var \Webklex\PHPIMAP\Message[] $messages
* #return void
*/
public function __construct($messages) {
$this->message = $messages[0];
echo "New message: ".$this->message->subject."\n";
}
}
But i m not sure how to implement them in Laravel , juste where and how should i register / capture this `new` Event !
**Especially that we have multiple Client instances not only one ( foreach user ... )**
Thank you so much for reading all this and hopefully people find this question useful.

When I've done similar tasks in the past I've used the Message-ID defined in the email spec to identify each email uniquely.
You can use your IMAP library to get a list of emails with their Message-IDs, then compare those Message-IDs to your database. Just make sure you add a new field to your Email model (or whatever you've called it) to store the Message-ID.

Related

How to customize my Laravel email verification message

during the conception of my web site using laravel 7 I found some troubles when I wanted to customize my laravel customize my Laravel email verification message.
first, I went to this file "C:\xampp\htdocs\clinique_juridique\vendor\laravel\framework\src\Illuminate\Auth\Notifications\VerifyEmail.php",then i translate the sentences that are there .
Here I met two issues, the first one some sentences are not in VerifyEmail.php so I couldn't translate them the second one, I didn't know how to change the style of the message, of course, also I didn't know how to include the logo of my website.
thank you in advance.
So I think you're asking about this specific part of the code (took from Laravel 8 vendor code):
/**
* Build the mail representation of the notification.
*
* #param mixed $notifiable
* #return \Illuminate\Notifications\Messages\MailMessage
*/
public function toMail($notifiable)
{
$verificationUrl = $this->verificationUrl($notifiable);
if (static::$toMailCallback) {
return call_user_func(static::$toMailCallback, $notifiable, $verificationUrl);
}
return (new MailMessage)
->subject(Lang::get('Verify Email Address'))
->line(Lang::get('Please click the button below to verify your email address.'))
->action(Lang::get('Verify Email Address'), $verificationUrl)
->line(Lang::get('If you did not create an account, no further action is required.'));
}
First, you may use this class VerifyEmail and method toMail to send this confirmation email to your client, but if you look closer, you can identify that this function is using the Lang class, which can be found at Laravel Localization.
Otherwise, if you want to make it more complex you can create your own class MyVerifyEmail which extends VerifyEmail and recreate toMail method to serve your needs, but I can't think of a scenario where you do this.
Second, if you want to include some personalized style of your mail, try creating a Mailable, with this approach you can use a custom view (of course including a logo).
And finally, I encourage to do not to modify the vendor's directory, because it stores all the libraries that laravel needs to work properly. Instead, extend any class which you may want to modify.

Mautic hook is not called (ON_SENT_EMAIL_TO_USER)

I am writing a plug-on that should add an (dynamic) attachment to the email that is send to the end user. But I am stuck on one thing.
Firstly I was using the EMAIL_ON_SEND hook to add an attachment to the email. But it seems that it will add a attachment to each email everytime it is called.
For each email it is called two times. So to the first mail it will add 2 attachments and for the second one 4, etc etc.
The second approach was to use the ON_SENT_EMAIL_TO_USER hook. But this one does not seems to be called before the email (in a segment) is send.
class EmailSubscriber extends CommonSubscriber
{
protected $helper;
public function __construct(IntegrationHelper $helper)
{
$this->helper = $helper;
$this->parser = new ApiParser();
}
/**
* #return array
*/
public static function getSubscribedEvents()
{
return [
// EmailEvents::EMAIL_ON_SEND => ['onEmailSend', 100],
EmailEvents::ON_SENT_EMAIL_TO_USER => ['onEmailSend', 100],
];
}
/**
* Search and replace tokens with content
*
* #param EmailSendEvent $event
*/
public function onEmailSend(EmailSendEvent $event)
{
error_log('123');
}
Someway I have to hook on the actual action that is sending the email instead of the event (?). But I can't figure out which one
I can't answer directly but might be able to point you at some useful resources!
Firstly, are you trying to send the email to the Mautic user (e.g. the administrator or the owner of the lead), or to the lead? Just wanted to double check we're looking at the right thing as they are often confused!
It also depends on what you're trying to do, attach a file which isn't currently part of Mautic (e.g. an invoice or something like that) or if you're trying to attach a file which you want to track in Mautic as an asset.
In terms of attachments, these resources from the developer documentation may be useful:
Mailhelper - https://developer.mautic.org/#mail-helper
Attachments - https://developer.mautic.org/#attachments
It references attachFile() but there is also attachAsset() which allows you to attach a Mautic asset you have already uploaded (\Mautic\AssetBundle\Entity\Asset).
You may also want to take a look at https://forums.mautic.org where there may be more developers from the community able to give some further insight!
Hey Firstly thank you for the response.
The hook is called multiple times so I needed to tweak it.
So we track where it is called and filter it.
Besides that we need to clean the attachments every time.
Anyway even if it is not that clean, it does the trick
$trace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 5);
if (strpos($trace[4]['file'], 'SendEmailToContact.php') !== false) {
$helper = $event->getHelper();
$messageChildren = $helper->message->getChildren();
if (count($messageChildren) > 0) {
$helper->message->detach($messageChildren[0]);
}

How to access Mail data from MessageSent event on Laravel?

I'm using laravel 5.5, and trying to send emails with an image that is the sign of the client. To make the image accessible from the views I'm copying it into public folder and queued emails will access to it.
With a single action I can send multiple emails to the client, with sign into email, and pdf like the email attached, with sign image too. Then, the same image can be called multiple times from different emails. Is for this that I copy one image with a codified name for each email and passing the name of the image to the Mailable.
The problem is to make a sign of client public with a limited time. Then I'm trying to make listener for Illuminate\Mail\Events\MessageSent event that deletes the image of public folder getting the image name from the event... but I can't access to it.
How can I access to data of mailable from the event?
Do you know a better way to do this?
Thanks in advance.
Mailable class
class SEPA extends Mailable
{
use Queueable, SerializesModels;
public $client;
/**
* Create a new message instance.
*
* #param Client $client
*/
public function __construct(Client $client)
{
$this->client = $client;
}
/**
* Build the message.
*
* #return $this
*/
public function build()
{
$date = Carbon::now();
// Name codified
$fileName = md5(microtime()).".png";
// Making the image accessible from views
Storage::copy("clients/{$this->client->id}/firma.png", "public/tmp/{$fileName}");
$pdfName = "SEPA - {$this->client->name}{$this->client->cognom1}{$this->client->cognom2}.pdf";
$dades = [
'data' => $date,
'client' => $this->client,
'firma' => $fileName
];
// Generating PDF
$pdf = PDF::loadView('pdfs.SEPA', $dades);
if (!Storage::has("tmp/clients/{$this->client->id}")) Storage::makeDirectory("tmp/clients/{$this->client->id}");
$pdf->save(storage_path()."/app/tmp/clients/{$this->client->id}/".$pdfName);
return $this
->from(['address' => 'email#random.com'])
->view('emails.SEPA')
->with($dades)
->attach(storage_path()."/app/tmp/clients/{$this->client->id}/".$pdfName);
}
}
EventServiceProvider.php
protected $listen = [
'Illuminate\Mail\Events\MessageSent' => [
'App\Listeners\DeleteTempResources'
]
];
Listener
public function handle(MessageSent $event)
{
// Trying to access on data message
Log::info($event->message->firma);
}
You might be able to just set the additional data you need to access from the event via the withSwiftMessage() method, as extra fields on the actual swiftMessage, since that's what will be accessible in the event, as $message.
I saw someone did this here, e.g. to add a $user object:
$this->withSwiftMessage(function ($message) {
$message->user = $this->user; // any crazy field of your choosing
});
This seemed pretty unorthodox to me - adding rogue fields like that.
Note you don't need to use the $user object to get it into the closure as it's available in scope via $this, so long as it's a member property of the containing class.
To see it in the event when the message comes off the queue, you can Log::info('The user: ', [$event->message->user]) in the MessageSending event.
I've just tested this, and it works (I'm on 5.5), but I'm not yet using this myself in code as it does seem a little strange, adding a rogue field like that. I mention it though as it might actually solve your problem if you're comfortable with the method! If anyone knows a less ugly way to do it, I'm all ears...
P.S. I may consider just tacking on $message->lara_user_id = $this->user->id in the closure, for my own case, as that seems unlikely to collide with anything, and can be conveniently pulled back in the event. discussion welcome!

Laravel: Send emails only if the email is not on bounce list

I'm using Laravel 5.3 and the SES driver in order to send my emails.
I've set up my database and routes so that, whenever I send an email that returns as a bounce, I get a notification and add this email to a table of "invalid emails".
Now I need to setup my app so it only sends an email if the email is NOT in this bounce table. It's a check that will be made for every single email sent by this app, with no exceptions.
Is there an easy way to make this check on the email driver, or do I need to change all calls to the Mail facade and check this before sending the email?
I'd suggest creating your own Mailable class which inherits from \Illuminate\Mail\Mailable.
There is a method there called buildRecipients() which looks like this:
/**
* Add all of the recipients to the message.
*
* #param \Illuminate\Mail\Message $message
* #return $this
*/
protected function buildRecipients($message)
{
foreach (['to', 'cc', 'bcc', 'replyTo'] as $type) {
foreach ($this->{$type} as $recipient) {
$message->{$type}($recipient['address'], $recipient['name']);
}
}
return $this;
}
You could hook in to (override) this and add some logic to only add the recipient if he is not on the "blocked" list.

How can I pipe emails to my Laravel 5 application

I'm currently using cPanel on my server side and i've tried all the tutorials online that show how to pipe all your emails to Laravel project, I did find one tutorial that works on Laravel 4 but unfortunately it didn't work for me on Laravel 5.0:
http://www.sitepoint.com/piping-emails-laravel-application/
I've set up my cPanel "default address" to a php handler file but since i'm working with Laravel I can't get this file to work with the app classes and do stuff for my customers (like send notifications, save email information on the database, etc...)
please let me know if there is a nice clean way to accomplish that.
BTW, I need all the emails on this domain to go to my php handler not from one address only, because each one of my customers got his own email address
I ended up creating a free account on mandrill and they are posting all my incoming emails to one of my routes.. than, I've created a controller to handle the incoming emails from mandrill and i can do whatever I need in there...Thats the best way to do It...I'm getting and processing emails in less than 2 seconds. That's amazing.
I've added the mandrill MX records to a subdomain of mine and now I gave all my customers an email address with this subdomain on it "username#inbox.mydomain.com"
This is my route:
Route::post('inbound/message', 'MailController#inboundMessages');
and this is my controller example:
use Illuminate\Http\Request;
use App\Http\Requests;
use App\Http\Controllers\Controller;
use Carbon\Carbon;
class MailController extends Controller
{
/**
* main function to receive incoming email from mandrill POST request
* #param JSON $request Mandrill Object in JSON format
* #return string
*/
public function inboundMessages(Request $request){
if(isset($request['mandrill_events'])){
$messageJson = json_decode($request['mandrill_events']);
$message = $messageJson[0]->msg;
$email = [
"to" => $message->email,
"from" => $message->from_email,
"name" => isset($message->from_name) ? $message->from_name : "No Name",
"subject" => isset($message->subject) ? $message->subject : "No Subject",
"content" => isset($message->text) ? $message->text : "",
"content_html" => isset($message->html) ? $message->html : ""
];
//do whatever you want with your $email
}
}
}
hope it helps :) Good luck

Categories