I had change pretend as true in mail config. please check http://laravel.com/docs/4.2/mail#mail-and-local-development
Now log is showing to address like this.
[2014-11-22 17:12:49] production.INFO: Pretending to mail message to: dinukathilanga#gmail.com, bbelekkaya#gmail.com [] []
But i need debug cc emails also. How can i do it?
This is my code.
Mail::send($view, $data, function($message) use ($to, $cc, $subject)
{
foreach ($to as $toUser) {
$message->to($toUser['email'], $toUser['first_name'] . ' ' . $toUser['last_name']);
}
foreach ($cc as $ccUser) {
$message->cc($ccUser['email'], $ccUser['first_name'] . ' ' . $ccUser['last_name']);
}
$message->subject($subject);
});
Allow me to be frank here. I am new to Laravel, but I will try my best to explain this.
I do know how to debug email platforms though, the easiest process is by doing it through C.
I will try to be succint as possible.
Firstly, try using the laravel-debugbar (the latest version is 4).
This is an application that is capable of filtering the PHP Debug Bar.
By using this application you will be able to attach and edit output functions (here is the link for more information: Debug bar.
If this won't work, try debugging through C.
Fristly, you will compile the C program by inserting the debug option, option -g.
Afterwards, you'll launch the gdb into the platform.
Thirdly, you'll break the point in the C program, specifically, insert the break line_number function.
After that, you'll print the variable values in the gdp debugger.
For instance, you'll type commands such as print j and (gdp) p i (I will post the website where I've got this information from; it will give you a more broader walkthrough).
There are various operation for this process.
I strongly advise you visiting:Debug C program using gdb. Hope this helped.
Create a new class named ExtendedMailer for the sake of this example and save the file somewhere the autoloader is able to find it. Depending on where you put the file, you may need to run composer dump-autoload once you've saved it.
<?php
use Illuminate\Mail\Mailer;
class ExtendedMailer extends Mailer
{
protected function logMessage($message)
{
parent::logMessage($message);
$emails = implode(', ', array_keys((array) $message->getCc()));
$this->logger->info("Pretending to mail message to: {$emails}");
}
}
Create a new service provider, somewhere your application is able to load classes. As above, you may need to run composer dump-autoload
The below code simply extends the original MailServiceProvider but allows us to bind a different class to in the IoC, you'll notice the new ExtendedMailer; the class we created earlier. Obviously if you namespaced the class, reflect that change here.
<?php
use Illuminate\Mail\MailServiceProvider;
class ExtendedMailServiceProvider extends MailServiceProvider
{
/**
* Register the service provider.
*
* #return void
*/
public function register()
{
$me = $this;
$this->app->bindShared('mailer', function($app) use ($me)
{
$me->registerSwiftMailer();
// 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 ExtendedMailer(
$app['view'], $app['swift.mailer'], $app['events']
);
$this->setMailerDependencies($mailer, $app);
// If a "from" address is set, we will set it on the mailer so that all mail
// messages sent by the applications will utilize the same "from" address
// on each one, which makes the developer's life a lot more convenient.
$from = $app['config']['mail.from'];
if (is_array($from) && isset($from['address']))
{
$mailer->alwaysFrom($from['address'], $from['name']);
}
// Here we will determine if the mailer should be in "pretend" mode for this
// environment, which will simply write out e-mail to the logs instead of
// sending it over the web, which is useful for local dev environments.
$pretend = $app['config']->get('mail.pretend', false);
$mailer->pretend($pretend);
return $mailer;
});
}
}
In your config/app.php, you'll find a line which looks like
'Illuminate\Mail\MailServiceProvider',
You'll need to comment it out and add a line as below
'ExtendedMailServiceProvider',
What this does is replace the mailer which Laravel knows about with the one you've just created. The one you've just created is the same as the default one as it merely extends it, and adds functionality to the logMessage function.
Related
Symfony provides a way to send all emails to a specific email address during debugging and development but addressees in the BCC still receive the e-mail. This is very dangerous because you don't want to send out any emails from your local dev environment.
Is there a way to also deliver BCCs to a specific email address?
I wouldn't discount having your own wrapper service for Mailer. I have to admit I usually do that, since more often than not I consider the sending of emails too close to the application concerns, and I may want more freedom and flexibility than simply coupling myself to the frameworks package, as good as it may be.
That being said, Symfony's method of changing the recipients does not work with Bcc, because Bcc is part of the message, while the listener that changes the recipients manipulates the envelope.
You could create your own EventListener to manipulate the bcc header:
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\Mailer\Event\MessageEvent;
use Symfony\Component\Mime\Message;
class ManipulateBcc implements EventSubscriberInterface
{
private bool $removeExisting;
private array $forcedBcc;
public function __construct(bool $removeExisting = false, array $forcedBcc = [])
{
$this->removeExisting = $removeExisting;
$this->forcedBcc = $forcedBcc;
}
public static function getSubscribedEvents(): array
{
return [
MessageEvent::class => ['onMessage', -224],
];
}
public function onMessage(MessageEvent $event): void
{
if ( ! $this->removeExisting) {
return;
}
$message = $event->getMessage();
if ( ! $message instanceof Message) {
return;
}
$headers = $message->getHeaders();
if ($headers->has('bcc')) {
$headers->remove('bcc');
}
if ( ! empty($this->forcedBcc)) {
$headers->addMailboxListHeader('bcc', $this->forcedBcc);
}
}
}
By default, this does nothing. With the default configuration the eventlistener will be run but since removeExisting will be false, the listener will return without doing anything.
To enable it, you could add the following to services_dev.yaml, so it's only enabled during development:
# config/services_dev.yaml
services:
App\EventDispatcher\ManipulateBcc:
autoconfigure: true
arguments:
$removeExisting: true
$forcedBcc:
- 'fake.email#mailinator.com'
- 'even.faker#mailinator.com'
This was hastily written, and you cannot force BCCs without removing BCCs, which may be sufficient for many purposes but maybe not to your own. Use this as a starting point until it does what you need.
The only way which I think of right now is to create your own wrapper service for the mailer and check the environment if it’s dev just remove the BCC... you don’t need them anyway.
Currently, I am trying to integrate Mandrill functionality into a Zend 1 legacy application, and I'm not too familiar with the way they handle mail transports. Currently, I'm including the mandrill/mandrill composer package and attempting to follow the pattern of the other transport layers included in Zend 1:
class MandrillTransport extends Zend_Mail_Transport_Abstract
{
private $message = array();
protected function _formatMandrillArray()
{
//grab all the relavant data from the pre-existing mail object and put it into a Mandrill-friendly array
}
protected function _getAttachments() {
//loop through and format attachments that get added to array
}
protected function _sendMail()
{
//send Mandrill message with included data
$mandrill = new Mandrill(Zend::registry('config')->mandrill->APIKey);
$mandrill->messages->send($this->message);
}
public function send() {
//Format all the stuff and send it
}
}
And then I'm assuming I can use this in the "send()" function, which appears to take the transport as a parameter:
//TODO: Put this in a better spot
require_once __DIR__ . "/ZendFramework/Zend/Mail/Transport/MandrillTransport.php";
$tr = new MandrillTransport();
$email->send($tr);
Am I on the right track here? The reason I'd like to do this as a transport layer rather than just ripping out the existing code and replacing it with Mandrill is because there are a lot of different business processes sending mail, and we'd like to be able to pick and choose which is using the Sendmail transport and which are using Mandrill.
Thanks in advance,
-Chris
I need to send hundreds of emails using different credentials from laravel.
Each customer of mine has his/hers mail list and needs to provide their own SMTP server. I process that list and send emails on customer's behalf.
This is what I have so far. It is working, but it is very slow and I don't have many emails so far. I see a problem when I get more emails.
Any suggestions on how to improve?
PS- I use cron Console Command and use Kernel to schedule the job.
public function sendMailings($allMailings) {
foreach ($allMailings as $email) {
Config::set('mail.host', $email['smtpServer']);
Config::set('mail.port', $email['smtpPort']);
Config::set('mail.username', $email['smtpUser']);
Config::set('mail.password', $email['smtpPassword']);
Config::set('mail.encryption', $email['smtpProtocol']);
Config::set('mail.frommmail', trim($email['fromEmail']));
Config::set('mail.fromuser', trim($email['fromUser']));
Config::set('mail.subject', trim($email['subject']));
Config::set('mail.toEmail', trim($email['toEmail']));
Config::set('mail.toName', trim($email['toName']));
Config::set('mail.pretend', false);
$email_body = $email['emailBody'];
Mail::send('emails.availability, compact('email_body')
, function($message) {
$message->from(config('mail.username'), config('mail.fromUser'));
$message->replyTo(config('mail.frommmail'), config('mail.fromUser'));
$message->to(config('mail.toEmail'), config('mail.toName'))->subject(config('mail.subject'));
});
Log::info('Mail was sent');
}
}
You can not change email provider configs on-the-fly, so you must make new instance of mailer in service container. I did it before, i wrote a method in my own class to get new mailer instance:
/**
* #return Mailer
*/
protected function getMailer()
{
// Changing mailer configuration
config(['mail.driver' => static::getName()]);
// Register new instance of mailer on-the-fly
(new MailServiceProvider($this->container))->register();
// Get mailer instance from service container
return $this->container->make('mailer');
}
Sending e-mail messages directly in web app can drastically slow down the responsiveness of your application. You should always queue your messages.
Instead of Mail::send You can use Mail::queue
and then from cron or manually call
php artisan queue:work
That will process the next item on the queue. This command will do nothing if the queue is empty. But if there’s an item on the queue it will fetch the item and attempt to execute it.
I've heard a lot about monolog(https://github.com/Seldaek/monolog) & trying to use that in one of our app. But, can't able to fig. out how to use that. Don't know it's I'm only can't able to get any documentation of it or really it has no documentation at all.
We want to log all our errors in DB & as well as send an email notification about error when it'll get generate. For sending email we are using Swiftmailer(swiftmailer.org).
I can be able to run this sample code from Github link,
<?php
use Monolog\Logger;
use Monolog\Handler\StreamHandler;
// create a log channel
$log = new Logger('name');
$log->pushHandler(new StreamHandler('path/to/your.log', Logger::WARNING));
// add records to the log
$log->addWarning('Foo');
$log->addError('Bar');
but can't able to understand how to use this with DB & any other email library.
You posted an example yourself. Instead of StreamHandler use one or more of the other handlers that monolog is offering.
You have to look into the code of the handlers to see which dependencies they need. Look inside the Monolog directory and you'll find the Handler classes. Code is the most reliable documentation.
<?php
use Monolog\Logger;
use Monolog\Handler\SwiftMailerHandler;
use Swift_Mailer;
// ... more dependencies you need
// create your Swift_Mailer and Swift_Message instances
$handlers = [
new SwiftMailerHandler($swiftMailer, $swiftMessage),
// add more handler you need
];
$log = new Logger('name', $handlers);
$log->warning('Foo');
$log->error('Bar');
You have to create a Swift_Mailer and Swift_Message instance for the SwiftMailerHandler. Instead of pushHandler, you can add an array of handlers into the Logger constructor.
The Swift_Message instance is used for every log message where the message replaces every time the mail body.
I can only suggest to you to read the monolog code for information where a further documentation is missing.
I use Mandrill mail driver for tests. I have a remote staging, that I seed after deploy. And during seeding I try to disable email sends, that are linked to certain events.
Placing this in seeder:
Config::set('mail.driver', 'log');
Config::set('mail.pretend', true);
Has no effect. I don't understand why. I place this in root DatabaseSeeder#run or/and in child seeders — the same. Calls to Mandrill are still performed.
Is there a solution for this problem?
The reason your
Config::set('mail.driver', 'log');
Config::set('mail.pretend', true);
aren't working is because the mail object doesn't check these values before sending mail. Whaaaaaaaa?. If you take a look at the sendSwiftMessage method in the mailer class
#File: vendor/laravel/framework/src/Illuminate/Mail/Mailer.php
protected function sendSwiftMessage($message)
{
if ($this->events)
{
$this->events->fire('mailer.sending', array($message));
}
if ( ! $this->pretending)
{
$this->swift->send($message, $this->failedRecipients);
}
elseif (isset($this->logger))
{
$this->logMessage($message);
}
}
You can see the class checks $this->pretending, and not the configuration, before deciding if it should send the mail or not. So what sets pretending? That's in the MailServiceProvider class's register method.
public function register()
{
//...
$pretend = $app['config']->get('mail.pretend', false);
$mailer->pretend($pretend);
//...
}
When Laravel boots up and registers each service provider, it eventually registers the mail service provider and that's when it reads the configuration, and then tells the mailer if it should "pretend" or not. By the time you're calling this in your seeder, the mailer's already loaded it's configuration value.
Fortunately, there's a pretty easy solution. The mailer object is a singleton/shared service, and has public methods available to control if it should pretend or not. Just call the pretend method yourself instead of setting configuration values
Mail::pretend(true); //using the `Mail` facade to access the mailer object.
you should be able to turn the mailer off programatically.
This is an answer for Laravel 5.7, because pretend doesn't exists:
If you want to disable mail while seeding the database, you could simply 'abuse'
Mail::fake()
I think in two possibilities, you can try:
You can set the command to enable the mail pretend on-the-fly:
Mail::pretend();
The db seed are running with more than one request:
As is write here:
Configuration values that are set at run-time are only set for the
current request, and will not be carried over to subsequent requests.
So you can try set this config over requests, like a session, than finish in the end of the seeding.