0

I'm using this function in my shell to send email

Edit : UsersShell

<?php
namespace App\Shell;

use Cake\Console\Shell;
use Cake\Log\Log;
use Cake\Controller\Component;
use Cake\Controller\ComponentRegistry;
use App\Controller\Component\EmailComponent;

class UsersShell extends Shell
{
public function initialize()
{
    parent::initialize();
    $this->loadModel('Users');
    //Load Component 
    $this->Email = new EmailComponent(new ComponentRegistry());
}
public function mail()
{
    $to = 'exemple@gmail.com';
    $subject = 'Hi buddy, i got a message for you.';
    $message = 'User created new event';

    try {
        $mail = $this->Email->send_mail($to, $subject, $message);
        print_r($mail);
    } catch (Exception $e) {
        echo 'Message could not be sent. Mailer Error: ', $mail- 
 >ErrorInfo;
    }
    exit;   

}

I would like to know how can I call it in my controller ? here

Edit : Events is located in the plugins folder

EventsController

<?php

namespace FullCalendar\Controller;

use FullCalendar\Controller\FullCalendarAppController;
use Cake\Routing\Router;
use Cake\Event\Event;
use Cake\Console\ShellDispatcher;

class EventsController extends FullCalendarAppController
{
public $name = 'Events';

public function add()
{
    $event = $this->Events->newEntity();
    if ($this->request->is('post')) {
        $event = $this->Events->patchEntity($event, $this->request->data);
        if ($this->Events->save($event)) {

           /* $shell = new ShellDispatcher();
            $output = $shell->run(['cake', 'users'], ['plugin' => 
           'Events']);

            if (0 === $output) {
            $this->Flash->success('Success from shell command.');
            } else {
            $this->Flash->error('Failure from shell command.'); */

            $this->Flash->success(__('The event has been saved.'));
            return $this->redirect(['action' => 'index']);
        } else {
            $this->Flash->error(__('The event could not be saved. Please, 
    try again.'));
        }
    }
    $this->set('eventTypes', $this->Events->EventTypes->find('list'));
    $this->set(compact('event'));
    $this->set('_serialize', ['event']);
    $this->set('user_session', $this->request->session()- 
 >read('Auth.User'));
    $this->viewBuilder()->setLayout('user');
}

As you can see i used the shell dispatched i'm not sure if it's correct but i'm getting failure Thanks !

Edit :

EmailComponent

<?php
namespace App\Controller\Component;

use Cake\Controller\Component;
use Cake\Core\App;
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception;

require ROOT. '/vendor/phpmailer/phpmailer/src/Exception.php';
require ROOT. '/vendor/phpmailer/phpmailer/src/PHPMailer.php';
require ROOT. '/vendor/phpmailer/phpmailer/src/SMTP.php';

class EmailComponent extends Component {

public function send_mail($to, $subject, $message)
{
    // date_default_timezone_set('Asia/Calcutta');

    $sender = "exemple@gmail.com"; // this will be overwritten by GMail

    $header = "X-Mailer: PHP/".phpversion() . "Return-Path: $sender";

    $mail = new PHPMailer();

    $mail->SMTPDebug  = 2; // turn it off in production
    $mail->isSMTP();
    $mail->Host = 'smtp.gmail.com'; 
    $mail->SMTPAuth = true;
    $mail->Username   = "exemple@gmail.com";  
    $mail->Password   = "xxxx";
    $mail->SMTPSecure = "tls"; // ssl and tls
    $mail->Port = 587; // 465 and 587

    $mail->SMTPOptions = array (
        'tls' => array(
            'verify_peer' => false,
            'verify_peer_name' => false,
            'allow_self_signed' => true
        ),
        'ssl' => array(
            'verify_peer' => false,
            'verify_peer_name' => false,
            'allow_self_signed' => true
        )
    );

    $mail->From = $sender;
    $mail->FromName = "From Me";

    $mail->AddAddress($to);

    $mail->isHTML(true);
    $mail->CreateHeader($header);

    $mail->Subject = $subject;
    $mail->Body    = nl2br($message);
    $mail->AltBody = nl2br($message);

    // return an array with two keys: error & message
    if(!$mail->Send()) {
        return array('error' => true, 'message' => 'Mailer Error: ' . $mail->ErrorInfo);
    } else {
        return array('error' => false, 'message' =>  "Message sent!");
    }
}

}
  • 1
    https://stackoverflow.com/questions/28511023/how-to-load-a-component-in-console-shell read this answer and replace component with shell and it will be the very same. Sending an email should be an isolated object as well and not a component either. Good architecture would be to create an event, have a listener that creates an entry in a queue to send the email and then process the emails from a queue. The queue is a worker shell running all time in the background. There is even much more wrong with your code that doesn't fit in here. – floriank Jul 02 '18 at 09:34

2 Answers2

0

Correct me if I'm wrong. First your shell must be started something like this.

class UsersShell extends AppShell { 

      public function main(){ //change name here to main
         $to = 'exemple@gmail.com';
         $subject = 'Hi buddy, i got a message for you.';
         $message = 'User created new event';

         try {
             $mail = $this->Email->send_mail($to, $subject, $message);
             print_r($mail);
         } catch (Exception $e) {
             echo 'Message could not be sent. Mailer Error: ', $mail->ErrorInfo;
         }
         exit;   
     }       

}

By the way, if you want to check output, you must return something like true or false. Otherwise, there is no point to check output after execute the shell.

502_Geek
  • 2,046
  • 2
  • 22
  • 32
  • not necessarily check i edited post, i don't see why it's not working since it work fine when i lunch the shell alone –  Jul 02 '18 at 06:02
0

First Check Shell Command Run in CakePHP-CLI. Like this

bin/cake users mail

if shell command successfully running. Shell Class Fine.

Next Use Shell in Controller

<?php
namespace App\Controller;

use App\Controller\AppController;
use Cake\Console\ShellDispatcher;

class PagesController extends AppController
{
    /**
     * Run shell command
     */
    public function run()
    {
        $shell = new ShellDispatcher();
        $output = $shell->run(['cake', 'users', 'mail']);
        // $output = $shell->run(['cake', 'users', 'mail', 'email']); // [pass arguments]
        // debug($output);

        if ($output === 0) {
            echo "Shell Command execute";
        } else {
            echo "Failure form shell command";
        }

        exit;
    }
}

Change Shell Function : if mail not sent run $this->abort() function and return (int) 1 and mail sent successfully run $this->out() function and return (int) 0

/**
 * Send Mail with shell command
 */
public function mail()
{
    $to = 'mail@gmail.com';
    $subject = 'Hi buddy, i got a message for you.';
    $message = 'Nothing much. Just test out my Email Component using PHPMailer.';

    $mail = $this->Email->send_mail($to, $subject, $message);
    // debug($mail);
    if ($mail['error'] === false) {
        $this->out("Mail Successfully Sent For :: ". $to);
    } else {
        $this->abort("Mail Error.");
    }
}