Handling bounces and complaints in AWS SES with Laravel - email

I have configured Laravel to send mails via SES smtp and it's working fine. I want to increase my email quota for 24 hours hence the handling bounces and complaints part. Currently, my quota is 200 mails per 24 hours and the mail sent are only for registration confirmation and password reset.
I need help with this, please.

I recently made ground with this.
I followed these steps from the link Amazon sent me https://aws.amazon.com/blogs/ses/handling-bounces-and-complaints/
Set up the following AWS components to handle bounce notifications:
Create an Amazon SQS queue named ses-bounces-queue.
Create an Amazon SNS topic named ses-bounces-topic.
Configure the Amazon SNS topic to publish to the SQS queue.
Configure Amazon SES to publish bounce notifications using ses-bounces-topic to ses-bounces-queue.
And then I installed this package because
Out of the box, Laravel expects SQS messages to be generated in specific format
https://github.com/dusterio/laravel-plain-sqs
I followed their setup instructions and created this Job.
I was able to get a response from a SQS test message in any format and started this queue worker php artisan queue:work sqs-plain
ProcessFailedEmail.php
namespace App\Jobs;
use Dusterio\PlainSqs\Jobs\DispatcherJob;
use Illuminate\Contracts\Queue\Job;
class ProcessFailedEmail extends DispatcherJob
{
protected $data;
function __construct($data = null)
{
parent::__construct($data);
}
public function handle(Job $job, $data)
{
var_dump($data);
}
}
sqs-plain.php
/**
* List of plain SQS queues and their corresponding handling classes
*/
return [
'handlers' => [
'ses-bounces-queue' => App\Jobs\ProcessFailedEmail::class
],
'default-handler' => App\Jobs\ProcessFailedEmail::class
];

Related

Symfony Messenger: Send logged messenger errors per email (via swift_mailer)?

I've configured monolog to send errors via email as described in the symfony docs here: https://symfony.com/doc/4.3/logging/monolog_email.html
Works well with all errors happing during a request, as well as console command errors.
But it does not send emails for errors which occurred during the handling of a messenger message.
Errors are shown when running the consumer bin/console messenger:consume async -vv and they also show up in prod.log like this:
[2020-01-10 12:52:38] messenger.CRITICAL: Error thrown while handling message...
Thanks for any hints on how to set up monolog to get messenger errors emailed too.
In fact monolog swift_mailer type use SwiftMailerHandler
wish also implements reset interface and use memory spool by default wish keep all emails in buffer until it is destructed, so till the end of request :
onKernelTerminate
onCliTerminate
OR till reset method is called, which means that for messenger worker no emails will be send ever because ther's no instant flush - all of them will be kept in in-memory buffer, and probably lost if the process will be killed.
To solve this, you can just disable the default spool memory setting for swiftmailer.
Another solution is to flush your emails after WorkerMessageFailedEvent event gets fired, you can implement an event subscriber to do it for this.
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\Messenger\Event\WorkerMessageFailedEvent;
use Symfony\Component\Messenger\Event\WorkerMessageHandledEvent;
use Symfony\Contracts\Service\ResetInterface;
/**
* Class ServiceResetterSubscriber.
*/
class ServiceResetterSubscriber implements EventSubscriberInterface
{
protected ResetInterface $servicesResetter;
public function __construct(ResetInterface $servicesResetter)
{
$this->servicesResetter = $servicesResetter;
}
public function resetServices(): void
{
$this->servicesResetter->reset();
}
public static function getSubscribedEvents(): array
{
return [
WorkerMessageFailedEvent::class => ['resetServices', 10],
];
}
}
Register your service with the right argument:
App\EventSubscriber\ServiceResetterSubscriber:
arguments: ['#services_resetter']
By the way without this (and without buffer limit) your app will leak and no emails will be sent ever.
Another trick:
Make sure that your message implements \JsonSerializable to get the message content in your logs, because messenger uses his monolog directly and its context serializer wish use json_encode for seriliazation.
That's why we need to customize their JSON representation when encoded is done with json_encode.

CakePHP 3.x - Email to log instead of sending during debug

I would like to switch my application to a configuration where email isn't actually send, but instead saved to a log file.
This way I can test my application normally without being afraid of accidentally emailing to hundreds of users and without spamming myself.
I figured something with EmailTransports could be a solution. For instance, when using the DebugTransport the emails aren't send at all, the mail content is instead only returned by the ->send() function.
The downside of this transport is than I have to modify controller code in order to display the content, which I would like to avoid.
So is there a configuration such that email is stored to files instead of being sent, e.g.:
[root]
logs/
emails/
2019-10-01_15:32_email#example.com.txt
2019-10-01_16:54_another_recipient#example.com.txt
...
There is no such built-in configuration, no, but you can easily create your own custom transport that logs emails to files instead of sending them.
Here's a very basic example transport that extends the debug transport, and writes the data to a custom logging scope:
namespace App\Mailer\Transport;
use Cake\Log\LogTrait;
use Cake\Mailer\Email;
use Cake\Mailer\Transport\DebugTransport;
use Psr\Log\LogLevel;
class TestTransport extends DebugTransport
{
use LogTrait;
public function send(Email $email)
{
$data = parent::send($email);
$this->log(json_encode($data), LogLevel::DEBUG, ['scope' => ['emails']]);
return $data;
}
}
See also
Cookbook > Email > Using Transports > Creating Custom Transports

passing data to mailgun webhooks in laravel

Im using laravel and configured mailgun to send mails
I want to use webhooks to track them.
so I need to send data with the message so I can track it using the web hook
for example attach a message id to each mail I send
tried to follow the mailgun documnation but no luck
this is my code for sending the mail
$data = array('course_name' => $course_name,'grade' => $grade,'email' => $stud->email,
"v:messageId" => "123");
Mail::send('emails.stud_feedback',$data, function ($message) {
$message->to($this->email)->subject( $this->course);
$message->attach($this->file, ['as' => 'feedback']);
});
according to the documnation the web hook should post me the message id,
but Im not getting it.
what am I doing wrong?
solved by setting headers to the mail:
$message->getHeaders()->addTextHeader('X-Mailgun-Variables', "{'messageid:123}'}");
Use This :
Mail::send('emails.test',[]), function ($message) use ($subject, $from, $emails) {
dd($message->getSwiftMessage()->getId());
});

Sending and Queuing emails in laravel

Hello i am trying to send emails in laravel this is currently what i do:
$parameters = array(
'date_of_purchase' => date('l, d m Y H:i A'),
'amount' => $amount,
);
// Sending Mail
Mail::queue('emails.bus-ticket-purchase', $parameters, function ($message) use ($customer_email) {
if ($message->to($customer_email, '')->subject('Ticket Purchase')) {
$all_good = true;
}
});
This works fine,all emails get delivered, but i started getting complaints about how some emails were taking about an hour to come through so i decided to read laravels documentation on emails and queues, what i found there was actually quite different from what i had done:
Laravel Mail Queues
So i run the artisan command to create the SendMail command and tried to folow the rest of the documentation but i still do not get it, it states that to send a mail(push it on a queue) i should do this:
Queue::push(new SendEmail($message));
Now where does the above code go? In my SendMail command or in my controller? Is there somewhere where i can see how this all works, i would really like someone to explain all this to me.

MassTransit Send only

I am implementing a Service Bus and having a look at MassTransit. My pattern is not Publish/Subscribe but Sender/Receiver where the Receiver can be offline and came back online later.
Right now I am starting to write my tests to verify that MassTransit succesfully deliver the message using the following code:
bus = ServiceBusFactory.New(sbc =>
{
sbc.UseMsmq(
cfg =>
{
cfg.Configurator.UseJsonSerializer();
cfg.Configurator.ReceiveFrom("msmq://localhost/my_queue");
cfg.VerifyMsmqConfiguration();
});
});
Then I grab the bus and publish a message like this:
bus.Publish<TMessage>(message);
As I can notice from MSMQ, two queues are created and the message is sent cause Mass Transit does not raise any error but I cannot find any message in the queue container.
What am I doing wrong?
Update
Reading the Mass Transit newsgroup I found out that in a scenario of Sender/Receiver where the receiver can come online at any time later, the message can be Send using this code:
bus.GetEndpoint(new Uri("msmq://localhost/my_queue")).Send<TMessage>(message);
Again in my scenario I am not writing a Publisher/Subscriber but a Sender/Receiver.
First, to send, you can use a simple EndpointCacheFactory instead of a ServiceBusFactory...
var cache = EndpointCacheFactory.New(x => x.UseMsmq());
From the cache, you can retrieve an endpoint by address:
var endpoint = cache.GetEndpoint("msmq://localhost/queue_name");
Then, you can use the endpoint to send a message:
endpoint.Send(new MyMessage());
To receive, you would create a bus instance as you specified above:
var bus = ServiceBusFactory.New(x =>
{
x.UseMsmq();
x.ReceiveFrom("msmq://localhost/queue_name");
x.Subscribe(s => s.Handler<MyMessage>(x => {});
});
Once your receiver process is complete, call Dispose on the IServiceBus instance. Once your publisher is shutting down, call Dispose on the IEndpointCache instance.
Do not dispose of the individual endpoints (IEndpoint) instances, the cache keeps them available for later use until it is disposed.