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

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;

Related

How to send data in the mailgun header with 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"
},

yii2-websocket issue for getting online users list

I am using this package for a chat application. I am facing issue to get the online users list. There is a way suggested by someone I tried that but no success.
Code below for getting the online users list.
/**
* Subscribe to messages
*
* #param ConnectionInterface $client
* #param string $msg
*/
public function commandSubscribe(ConnectionInterface $client, $msg)
{
$request = #json_decode($msg, true);
$client->talkId = $request['talk_id'] ?? null;
$client->userId = $request['user_id'] ?? null;
$this->clients = $client;
foreach ($this->clients as $key=>$chatClient) {
$onlineUsers[] = $chatClient->name;
}
$client->send( json_encode(['onlineUsers'=> $onlineUsers, 'room'=>$client->talkId, 'user' =>$client->userId ,'message'=> 'User added to room']) );
}
I get the below response:
Response:{"onlineUsers":{},"room":"provider","user":"hassan","message":"User added to room"}

Laravel: Is possible send notification with delay, but changing smtp settings dynamically?

I'm developing a Multi Tenant (multiple database) with Laravel v5.7 and I'm successful in sending queue emails.
In some specific situations, I'd like to send on-demand notifications with 'delay', similar to the guide On-Demand Notifications, but informing the SMTP settings that should be used before sending.
I've developed a class that changes the values of config().
app/Tenant/SmtpConfig.php
class SmtpConfig
{
public static function setConnection(SmtpConta $conta = null)
{
// get connection default settings
$config = config()->get("mail");
// populate connection default settings
foreach ($config as $key => $value) {
if ( $key == 'host' ) { $config[$key] = $conta->mail_host ?? $config[$key]; }
if ( $key == 'from' ) { $config[$key] = [
'address' => ( $conta->mail_host === 'smtp.mailtrap.io' ) ? $config[$key]['address'] : $conta->mail_username,
'name' => $conta->conta ?? $config[$key]['name']
]; }
if ( $key == 'username' ) { $config[$key] = $conta->mail_username ?? $config[$key]; }
if ( $key == 'password' ) { $config[$key] = !empty($conta->mail_password) ? $conta->mail_password : $config[$key]; }
}
$config['encryption'] = ( $conta->mail_host === 'smtp.mailtrap.io' ) ? null : 'ssl';
// set connection default settings
config()->set("mail", $config);
}
}
... and I call this SmtpConfig class in notification:
/**
* Create a new notification instance.
*
* #param $conta
* #param $subject
* #return void
*/
public function __construct(SmtpConta $conta = null, $subject = null)
{
$this->conta = $conta;
$this->subject = $subject;
$when = \Carbon\Carbon::now()->addSecond(100);
$this->delay($when);
app(\App\Tenant\SmtpConfig::class)::setConnection($this->conta);
}
I can send the 'delayed' notification successfully, but apparently it always uses the default values of the .env file.
Now I'm not sure if where I'm calling the class makes any sense or even how can I tell the notification what SMTP configuration it should use.
I'm currently facing a similar challenge, on a Laravel 5.2 codebase using the Notification backport library.
This is an example of my solution, similar to Kit Loong's suggestion. We just extend the Illuminate\Notifications\Channels\MailChannel class and override the send() method.
You'll need to be able to determine the SMTP config from the recipient(s), or notification objects, so you'll need to edit my example as necessary.
Also this assumes your app is using the default Swift_Mailer so YMMV...
<?php
declare (strict_types = 1);
namespace App\Notifications\Channels;
use Illuminate\Notifications\Channels\MailChannel;
use Illuminate\Notifications\Notification;
class DynamicSmtpMailChannel extends MailChannel
{
/**
* Send the given notification.
*
* #param mixed $notifiable
* #param \Illuminate\Notifications\Notification $notification
* #return void
*/
public function send($notifiable, Notification $notification)
{
//define this method on your model (note $notifiable could be an array or collection of notifiables!)
$customSmtp = $notifiable->getSmtpConfig();
if ($customSmtp) {
$previousSwiftMailer = $this->mailer->getSwiftMailer();
$swiftTransport = new \Swift_SmtpTransport(
$customSmtp->smtp_server,
$customSmtp->smtp_port,
$customSmtp->smtp_encryption
);
$swiftTransport->setUsername($customSmtp->smtp_user);
$swiftTransport->setPassword($customSmtp->smtp_password);
$this->mailer->setSwiftMailer(new \Swift_Mailer($swiftTransport));
}
$result = parent::send($notifiable, $notification);
if (isset($previousSwiftMailer)) {
//restore the previous mailer
$this->mailer->setSwiftMailer($previousSwiftMailer);
}
return $result;
}
}
It may also be beneficial to keep an ephemeral store of custom swift mailers so you can re-use them in the same invokation/request (think about long-running workers) - like a collection class where a hash of the smtp config is used as the item key.
Best of luck with it.
Edit:
I should probably mention you may need to bind this in the service container. Something like this should suffice:
// in a service provider
public function register()
{
$this->app->bind(
\Illuminate\Notifications\Channels\MailChannel::class
\App\Notifications\Channels\DynamicSmtpMailChannel::class
);
}
Or alternatively, register it as a seperate notification channel.
I think you can also refer to this implementation.
https://stackoverflow.com/a/46135925/6011908
You could execute by passing custom smtp configs.
$transport = new Swift_SmtpTransport(
$customSmtp->host,
$customSmtp->port,
$customSmtp->encryption
);

Check mail is sent successfully or not on Laravel 5

I have a function that can send mail on Laravel5 using this
/**
* Send Mail from Parts Specification Form
*/
public function sendMail(Request $request) {
$data = $request->all();
$messageBody = $this->getMessageBody($data);
Mail::raw($messageBody, function ($message) {
$message->from('yourEmail#domain.com', 'Learning Laravel');
$message->to('goper.zosa#gmail.com');
$message->subject('Learning Laravel test email');
});
return redirect()->back();
}
/**
* Return message body from Parts Specification Form
* #param object $data
* #return string
*/
private function getMessageBody($data) {
$messageBody = 'dummy dummy dummy dummy';
}
and is sent successfully. But how to check if it was sent or not? Like
if (Mail::sent == 'error') {
echo 'Mail not sent';
} else {
echo 'Mail sent successfully.';
}
I'm just guessing that code.
I'm not entirely sure this would work but you can give it a shot
/**
* Send Mail from Parts Specification Form
*/
public function sendMail(Request $request) {
$data = $request->all();
$messageBody = $this->getMessageBody($data);
Mail::raw($messageBody, function ($message) {
$message->from('yourEmail#domain.com', 'Learning Laravel');
$message->to('goper.zosa#gmail.com');
$message->subject('Learning Laravel test email');
});
// check for failures
if (Mail::failures()) {
// return response showing failed emails
}
// otherwise everything is okay ...
return redirect()->back();
}
Hope this helps
The Mail::failures() will return an array of failed emails.
Mail::send(...)
if( count(Mail::failures()) > 0 ) {
echo "There was one or more failures. They were: <br />";
foreach(Mail::failures() as $email_address) {
echo " - $email_address <br />";
}
} else {
echo "No errors, all sent successfully!";
}
source : http://laravel.io/forum/08-08-2014-how-to-know-if-e-mail-was-sent
For Laravel 9.11.0
Mail::failures() // is deprecated in laravel 9.11.0
To check if your email was sent successfully one could wrap mail send in a try catch block:
try {
Mail::to($userEmail)->send($welcomeMailable);
} catch (Exception $e) {
//Email sent failed.
}
or since Mail::to($email)->send($mailable) on success returns an instance of : SentMessage one could check:
$welcomeEmailSent = Mail::to($userEmail)->send($welcomeMailable);
if ($welcomeEmailSent instanceof \Illuminate\Mail\SentMessage) {
//email sent success
} else {
//email sent failed
}
You may additionally can make use "Swift_TransportException" to identify any errors.
try{
//code to send the mail
}catch(\Swift_TransportException $transportExp){
//$transportExp->getMessage();
}
You can use the Mail::failures() function for that.
It will have a collection of failed mails if it exists so you can use the code below to check for it.
public function sendMail(Request $request) {
$data = $request->all();
$messageBody = $this->getMessageBody($data);
Mail::raw($messageBody, function ($message) use ($messageBody) {
$message->from('yourEmail#domain.com', 'Learning Laravel');
$message->to('goper.zosa#gmail.com');
$message->subject($messageBody);
});
// check for failed ones
if (Mail::failures()) {
// return failed mails
return new Error(Mail::failures());
}
// else do redirect back to normal
return redirect()->back();
}

send transactional email magento

I'm trying to send a confirmation email when a subscription order is created in magento but is not sending anything.
i know email configuration its fine because when i buy a regular product i do receive the email.
i created a template on System -> Transactional Emails , template with id=12, then on code on class AW_Sarp2_Model_Checkout_Type_Onepage extends Mage_Checkout_Model_Type_Onepage i call to send subs email method but it never sends any email
class AW_Sarp2_Model_Checkout_Type_Onepage extends Mage_Checkout_Model_Type_Onepage
{
public function saveOrder()
{ Mage::log("checkout/onepage",null,"onepageemail.log");
$isQuoteHasSubscriptionProduct = Mage::helper('aw_sarp2/quote')->isQuoteHasSubscriptionProduct(
$this->getQuote()
);
if (!$isQuoteHasSubscriptionProduct) //HERE I ASK IF IS A SUBSCRIBE PRODUCT {Mage::log("checkout/onepage34",null,"onepageemail.log");
return parent::saveOrder();
}
$this->validate();
$isNewCustomer = false;
switch ($this->getCheckoutMethod()) {
case self::METHOD_GUEST:Mage::log("checkout/onepage40",null,"onepageemail.log");
$this->_prepareGuestQuote();
break;
case self::METHOD_REGISTER:Mage::log("checkout/onepage43",null,"onepageemail.log");
$this->_prepareNewCustomerQuote();
$isNewCustomer = true;
break;
default:Mage::log("checkout/onepage47",null,"onepageemail.log");
$this->_prepareCustomerQuote();
break;
}
if ($this->getQuote()->getCustomerId()) {Mage::log("checkout/onepage52",null,"onepageemail.log");
$this->getQuote()->getCustomer()->save();
}
#AW_SARP2 override start
$service = Mage::getModel('aw_sarp2/sales_service_profile', $this->getQuote());Mage::log("checkout/onepage56",null,"onepageemail.log");
$service->submitProfile();Mage::log("checkout/onepage57",null,"onepageemail.log");
#AW_SARP2 override end
$this->getQuote()->save();Mage::log("checkout/onepage60",null,"onepageemail.log");
if ($isNewCustomer) {Mage::log("checkout/onepage61",null,"onepageemail.log");
try {
$this->_involveNewCustomer();Mage::log("checkout/onepage63",null,"onepageemail.log");
} catch (Exception $e) {
Mage::logException($e);
}
}
$this->_checkoutSession->setLastQuoteId($this->getQuote()->getId())
->setLastSuccessQuoteId($this->getQuote()->getId())
->clearHelperData();Mage::log("checkout/onepage71",null,"onepageemail.log");
// add recurring profiles information to the session
$profiles = $service->getRecurringPaymentProfiles();Mage::log("checkout/onepage73",null,"onepageemail.log");
if ($profiles) {Mage::log("checkout/onepage74",null,"onepageemail.log");
$ids = array();
foreach ($profiles as $profile) {
$ids[] = $profile->getId();
}Mage::log("checkout/onepage78",null,"onepageemail.log");
$this->sendSubscribeEmail2();Mage::log("checkout/onepage79",null,"onepageemail.log");
$this->_checkoutSession->setLastRecurringProfileIds($ids);
Mage::log("checkout/onepage82",null,"onepageemail.log");
}
return $this;
}
public function sendSubscribeEmail2(){ //HERE I TRY TO SEND THE EMAIL
$templateId = 12;
// Set sender information
$senderName = Mage::getStoreConfig('trans_email/ident_support/name');
$senderEmail = Mage::getStoreConfig('trans_email/ident_support/email');
$sender = array('name' => $senderName,
'email' => $senderEmail);
// Set recepient information
$recepientEmail = 'minorandres#gmail.com';
$recepientName = 'Test Test';
// Get Store ID
$storeId = Mage::app()->getStore()->getId();
// Set variables that can be used in email template
$vars = array('customerName' => 'test',
'customerEmail' => 'minorandres#gmail.com');
$translate = Mage::getSingleton('core/translate');Mage::log("checkout/onepage103",null,"onepageemail.log");
// Send Transactional Email
Mage::getModel('core/email_template')
->sendTransactional($templateId, $sender, $recepientEmail, $recepientName, $vars, $storeId);Mage::log("checkout/onepage106",null,"onepageemail.log");
if (!Mage::getModel('core/email_template')->getSentSuccess()) {
Mage::log("EXCEPTION!!!! =( checkout/onepage107",null,"onepageemail.log");
}
is there something in xml files that i have to do or other place?, please help me
Since i am dealing with subscription products they are handle by a different SMTP provider, on the exception.log i got and error "Mandril cant send email" something like that then i went to Admin Panel and under system>transactional emails has a subtab called mandril i configured that tool and create an account on mandril, then i put the API key indicaded by mandril into system>configuration>mandril(on left side).

Resources