How to configure laragon/sendmail with Symfony - symfony

I'm trying to configure a Symfony 6.1 project to send mail through a fresh installed laragon and sendmail, but all my tries were unsuccessful.
I tried with many configuration and this one doesn't trigger error, but I don't receive any mail and any debug message :
#.env
MAILER_DSN=smtp://localhost
#php.ini
[mail function]
; For Win32 only.
; https://php.net/smtp
SMTP = localhost
; https://php.net/smtp-port
smtp_port = 25
; For Win32 only.
; https://php.net/sendmail-from
;sendmail_from = me#example.com
; For Unix only. You may supply arguments as well (default: "sendmail -t -i").
; https://php.net/sendmail-path
;sendmail_path =
; Force the addition of the specified parameters to be passed as extra parameters
; to the sendmail binary. These parameters will always replace the value of
; the 5th parameter to mail().
;mail.force_extra_parameters =
; Add X-PHP-Originating-Script: that will include uid of the script followed by the filename
mail.add_x_header = Off
sendmail_path="C:/laragon/bin/sendmail/sendmail.exe"
; The path to a log file that will log all mail() calls. Log entries include
; the full path of the script, line number, To address and headers.
;mail.log =
; Log mail to syslog (Event Log on Windows).
;mail.log = syslog
<?php
// src/Controller/MailerController.php
namespace App\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Mailer\Exception\TransportExceptionInterface;
use Symfony\Component\Mailer\MailerInterface;
use Symfony\Component\Mime\Email;
use Symfony\Component\Routing\Annotation\Route;
class MailerController extends AbstractController
{
#[Route('/email')]
public function sendEmail(MailerInterface $mailer): Response
{
$email = (new Email())
->from('noreply#mydomain.com')
->to('nobody#gmail.com')
->subject('Time for Symfony Mailer!')
->text('Sending emails is fun again!')
->html('<p>See Twig integration for better HTML integration!</p>');
try {
$mailer->send($email);
} catch (TransportExceptionInterface $e) {
die("debug:".$e->getDebug());
}
return new Response('ok');
}
}
The route to test : http://127.0.0.1:8000/email
Result :

Related

Corda - Failed to find a store at certificates\sslkeystore.jks

Corda open source on Linux. Node RPC SSL enabled. I am getting error "Failed to find a store at certificates\sslkeystore.jks". Any ideas? I have entered absolute path in keyStorePath.
You must follow the steps of this paragraph: https://docs.corda.net/clientrpc.html#wire-security which I detailed for you below.
When you enable RPC SSL, you must run this command one time (you will be asked to supply 2 new passwords):
java -jar corda.jar generate-rpc-ssl-settings
It will create the rpcsslkeystore.jks under certificates folder, and rpcssltruststore.jks under certificates/export folder.
Inside your node.conf supply the path and password of rpcsslkeystore.jks:
rpcSettings {
useSsl=true
ssl {
keyStorePath=${baseDirectory}/certificates/rpcsslkeystore.jks
keyStorePassword=password
}
standAloneBroker = false
address = "0.0.0.0:10003"
adminAddress = "0.0.0.0:10004"
}
Now if you have a webserver, inside NodeRPCConnection you must use the constructor that takes a ClientRpcSslOptions parameter:
// RPC SSL properties.
#Value("${config.rpc.ssl.truststorepath}")
private String trustStorePath;
#Value("${config.rpc.ssl.truststorepassword}")
private String trustStorePassword;
#PostConstruct
public void initialiseNodeRPCConnection() {
NetworkHostAndPort rpcAddress = new NetworkHostAndPort(host, rpcPort);
ClientRpcSslOptions clientRpcSslOptions = new ClientRpcSslOptions(Paths.get(trustStorePath),
trustStorePassword, "JKS");
CordaRPCClient rpcClient = new CordaRPCClient(rpcAddress, clientRpcSslOptions, null);
rpcConnection = rpcClient.start(username, password);
proxy = rpcConnection.getProxy();
}
We added above 2 extra attributes that you must now supply when starting the webserver, for that; modify your clients module build.gradle:
task runNodeServer(type: JavaExec, dependsOn: jar) {
classpath = sourceSets.main.runtimeClasspath
main = 'com.example.server.ServerKt'
args '--server.port=50005', '--config.rpc.host=localhost',
'--config.rpc.port=10005', '--config.rpc.username=user1', '--config.rpc.password=test',
'--config.rpc.ssl.truststorepath=/path-to-project/build/nodes/your-node/certificates/export/rpcssltruststore.jks',
'--config.rpc.ssl.truststorepassword=password'
}
If you're planning to connect to the node with a standalone shell, you must do something similar, but it didn't work for me; I reported the following bug: https://github.com/corda/corda/issues/5955

Clear FileSystemCache in Symfony 3.4

I use Symfony\Component\Cache\Simple\FilesystemCache;
It works when I $cache->set $cache->get $cache->clear() etc
I don't want to use a custom ttl. I want to clear the cache setted only with console.
But when I do php bin/console cache:clear, it doesn't clear cache I have set before with FilesystemCache.
I have tried to clear every pools with console but it doesn't clear $cache either.
1. Why it happens
Symfony's bin/console cache:clear command clears the cache only from kernel cache dir, which is var/cache/{env} by default.
When you create instance of FilesystemCache, you can provide a path where you want to store your cache as a 3rd parameter. Here's a signature of FilesystemCache constructor
public function __construct(string $namespace = '', int $defaultLifetime = 0, string $directory = null)
If you don't provide 3rd parameter it will end up as sys_get_temp_dir().'/symfony-cache', which is /tmp/symfony-cache on Linux.
As you can see it's a different directory and it won't be cleared by cache:clear command.
2. How to fix it
The proper way
You need to create your own data-cache:clear command. It's very simple https://symfony.com/doc/current/console.html
In execute() method of your command you should instantiate your FilesystemCache and call clear() on it. Example:
protected function execute(InputInterface $input, OutputInterface $output)
{
$cache = new FilesystemCache();
$cache->clear();
}
Then you can call php bin/console data-cache:clear from console.
If you decide to switch to some other caching engine in future (Redis, Memcached etc.) you can simply adjust that command to clear that cache.
The wrong way
It will only work if you keep using FilesystemCache and does not
provide fine-grained control of which cache you actually clear.
You can store your cache in kernel.cache_dir by passing a 3rd parameter to FilesystemCache when you instantiate it.
Example:
$cache = new FilesystemCache('', 0, $container->getParameter('kernel.cache_dir').'/data-cache');
or when configured as a service
Symfony\Component\Cache\Simple\FilesystemCache:
arguments:
- ''
- 0
- '%kernel.cache_dir%/data-cache'
This way Symfony's cache:clear command will work for you, but it's not a good idea to store these 2 types of cache in the same place.
If you change some of your project files, you may want to clear only
kernel cache in /var/cache while keeping your data cache intact and
vice versa. That's why I recommend not to use this solution!
It finally works, using AdapterInterface
<?php
namespace Gh\GhBundle\Manager;
use Symfony\Component\Cache\Adapter\AdapterInterface;
class AppManager
{
protected $_rootDir;
protected $_cache;
public function __construct($rootDir, AdapterInterface $cache)
{
$this->_rootDir = $rootDir;
$this->_cache = $cache;
}
/**
*
* Get version of this app
* #return string
*/
public function getVersion()
{
$cache = $this->_cache;
$numVersion = $cache->getItem('stats.num_version');
if (!$numVersion->isHit()) {
$version = !file_exists($this->_rootDir . '/RELEASE.TXT') ? 'dev' : file_get_contents($this->_rootDir . '/RELEASE.TXT');
$numVersion->set($version);
$cache->save($numVersion);
}
return $numVersion->get();
}
/**
*
* Get name of this app
* #return string
*/
public function getName()
{
return 'GH';
}
}

Symfony - run console command on kernel.terminate

I have configured swiftmailer to spool emails using file type. here is my swiftmailer config
swiftmailer:
transport: "%mailer_transport%"
host: "%mailer_host%"
username: "%mailer_user%"
password: "%mailer_password%"
spool:
type: file
path: "%kernel.root_dir%/../var/spool"
When I send any emails it perfectly spools. I run following command to dispatch emails thereafter.
bin/console swiftmailer:spool:send --env=dev
According to Symfony documentation
the console command should be triggered by a cron job or scheduled task and run at a regular interval.
My problem is, I cannot use crontab because cron can be configured with a minimum of 1 minute interval which I cannot afford. I want to make use of the background process with immediate execution after the response is sent back to browser, hence minimizing execution of spools to bare minimum.
I attempted to solve this problem by creating an event listener class and listening to kernel.terminate, and execute the command using shell_exec or exec function, here is the code for reference.
app.kernel.terminate.listener:
arguments: ["#kernel"]
class: AppBundle\EventListener\KernelTerminateListener
tags:
- { name: kernel.event_listener, event: kernel.terminate }
Here is my EventListener class
<?php
namespace AppBundle\EventListener;
use Symfony\Component\HttpKernel\Event\PostResponseEvent;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface;
use Cocur\BackgroundProcess\BackgroundProcess;
class KernelTerminateListener
{
protected $kernel;
protected $console;
public function __construct($kernel)
{
$this->kernel = $kernel;
$this->console = $this->kernel->getRootDir().'/../bin/console ';
}
public function onKernelTerminate(PostResponseEvent $event)
{
$command = $this->console.'swiftmailer:spool:send --env='.$this->kernel->getEnvironment();
shell_exec($command);
}
}
What I am trying in here is to run bin/console swiftmailer:spool:send --env=dev on kernel.terminate event, unfortunately this does not work, any hint on how to approach this problem is appreciated.
Thank you.
Please use the memory spool type of swift mailer, it does exactly what you want
When you use spooling to store the emails to memory, they will get sent right before the kernel terminates. This means the email only gets sent if the whole request got executed without any unhandled exception or any errors. To configure swiftmailer with the memory option, use the following configuration:
Instead of using shel_exec make use of process component,which will create a new process and command will be executed after response is sent.
shel_exec or exec will execute under same process which forces kernal to wait for completing request(because once parent process killed,child also terminates). Process component will create a new process,under that command will be executed.
use Symfony\Component\Process\Process;
....
....
....
public function onKernelTerminate(PostResponseEvent $event)
{
$command = $this->console.'swiftmailer:spool:send --env=.'$this->kernel->getEnvironment().'> output.log 2> out.log &';
$process = new Process($command);
$process->run();
}
Perhaps It was an issue with PHP, I am using MAMP and OSX comes pre-installed with PHP, basically, I got two php version installed, and for some reason, when I gave correct PHP path it worked, here is my updated listener class which I renamed to MailerSpoolListener
<?php
namespace AppBundle\EventListener;
use Symfony\Component\HttpKernel\Event\PostResponseEvent;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface;
use Cocur\BackgroundProcess\BackgroundProcess;
class MailerSpoolListener
{
protected $kernel;
protected $php;
protected $console;
protected $env;
protected $command;
protected $muteOutput;
public function __construct($kernel)
{
$this->kernel = $kernel;
$this->php = PHP_BINDIR.'/php';
$this->command = 'swiftmailer:spool:send';
$this->console = $this->kernel->getRootDir().'/../bin/console';
$this->env = $this->kernel->getEnvironment();
$this->muteOutput = '> /dev/null 2>/dev/null &';
}
public function onKernelTerminate(PostResponseEvent $event)
{
$command = $this->php.' '.$this->console.' '.$this->command.' --env='.$this->env.' '.$this->muteOutput;
$process = shell_exec($command);
}
}

How can be fixed an error of PHPUnit when other local address (then - http://localhost) is used

My app starts locally by http : //sm1/app/web/app_dev.php (symfony3).
PHPUnit test has been build by framework.
namespace Tests\AppBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
class GoodControllerTest extends WebTestCase
{
public function testCompleteScenario()
{
// Create a new client to browse the application
$client = static::createClient([], ['HTTP_HOST' => 'sm1']);
// Create a new entry in the database
$crawler = $client->request('GET', '/good/');
$this->assertEquals(200,
$client->getResponse()->getStatusCode(),
"Unexpected HTTP status code for GET /good/"
);
$crawler = $client->click(
$crawler->selectLink('Create a new entry')->link());
But after test running I've got an error
There was 1 error:
1) Tests\AppBundle\Controller\GoodControllerTest::testCompleteScenario
InvalidArgumentException: The current node list is empty.
/home/sm1/www/app/vendor/symfony/symfony/src/Symfony/Component/DomCrawler/Crawler.php:735
/home/sm1/www/app/tests/AppBundle/Controller/GoodControllerTest.php:18
and in a log file this message:
request.INFO: Matched route "{route}".
{"route":"good_index","route_parameters":
{"_controller":"AppBundle\Controller\GoodController::indexAction",
"_route":"good_index"},
"request_uri":"http://sm1/good/","method":"GET"} []
How to fix "request_uri" from "http : //sm1/good/"
to "http : //sm1/app/web/app_dev.php/good/" ?
It is necessary to start web app only by http://app. That is, to use PHPUnit you need a virtual host. If the name of the input script is different from the default, note this in the file .htaccess.

Symfony ExcelBundle in Command

i'll try to do something like:
<?php
namespace ExportBundle\Command;
use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\HttpFoundation\ResponseHeaderBag;
// I am extending ContainerAwareCommand so that you can have access to $container
// which you can see how it's used in method execute
class HelloCommand extends ContainerAwareCommand {
// This method is used to register your command name, also the arguments it requires (if needed)
protected function configure() {
// We register an optional argument here. So more below:
$this->setName('hello:world')
->addArgument('name', InputArgument::OPTIONAL);
}
// This method is called once your command is being called fron console.
// $input - you can access your arguments passed from terminal (if any are given/required)
// $output - use that to show some response in terminal
protected function execute(InputInterface $input, OutputInterface $output) {
// ask the service for a excel object
$phpExcelObject = $this->get('phpexcel')->createPHPExcelObject();
$phpExcelObject->getProperties()->setCreator("liuggio")
->setLastModifiedBy("Giulio De Donato")
->setTitle("Office 2005 XLSX Test Document")
->setSubject("Office 2005 XLSX Test Document")
->setDescription("Test document for Office 2005 XLSX, generated using PHP classes.")
->setKeywords("office 2005 openxml php")
->setCategory("Test result file");
$phpExcelObject->setActiveSheetIndex(0)
->setCellValue('A1', 'Hello')
->setCellValue('C1', 'Hello')
->setCellValue('B2', 'world!');
$phpExcelObject->getActiveSheet()->setTitle('Simple');
// Set active sheet index to the first sheet, so Excel opens this as the first sheet
$phpExcelObject->setActiveSheetIndex(0);
// create the writer
$writer = $this->get('phpexcel')->createWriter($phpExcelObject, 'Excel2007');
// The save method is documented in the official PHPExcel library
$writer->save('filename.xlsx');
// Return a Symfony response (a view or something or this will thrown error !!!)
return "A symfony response";
$greetLine = $input->getArgument('name')
? sprintf('Hey there %s', $input->getArgument('name'))
: 'Hello world called without arguments passed!'
;
$output->writeln($greetLine);
}
}
but throw me this error:
[Symfony\Component\Debug\Exception\UndefinedMethodException]
Attempted to call an undefined method named "get" of class "ExportBundle\Command\HelloCommand".
Did you mean to call e.g. "getAliases", "getApplication", "getDefinition", "getDescription", "getHelp", "getHelper"
, "getHelperSet", "getName", "getNativeDefinition", "getProcessedHelp", "getSynopsis" or "getUsages"?
in the line:
$phpExcelObject = $this->get('phpexcel')->createPHPExcelObject();
work fine in a Controller but in command not.
how I can make it work in command?

Resources