Mail Plugin

A powerful email management plugin for Festi Framework that provides a flexible system for sending emails, managing templates, and logging all communications.

Features

  • Email template management through admin interface
  • SMTP support
  • HTML emails with template system
  • Email attachments
  • Comprehensive logging system
  • Extensible through hooks

Installation

Requirements

  • PHPMailer library
    composer require phpmailer/phpmailer:^6.5

Setup

  1. Add the plugin to your project.
  2. Migrate the database install/install.[mysql|pgsql].sql
  3. Configure the project in config.php:
// Define cache path
define('MAIL_CACHE_PATH', '/path/to/cache/dir/');

// OR use global config
$GLOBALS['config']['paths'] = array(
    'cache' => FS_ROOT.'cache'.DIRECTORY_SEPARATOR
);

// SMTP Configuration (optional)
$GLOBALS['config']['smtp'] = array( 
    'from'      => '[email protected]',
    'host'      => 'ssl://smtp.yourdomain.com',
    'port'      => '465',
    'auth'      => true,
    'username'  => 'your-username',
    'password'  => 'your-password'
);

Usage

Creating Email Templates

Create a template in the database:

INSERT INTO `email_templates` (`ident`, `caption`, `subject`, `body`) VALUES
('welcome_email', 'Welcome Email', 'Welcome to our service, <?php echo $user->name; ?>', '<html><body>Thank you for joining our service!<br/><br/>Your account details:<br/><?php echo $user->details; ?></body></html>');

Sending Emails

Basic usage:

// Data to be used in the email template
$emailData = array(
    'user' => $userObject
);

// Send the email
$this->plugin->mail->send(
    '[email protected]',   // Recipient email (string or array)
    'welcome_email',           // Template identifier
    $emailData                 // Data for template
);

With attachments:

$files = array(
    '/path/to/file1.pdf',
    '/path/to/file2.jpg'
);

$this->plugin->mail->send(
    array('[email protected]', '[email protected]'),  // Multiple recipients
    'invoice_email',
    $emailData,
    $files                                           // Attachments
);

Advanced Configuration

Custom email headers:

$emailData = array(
    'mail_from'      => '[email protected]',       // Custom sender email
    'mail_from_name' => 'Custom Sender Name',       // Custom sender name
    'charset'        => 'UTF-8',                    // Custom charset
    'replay_email'   => '[email protected]',     // Reply-to email
    'replay_name'    => 'Reply Name'                // Reply-to name
);

$this->plugin->mail->send('[email protected]', 'template_ident', $emailData);

Display all recipients in a single email (BCC off):

$this->plugin->mail->setDisplayRecipients(true);
$this->plugin->mail->send(array('[email protected]', '[email protected]'), 'template_ident', $data);

Email Templates with Layouts

Create a template file in plugins/Mail/templates/:

// plugins/Mail/templates/welcome.phtml
<html>
    <head>
        <title><?php echo $title; ?></title>
    </head>
    <body>
        <div class="header">Welcome to Our Service</div>

        <div class="content">
            <?php echo $mailBody; ?>
        </div>

        <div class="footer">
            Best regards,<br>
            The Team
        </div>
    </body>
</html>
Update email template to use file:

Update your email template to use this layout:

UPDATE `email_templates` 
SET `template` = 'welcome', `title` = 'Welcome Email' 
WHERE `ident` = 'welcome_email';

Admin Interface

Setting Up Email Template Management

Execute the following SQL to create the necessary permissions:

INSERT INTO `festi_sections` (`caption`, `ident`, `mask`)
VALUES ('Manage Email Templates', 'manage_email_templates', '6');

SET @id_section_manage_email_templates = (SELECT `id`
                                  FROM `festi_sections`
                                  WHERE `ident` = 'manage_email_templates');

SET @id_user_type_admin = (SELECT `id`
                           FROM `users_types`
                           WHERE `ident` = 'admin');

INSERT INTO `festi_sections_user_types_permission` (`id_section`, `id_user_type`, `value`)
VALUES (@id_section_manage_email_templates, @id_user_type_admin, '6');

Add menu item and URL rule:

SET @id_section_manage_email_templates = (SELECT `id`
                                          FROM `festi_sections`
                                          WHERE `ident` = 'manage_email_templates');
-- Add Mail plugin
INSERT INTO `festi_plugins` (`status`, `ident`)
VALUES ('active', 'Mail');

-- Add link for manage email templates page
INSERT INTO `festi_section_actions` (`id_section`, `plugin`, `method`, `mask`, `comment`) VALUES
    (@id_section_manage_email_templates, 'Mail', 'onDisplayTemplates', '6', '');

INSERT INTO `festi_url_rules` (`plugin`, `pattern`, `method`)
VALUES ('Mail', '~^/manage/email/templates/$~', 'onDisplayTemplates');

SET @id_url_rule = (SELECT `id`
                    FROM `festi_url_rules`
                    WHERE `plugin` = 'Mail'
                      AND `method` = 'onDisplayTemplates');

INSERT INTO `festi_url_rules2areas` (`id_url_rule`, `area`)
VALUES (@id_url_rule, 'backend');

-- Add menu item
INSERT INTO `festi_menus` (`caption`, `url`, `id_parent`, `order_n`, `description`, `id_section`, `area`, `ident`)
VALUES ('Email Templates', '/manage/email/templates/', NULL, 30, NULL, @id_section_manage_email_templates, NULL, NULL);

After completing setup, you can manage email templates at /manage/email/templates/.

Extension Points

Hooks

The plugin provides the following hooks:

  • HOOK_MAIL_HEADERS: Modify email headers before sending
  • HOOK_MAIL_CONTENT: Modify email content before sending

Example usage:

public function onHookMailHeaders(array &$data)
{
    // Add CC recipients
    $data['cc_recipients'] = array('[email protected]');

    // Change from address for specific templates
    if (isset($data['data']['template_type']) && $data['data']['template_type'] == 'billing') {
        $data['from_email'] = '[email protected]';
        $data['from_name'] = 'Billing Department';
    }
}

public function onHookMailContent(array &$data)
{
    // Access the PHPMailer instance
    $mail = $data['mail'];

    // Add custom headers
    $mail->addCustomHeader('X-Priority', '1');

    // Modify content for specific templates
    if ($data['ident'] == 'emergency_alert') {
        $mail->Subject = 'URGENT: ' . $mail->Subject;
    }
}

Domain Models

EmailTemplateValuesObject

Type-safe value object for email template data:

use plugin\Mail\Domain\Model\EmailTemplateValuesObject;

$template = new EmailTemplateValuesObject([
    'ident' => 'welcome_email',
    'subject' => 'Welcome!',
    'body' => '<p>Welcome to our service</p>',
    'title' => 'Welcome Email',
    'template' => 'welcome',
    'id_company' => 123
]);

// Getters
$ident = $template->getIdent();           // string
$subject = $template->getSubject();       // string  
$body = $template->getBody();             // string
$title = $template->getTitle();           // string|null
$templateName = $template->getTemplate(); // string|null
$companyId = $template->getCompanyID();   // int|null

// Setters
$template->setSubject('New Subject');
$template->setBody('<p>New body</p>');
$template->setTitle('New Title');
$template->setTemplate('new_template');

Fields: - id - Template ID - ident - Template identifier - caption - Display name - subject - Email subject - body - Email body content - title - Template title (optional) - template - Layout template file (optional) - id_company - Company/workspace ID (optional)

Events

BeforePrepareMailContentEvent

  • Type: before_prepare_mail_content
  • Class: plugin\Mail\Domain\Event\BeforePrepareMailContentEvent
  • When: Dispatched right before compiling the subject/body and applying a layout, after the template is loaded but before rendering.
  • Payload: EmailTemplateValuesObject - type-safe email template data

Subscriber example:

use plugin\Mail\Domain\Event\BeforePrepareMailContentEvent;
use plugin\Mail\Domain\Model\EmailTemplateValuesObject;

final class MailTemplateSubscriber
{
    public function __invoke(BeforePrepareMailContentEvent $event): void
    {
        $template = $event->getEmailTemplate();

        // Example: dynamically switch layout and prefix subject
        if ($template->getIdent() === 'welcome_email') {
            $template->setTemplate('welcome'); // use plugins/Mail/templates/welcome.phtml
            $template->setTitle('Welcome Email');
            $template->setSubject('🎉 ' . $template->getSubject());
        }
    }
}