PhpMailer in Slim4 project

Hello
How can I send mails from my Controller with PhpMailer?

I add the PHP Mailer to my Continer:

$container->set('mail', function(){
	return new PHPMailer(true);
});

And give it to the Controller:

$container->set(ContactController::class, function($container){
	return new ContactController(
		$container->get('view'),
		$container->get('mail')
	);
});

And my controller:

class ContactController{

	protected $view;
	protected $mail;

	public function __construct(Twig $view, PhpMailer $mail){
		$this->view = $view;
		$this->mail = $mail;
	}
public function sendMail(Request $request, Response $response, $args){
		// send mail
		try {
		    //Server settings
		    $mail->SMTPDebug = SMTP::DEBUG_SERVER;                      // Enable verbose debug output
		    $mail->isSMTP();                                            // Send using SMTP
		    $mail->Host       = 'smtp1.example.com';                    // Set the SMTP server to send through
		    $mail->SMTPAuth   = true;                                   // Enable SMTP authentication
		    $mail->Username   = 'user@example.com';                     // SMTP username
		    $mail->Password   = 'secret';                               // SMTP password
		    $mail->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS;         // Enable TLS encryption; `PHPMailer::ENCRYPTION_SMTPS` encouraged
		    $mail->Port       = 587;                                    // TCP port to connect to, use 465 for `PHPMailer::ENCRYPTION_SMTPS` above

		    //Recipients
		    $mail->setFrom('from@example.com', 'Mailer');
		    $mail->addAddress('joe@example.net', 'Joe User');     // Add a recipient
		    $mail->addAddress('ellen@example.com');               // Name is optional
		    $mail->addReplyTo('info@example.com', 'Information');
		    $mail->addCC('cc@example.com');
		    $mail->addBCC('bcc@example.com');

		    // Content
		    $mail->isHTML(true);                                  // Set email format to HTML
		    $mail->Subject = 'Here is the subject';
		    $mail->Body    = 'This is the HTML message body <b>in bold!</b>';
		    $mail->AltBody = 'This is the body in plain text for non-HTML mail clients';

		    $mail->send();
		    die('Message has been sent');
		} catch (Exception $e) {
		    die("Message could not be sent.");
		}

		return $response->withHeader('Location', '/contact')->withStatus(301);
	}
}

I get the following error:
Message: Call to undefined method stdClass::isSMTP()

Can please someone help me?

Thank you very much.

  1. Do no inject PhPMailer to your controller. Keep it the thinnest possible. Controller delegates tasks. In your case to some service.
  2. Create some service. Inject it to your controller. Inject PhPMailer to your service. Serve mailing process within the service. Return mailing result from service to controller. Let the controller to decide what kind of response should be sent back to client.

First of all, you should try accessing PhpMailer via $this->mail within your controller. It might help.

As a rule of thumb, I would probably offload the mailing logic into a service as mentioned above, but it’s fine to leave it in the controller if you’re just trying to prototype something quickly.

You should look into mapping interfaces to the container instead of mapping strings $container->set('mail'), instead you should map the interface to an implementation as a definition and use auto wiring where you can.

@sim Please note that the container entry is an shared instances (aka “Singleton”). Be careful when you are sending serial mails with PhpMailer within on request or process, because it’s possible that you send Mails where you don’t want it :wink: Make sure that you always create a new instance from phpmailer before you send an email. A factory class could be useful here.

@odan thank you very much. Can you please tell me more about the factory classes? I’m a really newbie.
Do you also have an example. That would be really great.

Thank you very much!

@sim Here you can find more information about the Factory design pattern

Example Factory for PHPMailer

<?php

namespace App\Factory;

use PHPMailer\PHPMailer\PHPMailer;

final class MailerFactory
{
    private $settings;

    public function __construct(array $settings)
    {
        $this->settings;
    }

    public function createMailer(): PHPMailer
    {
        $mail = new PHPMailer(true);

        // Server settings
        $mail->SMTPDebug = $this->settings['debug'];
        $mail->isSMTP();
        $mail->Host = $this->settings['host'];
        $mail->SMTPAuth = (bool)$this->settings['auth'];
        $mail->Username = $this->settings['username'];
        $mail->Password = $this->settings['password'];
        $mail->SMTPSecure = $this->settings['password'];
        $mail->Port = (int)$this->settings['port'];

        return $mail;
    }
}
1 Like