Email Class

The Email class composes and sends MIME emails via PHP’s built-in mail() function. It supports plain text and HTML bodies, multiple To / CC / BCC recipients, reply-to addresses, file attachments, priority flags, and a fluent chainable interface so every setter returns $this.

Loading

Load the library inside your controller:

<?php
$this->call->library('email');

Once loaded it is available as $this->email.

Basic Usage

Every setter returns $this, so calls can be chained:

<?php
$this->email
    ->sender('no-reply@example.com', 'My App')
    ->recipient('user@example.com')
    ->subject('Welcome to My App')
    ->email_content('Hello, thanks for signing up!')
    ->send();

Or called individually:

<?php
$this->email->sender('no-reply@example.com', 'My App');
$this->email->recipient('user@example.com');
$this->email->subject('Welcome');
$this->email->email_content('Hello!');
$this->email->send();

Sender

Set the From address and an optional display name.

<?php
// Address only
$this->email->sender('no-reply@example.com');

// Address with display name
$this->email->sender('no-reply@example.com', 'My Application');

Parameter

Description

Required

$sender_email

Valid email address

Yes

$display_name

Name shown in the From field (e.g. My App)

No

Note

An Exception is thrown if the address fails validation. The display name is passed through filter_header() to strip newlines and high-byte characters, preventing header injection attacks.

Recipients — To, CC, BCC

To

Add one or more primary recipients. Calling recipient() multiple times builds a list — duplicates are silently ignored.

<?php
$this->email->recipient('alice@example.com');
$this->email->recipient('bob@example.com');

CC (Carbon Copy)

Recipients in the CC list receive the email and can see each other’s addresses.

<?php
$this->email->cc('manager@example.com');
$this->email->cc('team@example.com');

BCC (Blind Carbon Copy)

Recipients in the BCC list receive the email but are hidden from all other recipients.

<?php
$this->email->bcc('audit@example.com');

Note

send() throws an Exception if no To recipients have been added.

Method

Description

Duplicates

recipient($email)

Add a To recipient

Silently ignored

cc($email)

Add a CC recipient

Silently ignored

bcc($email)

Add a BCC recipient

Silently ignored

Reply-To

Direct replies to a different address than the sender:

<?php
$this->email->reply_to('support@example.com');

If reply_to() is not called, replies go to the sender address automatically.

Subject

<?php
$this->email->subject('Your order has shipped');

Note

An Exception is thrown if the subject is empty. The value is passed through filter_header() to strip newlines and prevent header injection.

Email Content

Set the body and its type. The default type is 'plain'.

Plain text

<?php
$this->email->email_content('Hello, your account is ready.');

HTML

<?php
$this->email->email_content('
    <h1>Welcome!</h1>
    <p>Your account has been created.</p>
    <p><a href="https://example.com/login">Log in here</a></p>
', 'html');

HTML shortcut

html() is a convenience alias for email_content($content, 'html'):

<?php
$this->email->html('<h1>Welcome!</h1><p>Thanks for joining.</p>');

Parameter

Default

Description

$content

The body of the email. Lines are automatically wrapped at 70 characters using MIME-compliant \r\n line endings.

$type

'plain'

'plain'text/plain; 'html'text/html

Note

The charset for HTML emails defaults to config_item('charset'). Override it per-message with charset().

Priority

Set the email priority flag. This controls the X-Priority, X-MS-Priority, and Importance headers.

<?php
$this->email->priority(1);  // High
$this->email->priority(3);  // Normal (default)
$this->email->priority(5);  // Low

Value

Label

Notes

1

High

Most email clients show a red exclamation mark

2

High

3

Normal

Default — no special indicator shown

4

Low

5

Low

Most email clients show a blue down-arrow

Charset

Override the character set used for HTML emails on a per-message basis:

<?php
$this->email->charset('iso-8859-1');

If not called, the charset defaults to config_item('charset') (typically utf-8).

Attachments

Attach one or more files by providing their absolute server path. Duplicates are silently ignored.

<?php
// Single attachment
$this->email->attachment(APPPATH . 'uploads/invoice.pdf');

// Multiple attachments (chained)
$this->email
    ->attachment(APPPATH . 'uploads/invoice.pdf')
    ->attachment(APPPATH . 'uploads/receipt.pdf');

Attachments are base64-encoded and sent as multipart/related MIME parts. The MIME type and filename are detected automatically.

Note

An Exception is thrown if the path is empty or the file does not exist on disk. This is a change from the original behaviour where missing files were silently skipped — explicit errors prevent silent data loss.

Charset, Charset & State Reset

Reset for re-use

Call reset() to clear all state and reuse the same instance for a new email without reloading the library:

<?php
// Send first email
$this->email->sender('no-reply@example.com')
            ->recipient('alice@example.com')
            ->subject('Hello Alice')
            ->email_content('Hi Alice!')
            ->send();

// Reset and send a second email
$this->email->reset()
            ->sender('no-reply@example.com')
            ->recipient('bob@example.com')
            ->subject('Hello Bob')
            ->email_content('Hi Bob!')
            ->send();

Accessors

These read-only methods are useful for logging, testing, or conditional logic:

<?php
echo $this->email->get_sender();       // 'no-reply@example.com'
print_r($this->email->get_recipients()); // ['alice@example.com', ...]
print_r($this->email->get_cc());         // ['manager@example.com']
print_r($this->email->get_bcc());        // ['audit@example.com']
echo $this->email->get_subject();        // 'Your order has shipped'
var_dump($this->email->is_html());       // bool(true)

Method

Returns

Description

get_sender()

string

Current sender address

get_recipients()

array

All To recipient addresses

get_cc()

array

All CC recipient addresses

get_bcc()

array

All BCC recipient addresses

get_subject()

string

Current subject line

is_html()

bool

TRUE when the body type is HTML

Sending

Call send() after all required fields have been set.

<?php
$sent = $this->email->send();

if ($sent)
{
    // Mail accepted by the MTA
}
else
{
    log_message('error', 'mail() returned false');
}

send() throws an Exception (not just returns false) when:

  • sender() has not been called

  • recipient() has not been called

  • subject() has not been called

This makes missing-field errors loud and easy to catch during development.

<?php
try
{
    $this->email->send();
}
catch (Exception $e)
{
    log_message('error', 'Email error: ' . $e->getMessage());
    // handle gracefully
}

Method Reference

Method

Signature

Returns

sender()

sender($email, $display_name = '')

$this

recipient()

recipient($email)

$this

cc()

cc($email)

$this

bcc()

bcc($email)

$this

reply_to()

reply_to($email)

$this

subject()

subject($subject)

$this

email_content()

email_content($content, $type = 'plain')

$this

html()

html($html)

$this

priority()

priority($level = 3)

$this

charset()

charset($charset)

$this

attachment()

attachment($filepath)

$this

send()

send()

bool

reset()

reset()

$this

get_sender()

get_sender()

string

get_recipients()

get_recipients()

array

get_cc()

get_cc()

array

get_bcc()

get_bcc()

array

get_subject()

get_subject()

string

is_html()

is_html()

bool

valid_email()

valid_email($email)

bool or throws Exception

filter_header()

filter_header($string)

string

Complete Examples

Plain text password reset

<?php
$this->call->library('email');

$this->email
    ->sender('no-reply@example.com', 'My App')
    ->recipient($user['email'])
    ->reply_to('support@example.com')
    ->subject('Password Reset Request')
    ->email_content(
        "Hello {$user['name']},\r\n\r\n"
        . "Click the link below to reset your password:\r\n"
        . "https://example.com/reset/{$token}\r\n\r\n"
        . "If you did not request this, please ignore this email."
    )
    ->send();

HTML invoice email with attachment and high priority

<?php
$this->call->library('email');

try
{
    $sent = $this->email
        ->sender('billing@example.com', 'Billing Team')
        ->recipient($customer['email'])
        ->cc('accounts@example.com')
        ->subject('Invoice #' . $invoice_id)
        ->priority(1)
        ->html("
            <h2>Invoice #{$invoice_id}</h2>
            <p>Dear {$customer['name']},</p>
            <p>Please find your invoice attached.</p>
            <p>Thank you for your business.</p>
        ")
        ->attachment(APPPATH . 'uploads/invoices/invoice_' . $invoice_id . '.pdf')
        ->send();

    if ( ! $sent)
    {
        log_message('error', "Invoice #{$invoice_id} email failed for {$customer['email']}");
    }
}
catch (Exception $e)
{
    log_message('error', 'Email exception: ' . $e->getMessage());
}

Looped newsletter with reset between sends

<?php
$this->call->library('email');

$subscribers = $this->subscriber_model->get_active();

foreach ($subscribers as $subscriber)
{
    $this->email
        ->reset()
        ->sender('newsletter@example.com', 'Monthly Update')
        ->recipient($subscriber['email'])
        ->subject('April 2026 Newsletter')
        ->html('<h1>April Update</h1><p>Here is what is new this month...</p>')
        ->send();
}

Sending with CC, BCC, and low priority

<?php
$this->email
    ->sender('hr@example.com', 'HR Team')
    ->recipient('employee@example.com')
    ->cc('manager@example.com')
    ->bcc('hr-archive@example.com')
    ->subject('Your Annual Review')
    ->priority(5)
    ->email_content('Please find your annual review notes below...')
    ->attachment(APPPATH . 'uploads/reviews/review_2026.pdf')
    ->send();

Tips and Best Practices

  • Always wrap send() in a try/catch block — it now throws Exception for missing required fields, and mail() can return false on misconfigured servers even when no exception is thrown.

  • Use reset() when sending emails in a loop rather than reloading the library — it is faster and keeps the same instance.

  • Use bcc() when sending the same email to many recipients so addresses are not exposed to each other.

  • Use reply_to() whenever the sender is a no-reply address — this gives recipients a real mailbox to reply to.

  • Always pass absolute paths to attachment() — relative paths may resolve incorrectly depending on the server’s working directory.

  • For high-volume or transactional email (order confirmations, password resets), consider routing through an SMTP relay or a third-party service (SendGrid, Mailgun, SES). PHP’s mail() does not support SMTP authentication, queuing, or delivery tracking.

  • Test emails in development using tools like Mailpit or Mailtrap to catch formatting issues before sending to real addresses.