Kotchasan Framework Documentation

Kotchasan Framework Documentation

Email Class - Email Sending

EN 05 Feb 2026 07:50

Email Class - Email Sending

The Email class provides utilities for sending emails via PHP mail() or PHPMailer with SMTP support, CC, BCC, and HTML content.

Namespace

Kotchasan\Email

Overview

Email class provides:

  • Send emails via PHP mail() or PHPMailer
  • SMTP authentication support
  • Multiple recipients (CC, BCC)
  • HTML content support
  • Error checking and messages

API Reference

send()

Send email with custom configuration

public static function send(
    string $mailto,
    string $replyto,
    string $subject,
    string $msg,
    string $cc = '',
    string $bcc = ''
): Email

Parameters:

  • $mailto - Recipient email(s) (comma-separated for multiple)
  • $replyto - Reply-To email (uses nore ply_email from config if empty)
  • $subject - Email subject
  • $msg - Email content (HTML supported)
  • $cc - CC email(s) (optional, comma-separated)
  • $bcc - BCC email(s) (optional, comma-separated)

Returns: Email object (use error() and getErrorMessage() to check status)

Example:

use Kotchasan\\Email;

// Basic email
$email = Email::send(
    'user@example.com',
    'noreply@mysite.com',
    'Welcome to Our Site',
    '<h1>Welcome!</h1><p>Thank you for joining us.</p>'
);

if ($email->error()) {
    echo "Error: " . $email->getErrorMessage();
} else {
    echo "Email sent successfully!";
}

// Multiple recipients
$email = Email::send(
    'user1@example.com,user2@example.com',
    'support@mysite.com',
    'System Notification',
    '<p>This is a notification message.</p>'
);

// With CC and BCC
$email = Email::send(
    'manager@company.com',
    'hr@company.com',
    'Monthly Report',
    '<h2>Report for January</h2><p>Details...</p>',
    'supervisor@company.com',  // CC
    'ceo@company.com'           // BCC
);

// Reply-To with name
$email = Email::send(
    'customer@example.com',
    'Customer Service <support@mysite.com>',
    'Order Confirmation',
    '<p>Your order #12345 has been confirmed.</p>'
);

// User registration system
class UserRegistration
{
    public function sendWelcomeEmail($user)
    {
        $subject = "Welcome to " . config('web_title');

        $message = "
            <html>
            <head><title>Welcome</title></head>
            <body>
                <h1>Welcome, {$user['name']}!</h1>
                <p>Thank you for registering.</p>
                <p>Your username: <strong>{$user['username']}</strong></p>
                <p><a href='https://mysite.com/activate?token={$user['token']}'>
                   Click here to activate your account
                   </a></p>
            </body>
            </html>
        ";

        $email = Email::send(
            $user['email'],
            'noreply@mysite.com',
            $subject,
            $message
        );

        return !$email->error();
    }
}

// Notification system
class NotificationSystem
{
    public function notifyAdmins($subject, $message)
    {
        global $db;

        // Get all admin emails
        $admins = $db->select('users', ['email'], ['status' => 1]);
        $adminEmails = array_column($admins, 'email');

        $email = Email::send(
            implode(',', $adminEmails),
            'system@mysite.com',
            "[Admin] {$subject}",
            $message
        );

        if ($email->error()) {
            error_log("Failed to notify admins: " . $email->getErrorMessage());
            return false;
        }

        return true;
    }
}

// Password reset system
class PasswordReset
{
    public function sendResetLink($email, $token)
    {
        $resetLink = "https://mysite.com/reset-password?token={$token}";

        $subject = "Password Reset Request";
        $message = "
            <html>
            <body style='font-family: Arial, sans-serif;'>
                <div style='max-width: 600px; margin: 0 auto; padding: 20px;'>
                    <h2>Password Reset Request</h2>
                    <p>Someone requested a password reset for your account.</p>
                    <p>If this was you, click the link below:</p>
                    <p style='margin: 20px 0;'>
                        <a href='{$resetLink}'
                           style='background: #007bff; color: white;
                                  padding: 10px 20px; text-decoration: none;
                                  border-radius: 5px; display: inline-block;'>
                            Reset Password
                        </a>
                    </p>
                    <p>This link will expire in 24 hours.</p>
                    <p>If you didn't request this, please ignore this email.</p>
                </div>
            </body>
            </html>
        ";

        $emailObj = Email::send(
            $email,
            'security@mysite.com',
            $subject,
            $message
        );

        return !$emailObj->error();
    }
}

// Invoice system
class InvoiceSystem
{
    public function sendInvoice($customer, $invoiceData)
    {
        $subject = "Invoice #{$invoiceData['number']}";

        $message = "
            <html>
            <head>
                <style>
                    body { font-family: Arial, sans-serif; }
                    table { width: 100%; border-collapse: collapse; }
                    th, td { padding: 8px; text-align: left; border-bottom: 1px solid #ddd; }
                    th { background-color: #f2f2f2; }
                    .total { font-weight: bold; font-size: 18px; }
                </style>
            </head>
            <body>
                <h2>Invoice #{$invoiceData['number']}</h2>
                <p>Date: {$invoiceData['date']}</p>
                <p>Customer: {$customer['name']}</p>

                <table>
                    <thead>
                        <tr>
                            <th>Item</th>
                            <th>Quantity</th>
                            <th>Price</th>
                            <th>Total</th>
                        </tr>
                    </thead>
                    <tbody>";

        foreach ($invoiceData['items'] as $item) {
            $message .= "
                        <tr>
                            <td>{$item['name']}</td>
                            <td>{$item['qty']}</td>
                            <td>" . number_format($item['price'], 2) . "</td>
                            <td>" . number_format($item['total'], 2) . "</td>
                        </tr>";
        }

        $message .= "
                    </tbody>
                </table>

                <p class='total'>Total: " . number_format($invoiceData['total'], 2) . " THB</p>

                <p>Thank you for your business!</p>
            </body>
            </html>
        ";

        $email = Email::send(
            $customer['email'],
            'billing@mysite.com',
            $subject,
            $message,
            'accounting@mysite.com'  // CC to accounting
        );

        if ($email->error()) {
            // Log error
            error_log("Invoice email failed: " . $email->getErrorMessage());
            return false;
        }

        return true;
    }
}

error()

Check if there was an error sending the email

public function error(): bool

Returns: true = error occurred, false = sent successfully

Example:

use Kotchasan\Email;

$email = Email::send(
    'user@example.com',
    'noreply@mysite.com',
    'Test Email',
    '<p>Test message</p>'
);

if ($email->error()) {
    echo "Failed to send email";
    echo "Error: " . $email->getErrorMessage();
} else {
    echo "Email sent successfully!";
}

// Use in logging system
function sendAndLog($to, $subject, $message)
{
    $email = Email::send($to, '', $subject, $message);

    if ($email->error()) {
        error_log("Email send failed to {$to}: " . $email->getErrorMessage());
        return false;
    }

    error_log("Email sent successfully to {$to}");
    return true;
}

// Try retry if failed
function sendWithRetry($to, $subject, $message, $maxRetries = 3)
{
    for ($i = 0; $i < $maxRetries; $i++) {
        $email = Email::send($to, '', $subject, $message);

        if (!$email->error()) {
            return true;
        }

        if ($i < $maxRetries - 1) {
            sleep(2); // Wait 2 seconds before retry
        }
    }

    return false;
}

getErrorMessage()

Get error message from email sending

public function getErrorMessage(): string

Returns: Error message or empty string (if no error)

Example:

use Kotchasan\\Email;

$email = Email::send(
    'invalid-email',  // Invalid email
    'noreply@mysite.com',
    'Test',
    '<p>Test</p>'
);

if ($email->error()) {
    $errorMsg = $email->getErrorMessage();
    echo "Error details: {$errorMsg}";

    // Save error to database
    $db->insert('email_logs', [
        'to' => 'invalid-email',
        'subject' => 'Test',
        'status' => 'failed',
        'error' => $errorMsg,
        'created_at' => date('Y-m-d H:i:s')
    ]);
}

// Error tracking system
class EmailTracker
{
    public function send($to, $subject, $message)
    {
        $email = Email::send($to, '', $subject, $message);

        $log = [
            'to' => $to,
            'subject' => $subject,
            'sent_at' => date('Y-m-d H:i:s'),
            'status' => $email->error() ? 'failed' : 'success'
        ];

        if ($email->error()) {
            $log['error_message'] = $email->getErrorMessage();
        }

        global $db;
        $db->insert('email_logs', $log);

        return !$email->error();
    }

    public function getFailedEmails($limit = 10)
    {
        global $db;
        return $db->select('email_logs', '*', [
            'status' => 'failed'
        ], ['sent_at DESC'], $limit);
    }
}

// Notify admin when send fails
function sendWithAdminNotification($to, $subject, $message)
{
    $email = Email::send($to, '', $subject, $message);

    if ($email->error()) {
        $errorMsg = $email->getErrorMessage();

        // Notify admin
        Email::send(
            'admin@mysite.com',
            'system@mysite.com',
            '[Email Error] Failed to send email',
            "
                <h3>Email Send Failed</h3>
                <p><strong>To:</strong> {$to}</p>
                <p><strong>Subject:</strong> {$subject}</p>
                <p><strong>Error:</strong> {$errorMsg}</p>
            "
        );

        return false;
    }

    return true;
}

Configuration

Email class uses config from settings/config.php:

// Basic settings
'web_title' => 'My Website',
'noreply_email' => 'noreply@mysite.com',
'email_charset' => 'utf-8',

// Sending method
'email_use_phpMailer' => 0,  // 0 = PHP mail(), 1 = SMTP, 2 = PHPMailer with mail()

// SMTP Settings (if using PHPMailer)
'email_SMTPAuth' => true,
'email_Host' => 'smtp.gmail.com',
'email_Port' => 587,
'email_SMTPSecure' => 'tls',  // 'tls' or 'ssl'
'email_Username' => 'your@gmail.com',
'email_Password' => 'your-app-password',

SMTP Setup (Gmail)

return [
    'email_use_phpMailer' => 1,        // Use SMTP
    'email_SMTPAuth' => true,
    'email_Host' => 'smtp.gmail.com',
    'email_Port' => 587,
    'email_SMTPSecure' => 'tls',
    'email_Username' => 'yourname@gmail.com',
    'email_Password' => 'your-app-specific-password',
    'noreply_email' => 'noreply@yoursite.com',
];

SMTP Setup (Custom Server)

return [
    'email_use_phpMailer' => 1,
    'email_SMTPAuth' => true,
    'email_Host' => 'mail.yourserver.com',
    'email_Port' => 465,
    'email_SMTPSecure' => 'ssl',
    'email_Username' => 'mail@yoursite.com',
    'email_Password' => 'your-password',
];

Real-World Examples

1. User Registration System

use Kotchasan\\Email;

class UserController
{
    public function register($data)
    {
        global $db;

        // Save user
        $userId = $db->insert('users', [
            'email' => $data['email'],
            'name' => $data['name'],
            'password' => password_hash($data['password'], PASSWORD_DEFAULT),
            'token' => bin2hex(random_bytes(32)),
            'status' => 0  // Waiting for activation
        ]);

        // Send activation email
        $user = $db->first('users', ['id' => $userId]);
        $this->sendActivationEmail($user);

        return $userId;
    }

    private function sendActivationEmail($user)
    {
        $activateLink = "https://mysite.com/activate?token={$user->token}";

        $message = "
            <html>
            <body>
                <h2>Welcome to " . config('web_title') . "!</h2>
                <p>Hi {$user->name},</p>
                <p>Please click the link below to activate your account:</p>
                <p><a href='{$activateLink}'>Activate Account</a></p>
                <p>This link will expire in 24 hours.</p>
            </body>
            </html>
        ";

        $email = Email::send(
            $user->email,
            '',
            'Activate Your Account',
            $message
        );

        if ($email->error()) {
            error_log("Activation email failed for user {$user->id}: " .
                     $email->getErrorMessage());
        }
    }
}

2. Order Notification System

use Kotchasan\Email;

class OrderNotification
{
    public function notifyNewOrder($order)
    {
        // Notify customer
        $this->notifyCustomer($order);

        // Notify admin
        $this->notifyAdmin($order);
    }

    private function notifyCustomer($order)
    {
        $message = "
            <h2>Order Confirmation</h2>
            <p>Thank you for your order!</p>
            <p>Order #: {$order['number']}</p>
            <p>Total: $" . number_format($order['total'], 2) . "</p>
            <p>We will process your order shortly.</p>
        ";

        Email::send(
            $order['customer_email'],
            'orders@mysite.com',
            "Order Confirmation #{$order['number']}",
            $message
        );
    }

    private function notifyAdmin($order)
    {
        $message = "
            <h2>New Order Received</h2>
            <p>Order #: {$order['number']}</p>
            <p>Customer: {$order['customer_name']}</p>
            <p>Total: $" . number_format($order['total'], 2) . "</p>
            <p><a href='https://admin.mysite.com/orders/{$order['id']}'>
               View Order
               </a></p>
        ";

        Email::send(
            'admin@mysite.com',
            'system@mysite.com',
            "[New Order] #{$order['number']}",
            $message
        );
    }
}

3. Daily Report System

class DailyReport
{
    public function send()
    {
        global $db;

        // Gather information
        $today = date('Y-m-d');
        $stats = [
            'new_users' => $db->count('users', ['DATE(created_at)' => $today]),
            'new_orders' => $db->count('orders', ['DATE(created_at)' => $today]),
            'revenue' => $db->sum('orders', 'total', ['DATE(created_at)' => $today])
        ];

        // Generate report
        $message = "
            <html>
            <head>
                <style>
                    table { border-collapse: collapse; width: 100%; }
                    th, td { padding: 12px; text-align: left; border: 1px solid #ddd; }
                    th { background-color: #4CAF50; color: white; }
                </style>
            </head>
            <body>
                <h2>Daily Report - {$today}</h2>
                <table>
                    <tr>
                        <th>Metric</th>
                        <th>Value</th>
                    </tr>
                    <tr>
                        <td>New Users</td>
                        <td>{$stats['new_users']}</td>
                    </tr>
                    <tr>
                        <td>New Orders</td>
                        <td>{$stats['new_orders']}</td>
                    </tr>
                    <tr>
                        <td>Revenue</td>
                        <td>" . number_format($stats['revenue'], 2) . " THB</td>
                    </tr>
                </table>
            </body>
            </html>
        ";

        // Send to multiple admins
        $email = Email::send(
            'admin1@mysite.com,admin2@mysite.com',
            'reports@mysite.com',
            "Daily Report - {$today}",
            $message
        );

        return !$email->error();
    }
}

Best Practices

1. Always Check Errors

// ✅ Good - check error
$email = Email::send($to, '', $subject, $message);
if ($email->error()) {
    error_log($email->getErrorMessage());
}

// ❌ Bad - no error check
Email::send($to, '', $subject, $message);

2. Use HTML Templates

// ✅ Good - use template
function sendWelcomeEmail($user)
{
    $template = file_get_contents('templates/welcome.html');
    $message = str_replace([
        '{{name}}',
        '{{link}}'
    ], [
        $user['name'],
        $activationLink
    ], $template);

    return Email::send($user['email'], '', 'Welcome', $message);
}

// ❌ Bad - hardcoded HTML
$message = "<h1>Welcome</h1>..."; // Hard to maintain

3. Sanitize Email Addresses

// ✅ Good - validate first
function sendEmail($to, $subject, $message)
{
    if (!filter_var($to, FILTER_VALIDATE_EMAIL)) {
        return false;
    }

    $email = Email::send($to, '', $subject, $message);
    return !$email->error();
}

4. Use Queue for Bulk Emails

// ✅ Good - use queue
class EmailQueue
{
    public function add($to, $subject, $message)
    {
        global $db;
        $db->insert('email_queue', [
            'to' => $to,
            'subject' => $subject,
            'message' => $message,
            'status' => 'pending',
            'created_at' => date('Y-m-d H:i:s')
        ]);
    }

    public function process($limit = 10)
    {
        global $db;
        $emails = $db->select('email_queue', '*',
            ['status' => 'pending'], [], $limit);

        foreach ($emails as $item) {
            $email = Email::send($item->to, '', $item->subject, $item->message);

            $db->update('email_queue', ['id' => $item->id], [
                'status' => $email->error() ? 'failed' : 'sent',
                'error' => $email->getErrorMessage(),
                'sent_at' => date('Y-m-d H:i:s')
            ]);
        }
    }
}

Important Considerations

[!WARNING]
SMTP Credentials: Store username/password securely, don't commit to git

[!IMPORTANT]
Rate Limiting: Many SMTP providers limit emails per day, use queue

[!NOTE]
PHPMailer Required: If email_use_phpMailer = 1, must have PHPMailer library

[!TIP]
HTML Content: Use inline CSS, some email clients don't support <style> tags

Summary

Email class has 3 main methods:

  1. send() - Send email with CC/BCC and HTML support
  2. error() - Check if error occurred
  3. getErrorMessage() - Get error message

Supports:

  • PHP mail() function
  • PHPMailer with SMTP
  • HTML content
  • Multiple recipients (CC, BCC)
  • Error handling

Perfect for:

  • User registration
  • Notifications
  • Invoices/receipts
  • Automated reports