We have moved our forum to GitHub Discussions. For questions about Phalcon v3/v4/v5 you can visit here and for Phalcon v6 here.

Which mailer and how to install

Hi again,

i need a mailer, which can i use and how should i install it. Do someone has an idea for me.

Thank you in advance.

Rgds

Stefan

edited Oct '15

Use Swift Mailer: https://github.com/swiftmailer/swiftmailer

Put it anywhere you want in your application and then create service:

$di->set('mailer',function() use ($config) {
   include 'path to swift_required.php';
    $transport = Swift_SmtpTransport::newInstance($config->smtp->address,$config->smtp->port)
        ->setUsername($config->smtp->username)
        ->setPassword($config->smtp->password);
    $mailer = Swift_Mailer::newInstance($transport);
    return $mailer;
});

Where $config is ini file with smtp username, password, address and port.

Also i STRONGLY RECOMMEND to sending emails using queue, benstalkd and crontab, especially if you have many mails and IMHO MUST if you send mails in foreach, not during response.

Here i wrote comment about using queue, beanstalkd and crontab for handling of mail sending: https://forum.phalcon.io/discussion/9157/how-to-run-php-function-after-redirecting-user-to-another-page#C25513



59.9k

Hi Jurigag,

thank you for your answer, i will try it :-)

Rgds

Stefan



59.9k

Hi Jurigag,

i am sorry but i can't get it to run, here are my questions:

  1. How looks the config.ini?
  2. How looks the directory structure?
  3. Where do i implemet the MailTask?

Please can you help me?

Rgds

Stefan

[smtp] address = address of your mail server port = port of your mail server username = your username password = your password

  1. In my application config.ini is put in /app/config under root directory, swift_mailer library is put under /lib/swift, and services.php is put under /app/
  2. You implement it in cli, i have implemented it in /cli/tasks under root directory, and cli boostrap file is under /cli/

What problems you have ? Just write here your errors.



59.9k
edited Nov '15

Hi Jurigag,

thank you for your reply and your help :-)

I have problems to understand the general structure of the mailer code, in the past i used phpmailer with jquery ajax url. Do i have my replace my bootstrap which i have used until now, or do i just have to replace some code?

This is my index bootstrap:

<?php

use Phalcon\Loader;
use Phalcon\Mvc\View;
use Phalcon\Mvc\Application;
use Phalcon\DI\FactoryDefault;
use Phalcon\Mvc\Url as UrlProvider;
use Phalcon\Db\Adapter\Pdo\Mysql as DbAdapter;
use Phalcon\Config\Adapter\Ini as ConfigIni;

try {

// Register an autoloader
$loader = new Loader();
$loader->registerDirs(array(
    '../app/frontend/controllers/',
    '../app/frontend/models/',
    '../app/frontend/config/'
))->register();

$loader->registerNamespaces(
  array(
  '../app/frontend/forms/'
 )
)->register();

// Create a DI
$di = new FactoryDefault();

// Setup the view component
$di->set('view', function(){
$view = new \Phalcon\Mvc\View();
$view->setViewsDir('../app/frontend/views/');

    $view->registerEngines(array(
        '.volt' => function($view, $di) {
        $volt = new \Phalcon\Mvc\View\Engine\Volt($view, $di);
        $volt->setOptions(array(
          'compiledPath' => '../app/compiled/',
          'stat' => true,
          'compileAlways' => true
        ));
        return $volt;
        }
    ));

return $view;
});

// Setup a base URI so that all generated URIs include the "tutorial" folder
$di->set('url', function(){
    $url = new UrlProvider();
    $url->setBaseUri('/projects/fletcher-phalcon/');
    return $url;
});

define('BASE_DIR', dirname(__DIR__));
define('APP_DIR', BASE_DIR . '/app');

$config = include APP_DIR . '/frontend/config/config.php';

$di->set('mailer',function() use ($config) {
    include 'vendor/swiftmailer/lib/swift_required.php';
    $transport = Swift_SmtpTransport::newInstance($config->smtp->address,$config->smtp->port)
        ->setUsername($config->smtp->username)
        ->setPassword($config->smtp->password);
    $mailer = Swift_Mailer::newInstance($transport);
    return $mailer;
});

define('VERSION', '1.0.0');
// Using the CLI factory default services container
$di = new Cli();
// Define path to application directory
defined('APPLICATION_PATH')
|| define('APPLICATION_PATH', realpath(dirname(__FILE__)));
/**
 * Register the autoloader and tell it to register the tasks directory
 */
$loader = new \Phalcon\Loader();
$loader->registerDirs(
array(
    APPLICATION_PATH . 'app/tasks'
)
);
// Loading your classes
$loader->register();
$config = new Ini(APPLICATION_PATH."/../app/config/config.ini");
// Create a console application
$console = new ConsoleApp();
$console->setDI($di);
$di->set('queue', function () {
$queue = new Beanstalk(
    array(
        'host' => '127.0.0.1',
        'port' => '11300'
    )
);
return $queue;
});
$di->set('mailLogger', function () {
$mailLogger = new Phalcon\Logger\Adapter\File(APPLICATION_PATH."/logs/mail-log-" . date('Y-m-d') . ".log");
return $mailLogger;
});
$di->set('mailer', function () use ($config) {
include APPLICATION_PATH.'/../lib/swift/swift_required.php';
$transport = Swift_SmtpTransport::newInstance($config->smtp->address, $config->smtp->port)
    ->setUsername($config->smtp->username)
    ->setPassword($config->smtp->password);
$mailer = Swift_Mailer::newInstance($transport);
return $mailer;
});
/**
 * Process the console arguments
 */
$arguments = array();
foreach($argv as $k => $arg) {
if($k == 1) {
    $arguments['task'] = $arg;
} elseif($k == 2) {
    $arguments['action'] = $arg;
} elseif($k >= 3) {
    $arguments['params'][] = $arg;
}
}
// Define global constants for the current task and action
define('CURRENT_TASK', (isset($argv[1]) ? $argv[1] : null));
define('CURRENT_ACTION', (isset($argv[2]) ? $argv[2] : null));

// Handle the request
$application = new Application($di);

echo $application->handle()->getContent();

} catch (\Exception $e) {
 echo "PhalconException: ", $e->getMessage();
}

In app/tasks i have set the MailTask.php, which can't be loaded and the variable $argv is undefined. Or ist he cli bootstrap seperatedf rom the index bootstrap?

Thx again Jurigag

Rgds

Stefan

CLI boostrap is Command Line Interface Boostrap - for command line application. You have 2 boostrap files - one for cli app, one for normal app, you can place mailer in both, but you should sending mails only by cli using queue, tasks and cron.



59.9k
edited Nov '15

Hi Jurigag,

now i have this exception: PhalconException: CliController handler class cannot be loaded, how looks my form action /cli/task/send?

This is my Directory structure:

/app
 /frontend
  /config
   config.ini
   services.php
/cli
 /task
   index.php
 index.php
/lib
  swift_required.php
/public

config.ini

 [smpt]
 address = 'xxxxx'
 port = xxxxx
 security = 'xxxxx',
 username = 'xxxxx',
 password = 'xxxxx'

Cli index.php

<?php
use Phalcon\CLI\Console as ConsoleApp;
use Phalcon\Config\Adapter\Ini;
use Phalcon\Di\FactoryDefault\Cli;
use Phalcon\Logger;
use Phalcon\Mvc\Model\Manager;
use Phalcon\Queue\Beanstalk;

define('VERSION', '1.0.0');
// Using the CLI factory default services container
$di = new Cli();
// Define path to application directory
defined('APPLICATION_PATH')
|| define('APPLICATION_PATH', realpath(dirname(__FILE__)));
/**
* Register the autoloader and tell it to register the tasks directory
 */
$loader = new \Phalcon\Loader();
$loader->registerDirs(
array(
    APPLICATION_PATH . 'cli/task/'
)
);
// Loading your classes
$loader->register();  
$config = new Ini(APPLICATION_PATH."/../app/frontend/config/config.ini");
// Create a console application
$console = new ConsoleApp();
$console->setDI($di);
$di->set('queue', function () {
$queue = new Beanstalk(
    array(
        'host' => '127.0.0.1',
        'port' => '11300'
    )
);
return $queue;
});
$di->set('mailLogger', function () {
$mailLogger = new Phalcon\Logger\Adapter\File(APPLICATION_PATH."/logs/mail-log-" . date('Y-m-d') .       ".log");
return $mailLogger;
});
$di->set('mailer', function () use ($config) {
include APPLICATION_PATH.'/../lib/swift/swift_required.php';
$transport = Swift_SmtpTransport::newInstance($config->smtp->address, $config->smtp->port)
    ->setUsername($config->smtp->username)
    ->setPassword($config->smtp->password);
$mailer = Swift_Mailer::newInstance($transport);
return $mailer;
});

$arguments = array();
foreach($argv as $k => $arg) {
if($k == 1) {
    $arguments['task'] = $arg;
} elseif($k == 2) {
    $arguments['action'] = $arg;
} elseif($k >= 3) {
    $arguments['params'][] = $arg;
}
}
// Define global constants for the current task and action
define('CURRENT_TASK', (isset($argv[1]) ? $argv[1] : null));
define('CURRENT_ACTION', (isset($argv[2]) ? $argv[2] : null));
try {
// Handle incoming arguments
$console->handle($arguments);
} catch(\Phalcon\Exception $e) {
echo $e->getMessage();
exit(255);
}

task index.php

  require __DIR__ . '/../../lib/swift_required.php';

        class Mail extends Phalcon\Mvc\User\Component {
            protected $_transport;

            public function send($to, $subject, $name, $params) {
                $config = new Phalcon\Config\Adapter\Ini(__DIR__ . '/../../config/config.ini');
                $mailConfig = $config->mail;

                $template = $this->getTemplate($name, $params);
                // Create the message
                $message = Swift_Message::newInstance()
                    ->setSubject($subject)
                    ->setTo($to)
                    ->setFrom(array(
                        $mailConfig->fromEmail => $mailConfig->fromName
                    ))
                    ->setBody($template, 'text/html');
                if (!$this->_transport) {
                    $this->_transport = Swift_SmtpTransport::newInstance(
                        $mailConfig->smtpServer,
                        $mailConfig->smtpPort,
                        $mailConfig->smtpSecurity
                    )
                        ->setUsername($mailConfig->smtpUsername)
                        ->setPassword($mailConfig->smtpPassword);
                }
                // Create the Mailer using your created Transport
                $mailer = Swift_Mailer::newInstance($this->_transport);
                $mailer->send($message);

            }
            public function getTemplate($name, $params) {
                $parameters = array_merge(array(
                    'publicUrl' => "website.com",
                ), $params);
                return $this->view->getRender('emailTemplates', $name, $parameters, function($view){
                    $view->setRenderLevel(View::LEVEL_LAYOUT);
                });
                return $view->getContent();
            }
        }

Do you have somewhere an live example?

Thx again Jurigag

Rgds

Stefan

But whats is clicontroller ? Where are you calling it ? From command line ? There are no such a thing as clicontroller in cli application. Task code is pretty simple:

<?php
use Phalcon\Cli\Task;
use Phalcon\Logger\Adapter\File;
use Phalcon\Queue\Beanstalk;

/**
 * Created by PhpStorm.
 * User: User
 * Date: 30.09.15
 * Time: 13:04
 */
class MailTask extends Task
{
    /**
     * @var Beanstalk
     */
    protected $queue;
    /**
     * @var Swift_Mailer
     */
    protected $mailer;
    /**
     * @var File
     */
    protected $mailLogger;

    public function initialize()
    {
        $this->queue = $this->di->get('queue');
        $this->mailer = $this->di->get('mailer');
        $this->mailLogger = $this->di->get('mailLogger');
    }

    public function sendAction()
    {
        $this->queue->watch('mail');
        while ($this->queue->stats()["current-jobs-ready"] > 0 && ($job = $this->queue->reserve())) {

            $message=$job->getBody()['mail'];
            if($this->mailer->send($message)){
                $this->mailLogger->info(PHP_EOL."Mail Sended: ".PHP_EOL.
                "Subject: ".$message->getSubject().PHP_EOL.
                "To: ".json_encode($message->getTo()).PHP_EOL.
                "Reply To: ".json_encode($message->getReplyTo()).PHP_EOL.
                "From: ".json_encode($message->getFrom()).PHP_EOL.
                "=======================================================");
            }
            else{
                $this->mailLogger->error(PHP_EOL."Mail Failed: ".PHP_EOL.
                    "Subject: ".$message->getSubject().PHP_EOL.
                    "To: ".json_encode($message->getTo()).PHP_EOL.
                    "Reply To: ".json_encode($message->getReplyTo()).PHP_EOL.
                    "From: ".json_encode($message->getFrom()).PHP_EOL.
                    "=======================================================");
            };

            $job->delete();
        }
    }
}

Your Mail should extends Task, not component. And somwhere in app you are rendering view, setting where to send from who etc, just prepare whole email, putting to queue and let your task only to just send it - cuz it cost a most of time.



59.9k

Hi Jurigag,

thank you so much for your help, but i will try something else. I can't get it run and i don't really understand this structure.

Wish you the best.

Rgds

Stefan