Mailer Service

Table of contents

  1. Overview
  2. Key Components
  3. Using sendTemplate() in Chappy.php
  4. Customizing sendTo() with Advanced Parameters
  5. Attachment Management


1. Overview Table of Contents

The Chappy.php E-mail system is a modular, extensible implementation built on Symfony Mailer. It allows developers to send fully styled, template-driven emails with optional layouts and attachments. Emails are logged for auditing, and inline CSS rendering is supported via CssToInlineStyles.

2. Key Components Table of Contents

A. MailerService

Central service that composes and sends emails.

Features:

  • Send raw HTML or styled template-based emails
  • Inline CSS support
  • Optional plain text alternative
  • Full logging of email attempts
  • Attachment support

Paths Used:

  • Layouts: resources/views/emails/layouts/
  • Templates: resources/views/emails/
  • Stylesheets: resources/css/


B. AbstractMailer

Base class for creating structured mailers. Encapsulates logic for defining recipient, template, subject, and data payload.

Default behavior:

  • Uses MailerService::sendTemplate
  • Layout: default
  • Style: default


C. Custom Mailers (e.g. WelcomeMailer)

Extend AbstractMailer to create reusable mail definitions.

class WelcomeMailer extends AbstractMailer {
    protected function getData(): array {
        return ['user' => $this->user];
    }

    protected function getSubject(): string {
        return 'Welcome to ' . env('SITE_TITLE');
    }

    protected function getTemplate(): string {
        return 'welcome';
    }
}

Built In Mailers

  • AccountDeactivatedMailer - Notifies user when account is deactivated. More info in UserService section.
  • PasswordResetMailer - Notifies user when password needs to be reset
  • UpdatePasswordMailer - Notifies user when password is updated
  • WelcomeMailer - Sent when user creates an account

Example Usage

WelcomeMailer::sendTo($user);

Build Your Own Mailer Run the following command:

php console make:mailer MyMailer

File will be generated at app\CustomMailers. The modify the getData, getSubject, and getTemplate functions.


D. Templates and Layouts

Making a template:

php console make:email

You can find the new template at resources/views/emails/

// Example: welcome.php (template)
<h1>Welcome, <?= $user->name ?>!</h1>
<p>Thank you for signing up.</p>

Making a layout

php console make:email-layout
// Example: default.php (layout)
<html>
  <body>
    <?= $content ?>
  </body>
</html>

You can find the layout at resources/views/emails/layouts/

Adding Styles

php console make:styles

Your styles can be found at resources/css/

Optional .txt files with the same name as the template can be used for plain text versions.


E. Logging

Every email attempt (success or failure) is logged using the framework’s Logger class. Fields include:

  • Status (success or failed)
  • Timestamp
  • Recipient
  • Subject
  • HTML body (escaped)
  • Text body (if provided)
  • Template name
  • DSN transport
  • Error message (if failed)
  • Attachment metadata
  • Logs use the error or info log levels.


F. Attachments

Use the Attachments class to prepare data arrays.

Attachments::path($emailAttachment);
Attachments::content($emailAttachment);

Pass these into the sendTemplate() method or buildAndSend().


G. Environment Configuration

Set the following in your .env file:

MAILER_DSN=smtp://user:pass@smtp.mailtrap.io:2525
MAIL_FROM_ADDRESS=noreply@example.com


H. Example Use Case

$user = Users::findById(1);
WelcomeMailer::sendTo($user);

This sends a templated welcome email using the default layout and style.


I. Notes

  • HTML and text versions improve deliverability
  • CSS is inlined to ensure better rendering across clients
  • All template rendering uses output buffering and extract() for dynamic data injection


3. 📬 Using sendTemplate() in Chappy.php Table of Contents

The MailerService::sendTemplate() method allows you to send HTML (and optionally plain-text) emails using reusable templates, layouts, and CSS stylesheets. This method is powerful and flexible, supporting both embedded and path-based file attachments.

🧠 Basic Usage

$mail = new MailerService();
$user = Users::findById(1);

$mail->sendTemplate(
    $user->email,
    'Welcome Subject',
    'welcome',                   // Template name (without extension)
    ['user' => $user],           // Data passed to template
    'default',                   // Layout name
    [],                          // Attachments
    MailerService::FRAMEWORK_LAYOUT_PATH,
    MailerService::FRAMEWORK_TEMPLATE_PATH,
    'default',                   // CSS filename (no extension)
    MailerService::FRAMEWORK_STYLES_PATH
);


A. Test Case Examples

1. Basic HTML E-mail

Sends a raw HTML string without templates:

$mail->send($user->email, 'test_email_is_sent', '<p>Your account is ready!</p>');


2. HTML Template with Layout and Stylesheet

$mail->sendTemplate(
    $user->email,
    'test_email_template',
    'welcome',                   // welcome.php under views/emails/
    ['user' => $user],
    'default',                   // default.php under views/emails/layouts/
    [],
    MailerService::FRAMEWORK_LAYOUT_PATH,
    MailerService::FRAMEWORK_TEMPLATE_PATH,
    'default',                   // default.css under views/emails/styles/
    MailerService::FRAMEWORK_STYLES_PATH
);


3. HTML + Text Email from Dual Template

Includes welcome_text.txt if found in views/emails/:

$mail->sendTemplate(
    $user->email,
    'test_email_text_template',
    'welcome_text',
    ['user' => $user->username],
    'default',
    [],
    MailerService::FRAMEWORK_LAYOUT_PATH,
    MailerService::FRAMEWORK_TEMPLATE_PATH,
    'default',
    MailerService::FRAMEWORK_STYLES_PATH
);


B. Adding Attachments

1. Single Attachment

$attachment = EmailAttachments::findById(2);

$mail->sendTemplate(
    $user->email,
    'test_email_single_attachment_and_template',
    'welcome',
    ['user' => $user->username],
    'default',
    Attachments::content($attachment),
    ...
);


2. Multiple Attachments (Content + Path)

$attachments = [
    Attachments::content($attachment2),
    Attachments::path($attachment1)
];

$mail->sendTemplate(
    $user->email,
    'test_email_multiple_attachments_and_template',
    'welcome',
    ['user' => $user->username],
    'default',
    $attachments,
    ...
);

3. Text Template with Attachments

Combines .txt content fallback and multiple files:

$mail->sendTemplate(
    $user->email,
    'test_email_text_template_with_attachments',
    'welcome_text',
    ['user' => $user->username],
    'default',
    $attachments,
    ...
);

C. 🗂 Overriding Default Paths

To use custom layout, template, or styles from your own application:

Parameter Default Constant Custom Example
$layoutPath MailerService::FRAMEWORK_LAYOUT_PATH resources/views/emails/layouts/
$templatePath MailerService::FRAMEWORK_TEMPLATE_PATH resources/views/emails/
$stylesPath MailerService::FRAMEWORK_STYLES_PATH resources/css/

Pass custom paths manually to override framework defaults:

$mail->sendTemplate(
    $to,
    $subject,
    $template,
    $data,
    'custom_layout',
    [],
    CHAPPY_BASE_PATH . '/resources/views/emails/layouts/',
    CHAPPY_BASE_PATH . '/resources/views/emails/',
    'custom_style',
    CHAPPY_BASE_PATH . '/resources/css/'
);

🧭 Using Default Application Paths

If you want to use your own customized email templates, layouts, and styles located in:

  • resources/views/emails/layouts/
  • resources/views/emails/
  • resources/css/

You do not need to pass path parameters at all — just set them to null, or omit them entirely:

$mail->sendTemplate(
    $user->email,
    'Welcome to Chappy.php!',
    'welcome',
    ['user' => $user],
    'default',     // Layout name (e.g., default.php)
    [],            // No attachments
    null,          // Use default layout path: /resources/views/emails/layouts/
    null,          // Use default template path: /resources/views/emails/
    'default',     // CSS file: default.css
    null           // Use default style path: /resources/css/
);

These values are automatically resolved using:

  • self::$layoutPath
  • self::$templatePath
  • self::$stylesPath

…which are set to point to your resources/ directory.


4. Customizing sendTo() with Advanced Parameters Table of Contents

By default, AbstractMailer::sendTo() uses the base send() method, which calls buildAndSend() with default parameters. However, if your custom mailer requires attachments or custom layout/template/style paths, you can override sendTo() directly.

🛠 Example: Overriding sendTo() to Add Attachments

use App\Models\Users;
use Core\Models\EmailAttachments;
use Core\Lib\Mail\AbstractMailer;
use Core\Lib\Mail\Attachments;

class WelcomeMailer extends AbstractMailer
{
    protected function getData(): array {
        return ['user' => $this->user];
    }

    protected function getSubject(): string {
        return 'Welcome to ' . env('SITE_TITLE');
    }

    protected function getTemplate(): string {
        return 'welcome';
    }

    /**
     * Override the static sendTo method to include custom build options.
     */
    public static function sendTo(Users $user): bool {
        $mailer = new static($user);

        $attachment1 = EmailAttachments::findById(1);
        $attachment2 = EmailAttachments::findById(2);

        return $mailer->buildAndSend(
            null, // layout (defaults to 'default')
            [
                Attachments::content($attachment1),
                Attachments::path($attachment2)
            ],
            null, // layout path (uses /resources/views/emails/layouts/)
            null, // template path (uses /resources/views/emails/)
            'default', // CSS filename
            null  // CSS path (uses /resources/css/)
        );
    }
}

🔍 Usage in Controller or Console

$user = Users::findById(1);
WelcomeMailer::sendTo($user); // Sends with attachments and full customization

✅ When Should You Override sendTo()? You should override sendTo() when:

  • You want to embed logic unique to that mailer (e.g. attachments, path overrides)
  • You need to inject data not handled by the getData() method
  • You want to isolate one-off logic from your controller or service layer

📌 Reminder: buildAndSend() Signature

protected function buildAndSend(
    ?string $layout = null,
    array $attachments = [],
    ?string $layoutPath = null,
    ?string $templatePath = null,
    ?string $styles = null,
    ?string $stylesPath = null
): bool

🧼 Best Practice If your attachments or logic are conditional, wrap them cleanly in the overridden sendTo() to keep your mailer class readable.

5. Attachment Management Table of Contents

The admin dashboard allows administrators to upload, preview, update, and delete email attachments. These attachments can later be used with the framework’s MailerService::sendTemplate() functionality. This section documents the related views and controller actions.

A. 📄 Attachments Listing

View: admindashboard.attachments

This page displays a table of all uploaded attachments, including:

  • Original filename (with a link to the attachment details)
  • Uploader username
  • File size (formatted) -Action buttons: Edit / Delete

Add New Attachment: A button is available to navigate to the upload form:/admindashboard/editAttachments/new


B. 📋 Add or Edit Attachment

View: admindashboard.attachments_form This form supports both creating and updating attachments:

  • Description (WYSIWYG via TinyMCE)
  • File Upload (only for new records)
  • CSRF Protection enabled via csrf()
  • Save and Cancel buttons


C. 📁 Attachment Details

View: admindashboard.attachment_details

This view shows metadata and a preview link:

  • Created and Updated timestamps (in human-readable format)
  • File size and MIME type
  • Uploader username
  • Description (rich text rendered safely)
  • Link to Preview the file: /admindashboard/preview/:id


D. 🧪 Usage with MailerService

Once uploaded, attachments can be used in MailerService::sendTemplate():

$mailer->sendTemplate(
    $to,
    'Subject Line',
    'template_name',
    ['user' => $user],
    'default',
    [
        Attachments::content($attachment),
        Attachments::path($attachment)
    ],
    null, // layout path (null uses /resources/views/emails/layouts)
    null, // template path (null uses /resources/views/emails/templates)
    'default',
    null  // styles path
);


E. ✅ Additional Notes

  • Uploaded files are stored and accessible only within admin.
  • Attachments are associated with users via the user_id column.
  • File metadata such as MIME type and size are captured and stored during upload.
  • Descriptions are HTML-safe and stored with support for rich formatting.

This section allows administrators to manage reusable file assets securely and efficiently for use in transactional emails.