I am using global from option in config/mail.php as mentioned in the documentation to use the same from address for all of my emails being sent. This works as expected. However, when I attempt to explicitly set a from address within the build function of a Mailable class, the global address is still used. Is there something I could be missing, all of this seems to come straight from the documentation for 5.4. My Mailable class is as follows (there is definitely a value in the $this->email property as it is displayed when echoed):
namespace App\Mail;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Contracts\Queue\ShouldQueue;
class ContactMessage extends Mailable
{
use Queueable, SerializesModels;
public $user_email;
public $user_message;
/**
* Create a new message instance.
*
* #return void
*/
public function __construct($user_email, $user_message)
{
$this->user_email = $user_email;
$this->user_message = $user_message;
}
/**
* Build the message.
*
* #return $this
*/
public function build()
{
// echo '<pre>';
// echo var_export($this->user_email, true);
// echo '<br/><br/>';
// echo var_export($this->message, true);
// die;
return $this->from($this->user_email)
->subject('Contact Message')
->view('mail.contactMessage');
}
}
Your code is correct. Thing is, setting the From header is a privileged operation in most MTA.
If you use sendmail, postfix, or other similars on a local machine you can usually set the From. However, when using an authenticated account at a third party, you usually cannot.
To change the From header with a third party, you need to either use an authenticated account that matches your From (eg with GMail), or configure the allowed From in your account (eg at AWS SES).
Related
I'm using Laravel 7, with queues and supervisor, and I have the following mail class:
<?php
namespace App\Mail;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
class Invoice extends Mailable
{
use Queueable, SerializesModels;
protected $item;
public function __construct($item)
{
$this->item = $item;
}
public function build()
{
$this->from('noreply#mydomain.com', $this->item->subscription->name)
->to($this->item->to['email'], $this->item->to['name'])
->subject($this->item->subject)
->replyTo($this->item->subscription->email, $this->item->subscription->name)
->view('mails/invoice')
->with('item', $this->item);
if ($this->item->bcc)
$this->bcc($this->item->bcc);
return $this;
}
}
As you can see, I use the function ->from($email, $name) to specify the header. The noreply#mydomain.com is permanent/fixed, but the $name isn't. It always tries to grab the subscription name.
What happens is that sometimes this works and sometimes it doesn't and I can' figure out why.
I want the emails to be sent always with the header according to my clients subscription name:
Google Company «noreply#mydomain.com»
Facebook Company «noreply#mydomain.com»
But sometimes it sends like this:
My SaaS Software «noreply#mydomain.com»
Because it grabs the content of the .env file. What I don't understand is why sometimes it works perfectly and sometimes it doesn't.
The variable $this->item->subscription content always exists. If it didn't exists, the replyTo() would also cause problems, which never causes.
EDIT:
The item variable contains the following:
$item = new \stdClass;
$item->invoice = $invoice;
$item->subscription = $subscription;
$item->subject = $subject;
$item->message = $message;
$item->to = $to;
$item->bcc = $bcc;
\Mail::queue(new \App\Mail\Invoice($item));
EDIT 2:
After applying the log::debug, the error occurred today and in the log it shows correctly:
Client Name «noreply#mydomain.com»
But the email received (i put my personal email as BCC) has the from as:
My SaaS Software «noreply#mydomain.com»
Solved (?).
I have read somewhere someone suggesting that some fields should be passed as an argument and apply it in the __construct, in case there were problems with queue.
So far, from all the emails I have seen, everything is working. The expected result is visible, it shows as: SomeCompany LTD «noreply#mydomain.com»
<?php
namespace App\Mail;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
class Invoice extends Mailable
{
use Queueable, SerializesModels;
protected $item;
public function __construct($item)
{
$this->item = $item;
// Initialize the <from> here & pass as an argument
$this->from($item->from['email'], $item->from['name']);
}
public function build()
{
$this->to($this->item->to['email'], $this->item->to['name'])
->subject($this->item->subject)
->replyTo($this->item->subscription->email, $this->item->subscription->name)
->view('mails/invoice')
->with('item', $this->item);
if ($this->item->bcc)
$this->bcc($this->item->bcc);
return $this;
}
}
I have been stuck in this for quite a while now. I am trying to extract messageID of an email through a callback function and store in DB for later use. I simulated the same conditions in a gmail based server and it works. But I don't think the email server has to do with anything. Here is my mailable class where I try to extract the messageID:
<?php
namespace App\Mail;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
use App\EmailLog;
use App\EmailLogDetail;
class GenericSendEmailMailable extends Mailable
{
//use Queueable, SerializesModels;
/**
* Create a new message instance.
*
* #return void
*/
private $applicationTemplate;
public $subject;
private $data;
private $emailLogId;
public function __construct(String $applicationTemplate,Array $data,String $subject, $emailLogId)
{
//
$this->applicationTemplate = $applicationTemplate;
$this->data = $data;
$this->subject = $subject;
$this->emailLogId = $emailLogId;
}
/**
* Build the message.
*
* #return $this
*/
public function build()
{
$emailLogId = $this->emailLogId;
$view = $this->applicationTemplate;
$data = $this->data;
$subject = $this->subject;
return $this->subject($subject)
->view($view,$data)
->withSwiftMessage(function ($message) use ($emailLogId){
$emailLog = EmailLog::where('id', $emailLogId)->first();
if(isset($emailLog->email_log_details)){
foreach($emailLog->email_log_details as $emailLogDetail){
$emailLogDetail->message_id = $message->getId();
$emailLogDetail->save();
}
}
});
}
}
Here, the $message->getId(); should be working fine but its not cause when I send mail and check the DB, the message Id is not stored. By the way, the email send operation is dispatched as a job. Any ideas as to why this is not working?
If anybody is interested in the future, this was due to the heavy processing inside the job. I was facing an execution timeout. I did two things, first I did any trivial processing before dispatching the job rather than in the job itself. And finally I increased the timeout by adding
public $timeout = 300;
in the job class. Also, I increased the "retry_after" in the driver I was using to just a bit more than the actual timeout (320 in my case).
The best way to identify the problem for a queue is to observe the worker.log file and determine whether any jobs failed or not. If failed, the reason (or exception) can be caught by creating a failed_jobs table in your database.
I'm trying to send an email using laravel however I keep getting the cannot access empty property error whenever I run my code.
I've done my research on the error and it seems to be usually caused by using a $ before the property name, example $this->$username instead of $this->username. However, that isn't the case in my code.
I can't really tell what's causing it nor do I have great experience in Laravel
Here's my mailable class:
<?php
namespace App\Mail;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Contracts\Queue\ShouldQueue;
class VerificationMail extends Mailable
{
use Queueable, SerializesModels;
public $data;
/**
* Create a new message instance.
*
* #return void
*/
public function __construct($data)
{
$this->data = $data;
}
/**
* Build the message.
*
* #return $this
*/
public function build()
{
$data2 = ['companyName' => $this->data['name'], 'verificationCode' => $this->data['verificationCode']];
return $this->from('noreply#REMOVED.com')
->$this->view('emails.verification', $data2);
}
}
My view is saved in resources/views/emails/verification.blade.php
I saw also that this error can sometimes be caused by using $message as variable name inside the views, however that isn't the case with me. I tried loading the view with a normal route without any mail sending involved and it loaded normally.
Can anyone spot it? Thanks.
You have error here:
return $this->from('noreply#REMOVED.com')
->$this->view('emails.verification', $data2);
Use following instead: (remove second $this->)
return $this->from('noreply#REMOVED.com')
->view('emails.verification', $data2);
Hello, I'm making a mail service in laravel, that supports attachment upload, when the user send me the file, I store it in a Amazon S3 driver for further attachment.
Here's my Mail class witch I send the mail object with the copies of email and attachments.
<?php
namespace App\Mail;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Storage;
use Illuminate\Contracts\Queue\ShouldQueue;
class Mail extends Mailable
{
use Queueable, SerializesModels;
public $email;
public $attachments;
public $copies;
/**
* Create a new message instance.
*
* #return void
*/
public function __construct($email, $copies = [], $attachments = [])
{
$this->email = $email;
$this->copies = $copies;
$this->attachments = $attachments;
}
/**
* Build the message.
*
* #return $this
*/
public function build()
{
$m = $this->from($this->email->sender->email, $this->email->sender->name)
->replyTo($this->email->sender->email, $this->email->sender->name)
->subject($this->email->subject);
foreach ($this->copies as $copy) {
if ($copy->type == 'CC') {
$m->cc($copy->destiny->email);
} else {
$m->bcc($copy->destiny->email);
}
}
if (!empty($this->attachments)) {
foreach ($this->attachments as $attachment) {
$attachmentParameters = [
"as" => $attachment->name,
"mime" => $attachment->mime
];
$m->attach(Storage::disk('s3Attachments')->url($attachment->path), $attachmentParameters);
}
}
return $m->view('emails.text-plain');
}
}
I've already used the dd(Storage::disk('s3Attachments')->url($attachment->path)) and confirmed that it is a string with the full path of the file like the documentation asks.
To add attachments to an email, use the attach method within the
mailable class' build method. The attach method accepts the full path
to the file as its first argument:
Then When I run the code, it brings this error:
[2018-05-05 20:58:52] testing.ERROR: Type error: Argument 2 passed to Illuminate\Mail\Message::attach() must be of the type array, null given, called in /home/lefel/Sites/happymail/vendor/laravel/framework/src/Illuminate/Mail/Mailable.php on line 311
I've tried using attach(), with just one argument:
$m->attach(Storage::disk('s3Attachments')->url($attachment->path));
But Same Error, I'm Using Laravel 5.5 with Amazon SES Driver, and already confirmed that I installed the following dependencies in my package.json:
composer require guzzlehttp/guzzle
"aws/aws-sdk-php": "~3.0"
I've searched the web and didn't find the solution, I need Help Please.
Regards.
I have just faced the exact same issue.
The problem is that you override the $attachments property.
Use another name for this variable and it will work!
This is my first time using events in Laravel/Lumen.
I am actually using Lumen and I am trying to dispatch an instance of Mailable when a new user signs up in order to send an email in the background.
I believe I have set it up right, but I keep getting this error...
Type error: Argument 1 passed to Illuminate\Mail\Mailable::queue() must implement interface Illuminate\Contracts\Queue\Factory, instance of Illuminate\Queue\DatabaseQueue given
I can't actually see within the error message itself where the issue is coming from e.g. there is no line numbers.
However, this is my code...
AuthenticationContoller.php
$this->dispatch(new NewUser($user));
NewUser.php
<?php
namespace App\Mail;
use App\Models\User;
use Illuminate\Mail\Mailable;
use Illuminate\Bus\Queueable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Contracts\Queue\ShouldQueue;
class NewUser extends Mailable implements ShouldQueue
{
use Queueable, SerializesModels;
protected $user;
public function __construct(User $user)
{
$this->user = $user;
}
/**
* Build the message.
*
* #return $this
*/
public function build()
{
return $this->view('test')->to('test#test.com', 'Test')
->from('test#test.com', 'test')->replyTo('test#test.com', 'test')
->subject('Welcome to the blog!');
}
}
I ran into the same issue. It seems like Lumen and Illuminate/Mailer don't work together all that well.
However I found quite an easy fix in a Github thread.
Basically you just have to create a new service provider in your app/Providers directory.
MailServiceprovider.php
<?php
namespace App\Providers;
use Illuminate\Mail\Mailer;
use Illuminate\Mail\MailServiceProvider as BaseProvider;
class MailServiceProvider extends BaseProvider
{
/**
* Register the Illuminate mailer instance.
*
* #return void
*/
protected function registerIlluminateMailer()
{
$this->app->singleton('mailer', function ($app) {
$config = $app->make('config')->get('mail');
// Once we have create the mailer instance, we will set a container instance
// on the mailer. This allows us to resolve mailer classes via containers
// for maximum testability on said classes instead of passing Closures.
$mailer = new Mailer(
$app['view'], $app['swift.mailer'], $app['events']
);
// The trick
$mailer->setQueue($app['queue']);
// Next we will set all of the global addresses on this mailer, which allows
// for easy unification of all "from" addresses as well as easy debugging
// of sent messages since they get be sent into a single email address.
foreach (['from', 'reply_to', 'to'] as $type) {
$this->setGlobalAddress($mailer, $config, $type);
}
return $mailer;
});
$this->app->configure('mail');
$this->app->alias('mailer', \Illuminate\Contracts\Mail\Mailer::class);
}
}
And then you just have to register this service provider in your bootstrap/app.php instead of the default one by adding the following line:
$app->register(\App\Providers\MailServiceProvider::class);