Laravel pass data into mail for different recipents - php

I just created a newsletter in Laravel, where people can register with their email-adress and then somebody can send a mail to those who are registered.
Then I save those registrations in a table, together with the relating id of the sender of the newsletter (in my case its a seller, and buyers register for a newsletter)....
This is the code I use then so send a newsletter:
public function sendNewsletter(Request $request){
$newsletterText = $request->newsletterText;
$seller = Auth::user();
$sellerID = $seller->id;
$newsletterMailAdresses = Newsletter::where('seller_id', $sellerID)->pluck('mailAdress');
Mail::bcc($newsletterMailAdresses)->send(new newsletterMail($newsletterText));
return "<p style='color:green;'>Newsletter erfolgreich versandt</p>";
}
Its called with an AJAX request, but shouldn't change anything...
What I need now is to give the users the possibility to unsubscribe from the newsletter as well, via a link in the mail.
This is the corresponding mail class:
<?php
namespace App\Mail;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Contracts\Queue\ShouldQueue;
class newsletterMail extends Mailable
{
use Queueable, SerializesModels;
/**
* Create a new message instance.
*
* #return void
*/
public $newsletterText;
/**
* Create a new message instance.
*
* #return void
*/
public function __construct($newsletterText)
{
$this->newsletterText = $newsletterText;
}
/**
* Build the message.
*
* #return $this
*/
public function build()
{
$subject = "Newsletter ShoppingPortal";
return $this->view('emails.newsLetter')->subject($subject);
}
}
And that's the mail view:
Newsletter vom Shoppingportal: <br/><br/>
<div>
{!!$newsletterText!!}
</div>
<br/>
To unsubscribe from Newsletter, use this link: localhost/unsubscribe/....
And here's the thing missing, I need to create a link to unsubscribe, therefore I would need the sellerID in the view (what would be possible, could just pass it in like the newsletterText, but HOW can I pass in or get the current mail adress the email is sent to? As this mail goes to some recipents, its different in each instance of the view... How can I do this, so how can I get the mail adress in the view?

I got it,
just changed the sending of the mail to this:
foreach($newsletterMailAdresses as $mailAdress){
Mail::to($mailAdress)->send(new NewsletterMail($newsletterText, $mailAdress, $sellerID));
}
Now I have the current mail adress while sending.

Related

Email verification does not seem to be sending anymore

I want to send email verification when a user signs up with a new Email Address. So at the Register Controller I added this:
public function register(Request $request)
{
if(Session::has('email')){
return Redirect::back()->withErrors(['msg' => 'Email was already sent to you, please check the spam folder too.']);
}else{
$validatedEmail = $request->validate([
'user_input' => 'required|unique:users,usr_email|regex:/(.+)#(.+)\.(.+)/i|max:125|min:3',
],[
'user_input.required' => 'You must enter this field',
'user_input.unique' => 'This email is already registered',
'user_input.regex' => 'This email is not correct',
'user_input.max' => 'Maximum length must be 125 characters',
'user_input.min' => 'Minimum length must be 3 characters',
]);
$register = new NewRegisterMemberWithEmail();
return $register->register();
}
}
So if the email was valid, it will call a helper class NewRegisterMemberWithEmail which goes like this:
class NewRegisterMemberWithEmail
{
public function register()
{
try{
$details = [
'title' => 'Verify email'
];
Mail::to(request()->all()['user_input'])->send(new AuthMail($details));
Session::put('email',request()->all()['user_input']);
return redirect()->route('login.form');
}catch(\PDOException $e){
dd($e);
}
}
}
So it used to work fine and correctly sends the email for verification, but I don't know why it does not send email nowadays.
In fact I have tested this with different mail service providers and for both Yahoo & Gmail the email did not received somehow!
But for local mail service provider based in my country the email was sent properly!
I don't know really what's going on here because the logic seems to be fine...
So if you know, please let me know... I would really really appreciate any idea or suggestion from you guys.
Also here is my AuthMail Class if you want to take a look at:
class AuthMail extends Mailable
{
use Queueable, SerializesModels;
public $details;
/**
* Create a new message instance.
*
* #return void
*/
public function __construct($details)
{
$this->details = $details;
}
/**
* Build the message.
*
* #return $this
*/
public function build()
{
return $this->subject('Sitename')->view('emails.AuthMail');
}
}
Once I was faced same problem when I was used Gmail as smtp.
Reason:
when we used our Gmail password directly in smtp settings then due to some Gmail policies it'll be blocked after sometime (months) and stopped email sending.
Solution:
we need to create an app-password from our Gmail security and use that password in smtp settings. below google article will guide:
How to create app-password on gmail
.env smtp setting for laravel:
MAIL_MAILER=smtp
MAIL_HOST=smtp.gmail.com
MAIL_PORT=587
MAIL_USERNAME=<your-email>
MAIL_PASSWORD=<app-password>
MAIL_ENCRYPTION=tls
I hope that'll help you.
If you use google mail to send email then we have the same problem.
On May 30, 2022 Google stop supporting less secure applications or third party application.
This is I think the reason why your send mail does not work (consider this answer if you use google mail as mail sender)
I was having issues when sending email, especially to gmail accounts. So I have changed my approach and overcome that issue.
Please check my answer below
Laravel Email
Example Mail Class
<?php
namespace App\Mail;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
use Symfony\Component\Mime\Email;
class OrderInfoMail extends Mailable
{
use Queueable, SerializesModels;
/**
* Create a new message instance.
*
* #return void
*/
public $data;
public function __construct($data)
{
$this->data = $data;
}
/**
* Build the message.
*
* #return $this
*/
public function build()
{
$this
->subject('Order Confirmation')
->from('noreply#app.xxx.co.uk', 'XXX Portal')
->view('orders.templates.order-form')
->with([
'name' => $this->data->name,
'sales_representative_name' => $this->data->sales_representative_name,
'sales_representative_phone' => $this->data->sales_representative_phone,
"items" => $this->data->items,
"address" => $this->data->address,
"net" => $this->data->net,
"payment" => $this->data->payment,
"balance" => $this->data->balance,
]);
$this->withSymfonyMessage(function (Email $message) {
$message->getHeaders()->addTextHeader(
'X-Mailer', 'PHP/' . phpversion()
);
});
return $this;
}
}
Usage
$email = 'a#b.com'; // pls change
$name = 'ab';// pls change
$data = new \stdClass();
$data->name = $name;
$data->sales_representative_name = \App\User::find(Auth::user()->id)->name;
$data->sales_representative_phone = \App\User::find(Auth::user()->id)->phones->first()->number;
$data->items = $order_items;
$data->address = $address;
$data->net = $net;
$data->payment = $payment;
$data->balance = $balance;
Mail::to($email)->send(new \App\Mail\OrderInfoMail($data));
I don't think the issue is your code. I think it is related to you sending practices. A solution is to use a service that is designed to send emails like SparkPost (full disclosure I work for SparkPost). There are many others. These services can help you make sure you are following email best practices.
You can make this work without an email service but at the very least you should verify you are following the best practices presented by MAAWG: https://www.m3aawg.org/published-documents

Is making my server send a mail from the email of a registered user impossible?

Right now I have functioning emailing on my Laravel back-end, however, the email is always sent from my gmail email. I was wondering if it is even possible to make the message appear as if it was send from the email of the registered user who's sending the message. For example right now it works like this:
Registered user George with email George#gmail.com sends a mail to user Ivan with email Ivan#gmail.com. When Ivan receives the email, the FROM field shows my mail username.
I'm wondering if it's even possible to set up the email code, so that it appears that the email comes from the user who's actually sending the email?
I reckon that is impossible because you'd need to somehow authenticate that you are in fact the owner of that email, before being able to send a message. Otherwise you can make emails that appear to be send from one email, when they're in fact from another.
I assume this is a very foolish question, but I just started fiddling with emails today and it's quite confusing.
That's how I send emails:
EmailController:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class EmailController extends Controller
{
public function sendMail(Request $request){
$title = "Email Title";
$body = "Email Body";
$receiver = "test123#abv.bg";
$details = [
'title' => $title,
'body' => $body
];
\Mail::to($receiver)->send(new \App\Mail\HiMail($details));
return redirect('/');
}
}
Mail.php:
<?php
namespace App\Mail;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
class HiMail extends Mailable
{
use Queueable, SerializesModels;
public $details;
/**
* Create a new message instance.
*
* #return void
*/
public function __construct($details)
{
$this->details = $details;
}
/**
* Build the message.
*
* #return $this
*/
public function build()
{
return $this->subject("Test Mail")->view("emails.hi");
}
}
mail.blade.php:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<h1>{{ $details['title'] }}</h1>
<p>{{ $details['body'] }}</p>
<p>Thank you</p>
</body>
</html>

Issue with displaying randomly generated code

So i have a section of code that creates a random code and sends it in a private message (on another website) to them, however id like to update it to also display the code in the success message
Models
public function createDepositRequest()
{
// Generate unique code
$code = Codes::generateCode();
$deposit = Deposits::create([
"accountID" => $this->id,
"code" => $code,
]);
echo $code;
dispatch(new CreateDepositRequest($deposit));
}
UserController
/**
* Creates a deposit request for an account
*
* #param int $accountID
* #throws UserErrorException
*/
protected function deposit(int $accountID)
{
// Get the account
$account = Accounts::find($accountID);
if ($account === null || $account->count() === 0)
throw new UserErrorException("That account doesn't exist");
// Verify that the submitting user owns this account
if (Auth::user()->nID != $account->nID)
throw new UserErrorException("You don't own that account, silly billy");
// Now call to create the deposit request
$account->createDepositRequest();
$this->output->addSuccess("Deposit request added successfully. Please check your inbox in-game for instructions");
}
Job (the thing that has it sent to the other site) ```
namespace App\Jobs;
use App\Classes\Nation;
use App\Classes\PWClient;
use App\Models\Accounts;
use App\Models\Deposits;
use Illuminate\Bus\Queueable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
class CreateDepositRequest implements ShouldQueue
{
use InteractsWithQueue, Queueable, SerializesModels;
/**
* Holds the deposit request
*
* #var Deposits
*/
protected $deposit;
/**
* Create a new job instance.
*
* #return void
*/
public function __construct(Deposits $deposit)
{
$this->deposit = $deposit;
}
/**
* Execute the job.
*
* #return void
*/
public function handle()
{
$client = new PWClient();
$client->login();
// Get nation info
$nation = new Nation($this->deposit->account->nID);
// Setup message
$message = "Hi {$nation->leader},\n\n You've submitted a deposit request for the account named: {$this->deposit->account->name}.\n\nThe code for your deposit is: {$this->deposit->code}\n\nPlease send whatever money and resources you want to deposit into your account into the bank using the code above as the transaction, just like how you make a payment towards a loan.\n\nPlease note that the system checks for deposits at five past the hour, so if you make a deposit during that time, your deposit [b]will not count[/b]. So please try to avoid that. Additionally, this means that your deposit will not show up in your account until then. You will receive a confirmation email when your deposit is processed. If you not get a message within two hours, please contact us.";
// Now send them a message
$client->sendMessage($nation->leader, "Deposit Request", $message);
echo "{$this->deposit->code}";
}
}
So ive tried a dozen things but im reaching a level where im above my knowlage it would appear. You can see that in the models i have it just echo the code, and since the user controller actually sends the success message, im not sure how to return the code generated in models for use in the usercontroller.
So to clarify i made a screenshot https://prnt.sc/r42p0v
Attempts tried: to add
-return $code; error was "undefined variable"
I can't say absolutely for sure without seeing more of the code, but it looks like you should be able to do this...
In your model, after
dispatch(new CreateDepositRequest($deposit));
add
return $code;
Then in your controller, replace
$account->createDepositRequest();
with
$code = $account->createDepositRequest();
Having done that, you should be able to access the returned $code value in the next line as something like
$this->output->addSuccess("Deposit request added successfully. Your code is $code. Please check your inbox in-game for instructions");
The only thing that would throw a wrench in this would be if there's something going on in dispatch(new CreateDepositRequest($deposit)); that isn't fully shown in your code above.

How get response after email message send. Symfony 4.3 mailer component

How get provider response result after mail send.
For example i send message via symfony/mailgun and want to get message-uid from provider after sending message
$email = (new Email())
->from('test#mail.com')
->to('foo#bar')
->subject('Send email test')
->text('email text');
$this->mailer->send($email); // is there any way to return response result instead void
Facing the same issue I came up with following solution:
Create your own handler for SendEmailMessage (inject original handler and use it's result for your purpose)
<?php
namespace MessengerBundle\MessageHandler;
use Symfony\Component\Mailer\Messenger\MessageHandler;
use Symfony\Component\Mailer\Messenger\SendEmailMessage;
use Symfony\Component\Mailer\SentMessage;
use Symfony\Component\Messenger\Handler\MessageHandlerInterface;
class SendEmailMessageHandler implements MessageHandlerInterface
{
/**
* #var MessageHandler
*/
private $defaultHandler;
/**
* SendEmailMessageHandler constructor.
* #param MessageHandler $defaultMessageHandler
*/
public function __construct(MessageHandler $defaultMessageHandler)
{
$this->defaultHandler = $defaultMessageHandler;
}
/**
* #param SendEmailMessage $message
* #return SentMessage|null
*/
public function __invoke(SendEmailMessage $message): ?SentMessage
{
$handler = $this->defaultHandler;
$sentMessage = $handler($message);
//your logic here
return $sentMessage;
}
}
Register it as a service:
MessengerBundle\MessageHandler\SendEmailMessageHandler:
autowire: true
autoconfigure: true
public: false
Replace original Symfony service with yours, otherwise mail will be sent twice (by original and your handlers):
mailer.messenger.message_handler:
class: MessengerBundle\MessageHandler\SendEmailMessageHandler
If this async approach don't fits to you, you can try this hack to extend mail service by adding getSentMessage into it.

How to set metadata and send text (.txt) file as attachment without storing on the server in laravel?

I am working on a module to send chats messages to user email (aka email transcript) using laravel 5.6.
I need to save all the chat messages to a txt file and send that file as attachment to user's email address.
I do not want to save the txt file to my server as many people would be using that application and it will increase the storage usage of the server i.e I need to generate the txt file in memory.
I am able to populate the chats in plain email without attachment but this is not the solution if the chat messages increase, email would be too lengthy and seems not professional to me.
This I have tried so far:
EmailTranscriptController.php
<?php
namespace App\Http\Controllers\Home;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use App\Models\Trade;
use App\Models\ChatMessage;
use Auth;
use Illuminate\Support\Facades\Mail;
use App\Mail\EmailTradeChatMessages;
use Validator;
class EmailTranscriptController extends Controller
{
public function emailTradeTranscript($tradeId)
{
$userId = Auth::id();
$userEmail = Auth::user()->email;
$trade = Trade::findClosedTradeByIdByUserId($tradeId, $userId);
if (is_null($trade)) {
return response()->api(false, 'Trade not available', null);
}
$tradeStartTime = $trade->created_at;
$tradeCloseTime = $trade->updated_at;
$tradeChats = ChatMessage::getAllChatByTradeId($tradeId);
Mail::to($userEmail)->queue(new EmailTradeChatMessages(
$tradeChats,
$tradeStartTime,
$tradeCloseTime
));
return response()->api(true, 'Email Sent Successfully', null);
}
}
EmailTradeChatMessages.php
<?php
namespace App\Mail;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Contracts\Queue\ShouldQueue;
class EmailTradeChatMessages extends Mailable
{
use Queueable, SerializesModels;
protected $chats;
protected $tradeStartTime;
protected $tradeCloseTime;
/**
* Create a new message instance.
*
* #return void
*/
public function __construct($chats, $tradeStartTime, $tradeCloseTime)
{
$this->chats = $chats;
$this->tradeStartTime = $tradeStartTime;
$this->tradeCloseTime = $tradeCloseTime;
}
/**
* Build the message.
*
* #return $this
*/
public function build()
{
return $this->markdown('emails.trade_chat_transcript')->with([
'chats' => $this->chats,
'tradeStartTime' => $this->tradeStartTime,
'tradeCloseTime' => $this->tradeCloseTime,
]);
}
}
trade_chat_transcript.blade.php (dummy)
#component('mail::message')
#Trade Started at: {{$tradeStartTime}}
#php
$count=0;
#endphp
#foreach($chats as $chat)
{{++$count}}
#endforeach
#Trade Closed at: {{$tradeCloseTime}}
Thanks,<br>
{{ config('app.name') }}
#endcomponent
Kindly help me getting the solution, I would also like to get other approaches to solution,if any.
Update
I found the solution for not storing the file on server itself and attach it using attachData() method, as follows:
public function build()
{
$email= $this->markdown('emails.trade_chat_transcript')->with([
'tradeId' => $this->tradeId,
'filename' => $this->filename,
'tradeStartTime' => $this->tradeStartTime,
'tradeCloseTime' => $this->tradeCloseTime,
])
->attachData($this->message,$this->filename,[
'mime'=>'text/plain'
]);
return $email;
}
Now I need to set metadata of the file to be attached in email eg. Author etc.
You need to create the file on the server. That being said you can delete it directly after. There is a method for that:
return response()->download($pathToFile)->deleteFileAfterSend(true);

Categories