Kotchasan Framework Documentation

Kotchasan Framework Documentation

คลาส Email - การส่งอีเมล

TH 05 Feb 2026 07:50

คลาส Email - การส่งอีเมล

คลาส Email เป็นยูทิลิตี้สำหรับส่งอีเมลผ่าน PHP mail() หรือ PHPMailer พร้อมรองรับ SMTP, CC, BCC และ HTML content

Namespace

Kotchasan\Email

ภาพรวม

Email class มีฟังก์ชัน:

  • ส่งอีเมลผ่าน PHP mail() หรือ PHPMailer
  • รองรับ SMTP authentication
  • ส่งถึงผู้รับหลายคน (CC, BCC)
  • รองรับ HTML content
  • ตรวจสอบ error และแสดง error message

API Reference

send()

ส่งอีเมลพร้อม configuration

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

Parameters:

  • $mailto - อีเมลผู้รับ (รองรับหลายอีเมล คั่นด้วย comma)
  • $replyto - อีเมล Reply-To (ถ้าว่างใช้ noreply_email จาก config)
  • $subject - หัวข้ออีเมล
  • $msg - เนื้อหา (รองรับ HTML)
  • $cc - อีเมล CC (optional, หลายอีเมลคั่นด้วย comma)
  • $bcc - อีเมล BCC (optional, หลายอีเมลคั่นด้วย comma)

Returns: Email object (ใช้ error() และ getErrorMessage() เช็ค status)

Example:

use Kotchasan\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!";
}

// ส่งถึงหลายคน
$email = Email::send(
    'user1@example.com,user2@example.com',
    'support@mysite.com',
    'System Notification',
    '<p>This is a notification message.</p>'
);

// ใช้ CC และ 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 พร้อมชื่อ
$email = Email::send(
    'customer@example.com',
    'Customer Service <support@mysite.com>',
    'Order Confirmation',
    '<p>Your order #12345 has been confirmed.</p>'
);

// ระบบสมัครสมาชิก
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();
    }
}

// ระบบแจ้งเตือน
class NotificationSystem
{
    public function notifyAdmins($subject, $message)
    {
        global $db;

        // ดึงอีเมล admin ทั้งหมด
        $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;
    }
}

// ระบบรีเซ็ตรหัสผ่าน
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();
    }
}

// ระบบใบแจ้งหนี้
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()

ตรวจสอบว่ามี error เกิดขึ้นหรือไม่

public function error(): bool

Returns: true = มี error, false = ส่งสำเร็จ

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!";
}

// ใช้ในระบบ logging
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;
}

// ลอง retry หากล้มเหลว
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); // รอ 2 วินาทีก่อน retry
        }
    }

    return false;
}

getErrorMessage()

ดึง error message

public function getErrorMessage(): string

Returns: Error message หรือ empty string (ถ้าไม่มี 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}";

    // บันทึก error ลง 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
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);
    }
}

// แจ้งเตือน admin เมื่อส่งไม่สำเร็จ
function sendWithAdminNotification($to, $subject, $message)
{
    $email = Email::send($to, '', $subject, $message);

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

        // แจ้ง 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 ใช้ config จาก settings/config.php:

// ตั้งค่าพื้นฐาน
'web_title' => 'My Website',
'noreply_email' => 'noreply@mysite.com',
'email_charset' => 'utf-8',

// วิธีส่งอีเมล
'email_use_phpMailer' => 0,  // 0 = PHP mail(), 1 = SMTP, 2 = PHPMailer with mail()

// SMTP Settings (ถ้าใช้ PHPMailer)
'email_SMTPAuth' => true,
'email_Host' => 'smtp.gmail.com',
'email_Port' => 587,
'email_SMTPSecure' => 'tls',  // 'tls' หรือ 'ssl'
'email_Username' => 'your@gmail.com',
'email_Password' => 'your-app-password',

การตั้งค่า SMTP (Gmail)

return [
    'email_use_phpMailer' => 1,        // ใช้ 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 (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',
];

ตัวอย่างการใช้งานจริง

1. ระบบสมัครสมาชิก

use Kotchasan\Email;

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

        // บันทึก 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  // รอ activate
        ]);

        // ส่งอีเมลยืนยัน
        $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. ระบบแจ้งเตือนคำสั่งซื้อ

use Kotchasan\Email;

class OrderNotification
{
    public function notifyNewOrder($order)
    {
        // แจ้งลูกค้า
        $this->notifyCustomer($order);

        // แจ้ง 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) . " THB</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) . " THB</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. ระบบรายงานประจำวัน

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

        // รวบรวมข้อมูล
        $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])
        ];

        // สร้างรายงาน
        $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>
        ";

        // ส่งถึงหลาย admin
        $email = Email::send(
            'admin1@mysite.com,admin2@mysite.com',
            'reports@mysite.com',
            "Daily Report - {$today}",
            $message
        );

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

Best Practices

1. ตรวจสอบ Error เสมอ

// ✅ 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. ใช้ HTML Template

// ✅ 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>..."; // ยากต่อการดูแล

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. ใช้ Queue สำหรับอีเมลจำนวนมาก

// ✅ 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')
            ]);
        }
    }
}

ข้อควรระวัง

[!WARNING]
SMTP Credentials: เก็บ username/password ใน config ที่ปลอดภัย อย่า commit ลง git

[!IMPORTANT]
Rate Limiting: หลาย SMTP provider จำกัดจำนวนอีเมลต่อวัน ควรใช้ queue

[!NOTE]
PHPMailer Required: ถ้าใช้ email_use_phpMailer = 1 ต้องมี PHPMailer library

[!TIP]
HTML Content: ใช้ inline CSS เพราะบาง email client ไม่รองรับ <style> tag

คลาสที่เกี่ยวข้อง

  • Text - การจัดการข้อความ
  • Template - การใช้ template engine

สรุป

Email class มี 3 เมธอดหลัก:

  1. send() - ส่งอีเมลพร้อม CC/BCC และ HTML support
  2. error() - ตรวจสอบว่ามี error หรือไม่
  3. getErrorMessage() - ดึง error message

รองรับ:

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

เหมาะสำหรับ:

  • ระบบสมัครสมาชิก
  • การแจ้งเตือน
  • ใบแจ้งหนี้/ใบเสร็จ
  • รายงานอัตโนมัติ