How to send data in the mailgun header with LARAVEL? - laravel

I am working with webhooks for the first time, in which I have to pass some 3 variables defined for later when Laravel takes it again I can update an action of the email sent for some reports.
The problem is that I can't pass data in the header of the email.
This is the structure that commonly sent the email to the users:
public $data;
/**
* Create a new message instance.
*
* #return void
*/
public function __construct($view, $subject, $data)
{
$this->view = $view;
$this->subject = $subject;
$this->data = $data;
}
public function build()
{
$message = $this->data;
// print_r($variables);
// exit;
return $this->from(config('mail.from.address'), config('mail.from.name'))
->view($this->view)
->subject($this->subject); //WORKED
/**NO WORKED*/
->withSwiftMessage(function ($message) use ($v){
$v->getHeaders()
->addTextHeader('Custom-Header', 'HeaderValue1')
->addTextHeader('Custom-Header2', 'HeaderValue2');
});
}
The emails if sent in that there is no problem, with the view and the data that is filled in the mail, but in the header the data is not filled in at least in this case, the 2 variables set ['Custom-Header', 'HeaderValue1', 'Custom-Header', 'HeaderValue2].

I had the same problem too and it took me quite a bit of research and testing. It seems that it needs to be in json format and you need to use 'X-Mailgun-Variables' instead of 'Custom-Header'. It should look like this
->addTextHeader('X-Mailgun-Variables', '{"variable1": "1", "variable2": "2"}')
the webhook should give you this result
"user-variables":{
"variable1":"1",
"variable2":"2"
},

Related

how to build a Laravel command that loops through users is sends unique emails to each user

I have a command that I'll run nightly using the Forge scheduler. The command simply loops through and sends emails to each user who qualifies for one.
COMMAND:
public function handle()
{
//Get all users
$users = User::all();
$data = [];
$renewalEmail = '';
foreach($users as $user)
{
//Check each users next_biling_date and see if is less than 72 hours from now, if so send reminder email
$nextBillingDate = ($user->hasSubscription())? $user->getSubscriptionData()->current_period_end : false;
$now = strtotime(now());
$threeDaysFromNow = 60*60*24*3;
//($user->hasSubscription())? $this->updateNextBillingDate($user) : false;//TODO: remove after working: follow up
if($user->hasSubscription() && $nextBillingDate-$now<=$threeDaysFromNow)
{
$data = [
'name' => $user->name,
'billingdate' => date('n/j/Y',strtotime($user->next_billing_date)),
];
// Log::info(print_r($data,true));
$renewalEmail = Mail::to('my#email.com')->send(new SubscriptionRenewalReminder($data));
// Log::info(print_r($renewalEmail,true));
}
}
return true;
}
My Mailable is pretty straight forward:
public function __construct($data)
{
$this->data = $data;
}
/**
* Build the message.
*
* #return $this
*/
public function build()
{
Log::info('SubscriptionRenewalReminder Email build() called: ');
$firstName = explode(' ',$this->data['name'])[0];
$billingDate = $this->data['billingdate'];
Log::info('firstname: '.$firstName);
Log::info('billingDate: '.$billingDate);
return $this->view('emails.subscription-renewal-reminder')
->from('my#email.com', 'Project')
->subject('Project Subscription Is About To Renew')
->withName($firstName)
->withBillingdate($billingDate);
}
All of my Log::info's dump out the right information. I have 3 test users who all qualify to get the email.
In my testing, all three emails show the first user's name and billing date. Instead of unique emails, they are all identical.
I may move this into a queue but on a small set of users this should work fine. TIA

How do I loop over json data

I am using FlutterWave as my payment gateway, I want to loop through a transaction whenever a customer finish making payment and check for the chargeamount which the user paid. the return data is in json format. Here is my code.
public function callback(Request $request)
{
$resp = $request->resp;
$body = json_decode($resp, true);
$txRef = $body['data']['data']['txRef'];
$data = Rave::verifyTransaction($txRef);
dd($data);
return redirect()->route('success');
}
I want to loop and check for the chargedamount but I couldn't. Thanks for your help
Seems like you are dumping an object. I don't think you need a loop to access the data you need. According to your image dump, to access the chargedamount attribute:
dd($data->data->chargedamount);
The data name here repeats, perhaps $payload in this case, its a better name.
public function callback(Request $request)
{
$resp = $request->resp;
$body = json_decode($resp, true);
$txRef = $body['data']['data']['txRef'];
$payload = Rave::verifyTransaction($txRef);
dd($payload->data->chargedamount);
return redirect()->route('success');
}
Some clean up:
public function callback(Request $request)
{
$json = json_decode($request->resp);
$payload = Rave::verifyTransaction($json->data->data->txRef);
dd($payload->data->chargedamount);
return redirect()->route('success');
}
Again that data->data repeating stuff, but in this case, nothing we can do, its in the API.

Laravel skip sending mail based on conditions

I'm looping through users in my controller function and sending an email to each user, but there's a special user who will sometimes be in the list who shouldn't receive emails.
I'd like to put an if statement in to skip that loop iteration if it's that user, but when I add return, return null etc, or just nothing in my if/else in the mailable class build function I get
InvalidArgumentException
Invalid view.
I could add the conditional in the controller and I'm sure that would be fine, except I have these emails in a whole load of my controllers so would be writing the conditional many times. If I can get it into a central location (and the mailable class is the only one I'm aware of) then I can write it once.
EDIT: the loop code has been requested so added below, but this is just one of many email loops in my controllers so NOT where I'd like to add my conditional.
$objNotification = new \stdClass();
$objNotification->message_body = "stuff";
$user_ids = DB::select('select user_id from users_to_things where thing_id = ?', [$thing->id]);
foreach($user_ids as $user_id) {
$user = User::find($user_id->user_id);
$objNotification->receiver = $user->name;
Mail::to($user->email)->send(new NotificationEmail($objNotification));
}
Here's my mailable class's build function (where I DO want to add the conditional if at all possible):
public function build()
{
if($this->notification->receiver == 'the special user') {
return;
} else {
return $this->from('somebody#somewhere.com', 'Sender Name')
->subject('some subject')
->view('emails.notification')
->text('emails.notification_plain');
}
}
What you want would conflict with the Single Responsibility Principle. The class is only suppose to send the email.
The build() in your mailable class returns error cause it expect you to return a message ( subject ,body, template or view, etc) for your mail.
1.) maybe instead you can assert a fake mail in your condition;
2.) Create a function in email class
public function needSend($mail)
{
... loads of conditions
return (condition) ? true : false;
}
then
if ($mail->needSend($mail)) {
\Mail::send($mail);
}
3.) Or the easiest but dirtiest way is you can put the condition inside your Controller in your for loop
foreach($user_ids as $user_id) {
$user = User::find($user_id->user_id);
$objNotification->receiver = $user->name;
if(condition == true) continue;
Mail::to($user->email)->send(new NotificationEmail($objNotification));
}
You can also read this thread on github. https://github.com/laravel/ideas/issues/519
Using the notification class, check your condition like a suppression list or maybe runtime condition. Return an empty array and it'll exit.
/**
* Get the notification's delivery channels.
*
* #param mixed $notifiable
* #return array
*/
public function via($notifiable)
{
return $notifiable->notificationSuppression()->exists() ? [] : ['mail'];
}

Laravel mailable passing array to blade

On my project i made a contact form. It was store details on databse and shows admin panel and sends it to via mail so i cant pass array variables to mailable view.
My controller;
$iletisim = new Contact();
$iletisim->ad = $request->input('ad');
$iletisim->soyad =$request->input('soyad');
$iletisim->email = $request->input('email');
$iletisim->mesaj = $request->input('mesaj');
$iletisim->save();
$gonder = array( 'gonderen'=>$request->input('ad'),
'email'=>$request->input('email'),
'mesaj'=>$request->input('mesaj')
);
Mail::send(new ContactMail($gonder));
Session::flash('success', 'Mesajınız Gönderilmiştir. En kısa sürede dönüş sağlanacaktır.');
return back();
}
My Contact.php
public $bilgiler;
public function __construct($gonder)
{
$this->bilgiler = $gonder;
}
/**
* Build the message.
*
* #return $this
*/
public function build()
{
return $this->view('homepage.emails.contact')->with(['bilgiler'=>$this->bilgiler]);
}
and my blade file
#component('mail::message')
# New Contact Form
{{$bilgiler->ad}}
Thanks,<br>
{{ config('app.name') }}
#endcomponent
Where is my mistake can you help.
Thanks
First of all, you don't need to add ->with(['bilgiler'=>$this->bilgiler]); since $bilgiger is public property. All public properties of Mailable are available in Blade
Also, since it's an array, you need to access it with:
$bilgiger['gonderen']
The $bilgiler->gonderen syntax is for objects, not for arrays. Also, you don't have id in the array.
And the last thing is you're using markdown email, so use the markdown() method:
return $this->markdown('homepage.emails.contact');

Laravel 4 mail class, how to know if the email was sent?

I'm using the new mail class in Laravel 4, does anybody know how to check if the email was sent? At least that the mail was successfully handed over to the MTA...
If you do
if ( ! Mail::send(array('text' => 'view'), $data, $callback) )
{
return View::make('errors.sendMail');
}
You will know when it was sent or not, but it could be better, because SwiftMailer knows to wich recipients it failed, but Laravel is not exposing the related parameter to help us get that information:
/**
* Send the given Message like it would be sent in a mail client.
*
* All recipients (with the exception of Bcc) will be able to see the other
* recipients this message was sent to.
*
* Recipient/sender data will be retrieved from the Message object.
*
* The return value is the number of recipients who were accepted for
* delivery.
*
* #param Swift_Mime_Message $message
* #param array $failedRecipients An array of failures by-reference
*
* #return integer
*/
public function send(Swift_Mime_Message $message, &$failedRecipients = null)
{
$failedRecipients = (array) $failedRecipients;
if (!$this->_transport->isStarted()) {
$this->_transport->start();
}
$sent = 0;
try {
$sent = $this->_transport->send($message, $failedRecipients);
} catch (Swift_RfcComplianceException $e) {
foreach ($message->getTo() as $address => $name) {
$failedRecipients[] = $address;
}
}
return $sent;
}
But you can extend Laravel's Mailer and add that functionality ($failedRecipients) to the method send of your new class.
EDIT
In 4.1 you can now have access to failed recipients using
Mail::failures();
Antonio has a good point about not knowing which failed.
The real questions is success though. You do not care which failed as much as if ANY failed.
Here is a example for checking if any failed.
$count=0;
$success_count = \Mail::send(array('email.html', 'email.text'), $data, function(\Illuminate\Mail\Message $message) use ($user,&$count)
{
$message->from($user->primary_email, $user->attributes->first.' '.$user->attributes->last );
// send a copy to me
$message->to('me#example.com', 'Example')->subject('Example Email');
$count++
// send a copy to sender
$message->cc($user->primary_email);
$count++
}
if($success_count < $count){
throw new Exception('Failed to send one or more emails.');
}
if(count(Mail::failures()) > 0){
//$errors = 'Failed to send password reset email, please try again.';
$message = "Email not send";
}
return $message;

Resources