webklex/laravel-imap

1.1.2 2018-05-19 18:18 UTC

README

Latest Version on Packagist Software License Build Status Total Downloads

Description

Laravel IMAP is an easy way to integrate the native php imap library into your Laravel app.

Table of Contents

Installation

  1. Install the php-imap library if it isn't already installed:
sudo apt-get install php*-imap && sudo apache2ctl graceful

You might also want to check phpinfo() if the extension is enabled.

  1. Now install the Laravel IMAP package by running the following command:
composer require webklex/laravel-imap
  1. If you're running Laravel >= 5.5, package discovery will configure the service provider and Client alias out of the box.

    Otherwise, for Laravel <= 5.4, edit your config/app.php file and:

    • add the following to the providers array:
      Webklex\IMAP\Providers\LaravelServiceProvider::class,
    • add the following to the aliases array:
      'Client' => Webklex\IMAP\Facades\Client::class,
  2. Run the command below to publish the package config file config/imap.php:

php artisan vendor:publish --provider="Webklex\IMAP\Providers\LaravelServiceProvider"

Configuration

If you are planning to use a single account, you might want to add the following to your .env file.

IMAP_HOST=somehost.com
IMAP_PORT=993
IMAP_ENCRYPTION=ssl
IMAP_VALIDATE_CERT=true
IMAP_USERNAME=root@example.com
IMAP_PASSWORD=secret
IMAP_DEFAULT_ACCOUNT=default

The following encryption methods are supported:

  • false — Disable encryption
  • ssl — Use SSL
  • tls — Use TLS

Detailed config/imap.php configuration:

  • default — used default account
  • accounts — all available accounts
    • default — default account identifier
      • host — imap host
      • port — imap port
      • encryption — desired encryption method
      • validate_cert — decide weather you want to verify the certificate or not
      • username — imap account username
      • password — imap account password
  • options — additional fetch options
    • delimiter — you can use any supported char such as ".", "/", etc
    • fetchFT_UID (message marked as read by fetching the message) or FT_PEEK (fetch the message without setting the "read" flag)
    • fetch_body — If set to false all messages will be fetched without the body and any potential attachments
    • fetch_attachment — If set to false all messages will be fetched without any attachments
    • open — special configuration for imap_open()
      • DISABLE_AUTHENTICATOR — Disable authentication properties.

Usage

This is a basic example, which will echo out all Mails within all imap folders and will move every message into INBOX.read. Please be aware that this should not ben tested in real live but it gives an impression on how things work.

use Webklex\IMAP\Client;

$oClient = new Client([
    'host'          => 'somehost.com',
    'port'          => 993,
    'encryption'    => 'ssl',
    'validate_cert' => true,
    'username'      => 'username',
    'password'      => 'password',
]);

//Connect to the IMAP Server
$oClient->connect();

//Get all Mailboxes
/** @var \Webklex\IMAP\Support\FolderCollection $aFolder */
$aFolder = $oClient->getFolders();

//Loop through every Mailbox
/** @var \Webklex\IMAP\Folder $oFolder */
foreach($aFolder as $oFolder){

    //Get all Messages of the current Mailbox $oFolder
    /** @var \Webklex\IMAP\Support\MessageCollection $aMessage */
    $aMessage = $oFolder->getMessages();
    
    /** @var \Webklex\IMAP\Message $oMessage */
    foreach($aMessage as $oMessage){
        echo $oMessage->subject.'<br />';
        echo 'Attachments: '.$oMessage->getAttachments()->count().'<br />';
        echo $oMessage->getHTMLBody(true);
        
        //Move the current Message to 'INBOX.read'
        if($oMessage->moveToFolder('INBOX.read') == true){
            echo 'Message has ben moved';
        }else{
            echo 'Message could not be moved';
        }
    }
}

If you use the Facade \Webklex\IMAP\Facades\Client::class please select an account first:

use Webklex\IMAP\Facades\Client;

$oClient = Client::account('default');
$oClient->connect();

There is an experimental function available to get a Folder instance by name. For an easier access please take a look at the new config option imap.options.delimiter however the getFolder method takes three options: the required (string) $folder_name and two optional variables. An integer $attributes which seems to be sometimes 32 or 64 (I honestly have no clue what this number does, so feel free to enlighten me and anyone else) and a delimiter which if it isn't set will use the default option configured inside the config/imap.php file.

/** @var \Webklex\IMAP\Client $oClient */

/** @var \Webklex\IMAP\Folder $oFolder */
$oFolder = $oClient->getFolder('INBOX.name');

Search for specific emails:

/** @var \Webklex\IMAP\Folder $oFolder */

//Get all messages since march 15 2018
/** @var \Webklex\IMAP\Support\MessageCollection $aMessage */
$aMessage = $oFolder->searchMessages([['SINCE', Carbon::parse('15.03.2018')]]);

//Get all messages containing "hello world"
/** @var \Webklex\IMAP\Support\MessageCollection $aMessage */
$aMessage = $oFolder->searchMessages([['TEXT', 'hello world']]);

//Get all unseen messages containing "hello world"
/** @var \Webklex\IMAP\Support\MessageCollection $aMessage */
$aMessage = $oFolder->searchMessages([['UNSEEN'], ['TEXT', 'hello world']]);

Available search criteria:

  • ALL — return all messages matching the rest of the criteria
  • ANSWERED — match messages with the \ANSWERED flag set
  • BCC "string" — match messages with "string" in the Bcc: field
  • BEFORE "date" — match messages with Date: before "date"
  • BODY "string" — match messages with "string" in the body of the message
  • CC "string" — match messages with "string" in the Cc: field
  • DELETED — match deleted messages
  • FLAGGED — match messages with the \FLAGGED (sometimes referred to as Important or Urgent) flag set
  • FROM "string" — match messages with "string" in the From: field
  • KEYWORD "string" — match messages with "string" as a keyword
  • NEW — match new messages
  • OLD — match old messages
  • ON "date" — match messages with Date: matching "date"
  • RECENT — match messages with the \RECENT flag set
  • SEEN — match messages that have been read (the \SEEN flag is set)
  • SINCE "date" — match messages with Date: after "date"
  • SUBJECT "string" — match messages with "string" in the Subject:
  • TEXT "string" — match messages with text "string"
  • TO "string" — match messages with "string" in the To:
  • UNANSWERED — match messages that have not been answered
  • UNDELETED — match messages that are not deleted
  • UNFLAGGED — match messages that are not flagged
  • UNKEYWORD "string" — match messages that do not have the keyword "string"
  • UNSEEN — match messages which have not been read yet

Further information:

Paginate a message collection:

/** @var \Webklex\IMAP\Support\MessageCollection $aMessage */

/** @var \Illuminate\Pagination\LengthAwarePaginator $paginator */
$paginator = $aMessage->paginate();

Get a specific message by uid (Please note that the uid is not unique and can change):

/** @var \Webklex\IMAP\Folder $oFolder */

/** @var \Webklex\IMAP\Message $oMessage */
$oMessage = $oFolder->getMessage($uid = 1);

Flag or "unflag" a message:

/** @var \Webklex\IMAP\Message $oMessage */
$oMessage->setFlag(['Seen', 'Spam']);
$oMessage->unsetFlag('Spam');

Save message attachments:

/** @var \Webklex\IMAP\Message $oMessage */

/** @var \Webklex\IMAP\Support\AttachmentCollection $aAttachment */
$aAttachment = $oMessage->getAttachments();

$aAttachment->each(function ($oAttachment) {
    /** @var \Webklex\IMAP\Attachment $oAttachment */
    $oAttachment->save();
});

Fetch messages without body fetching (decrease load):

/** @var \Webklex\IMAP\Folder $oFolder */

/** @var \Webklex\IMAP\Support\MessageCollection $aMessage */
$aMessage = $oFolder->searchMessages([['TEXT', 'Hello world']], null, false);

/** @var \Webklex\IMAP\Support\MessageCollection $aMessage */
$aMessage = $oFolder->getMessages('ALL', null, false);

Fetch messages without body and attachment fetching (decrease load):

/** @var \Webklex\IMAP\Folder $oFolder */

/** @var \Webklex\IMAP\Support\MessageCollection $aMessage */
$aMessage = $oFolder->searchMessages([['TEXT', 'Hello world']], null, false, 'UTF-8', false);

/** @var \Webklex\IMAP\Support\MessageCollection $aMessage */
$aMessage = $oFolder->getMessages('ALL', null, false, false);

Find the folder containing a message:

$oFolder = $aMessage->getContainingFolder();

Documentation

Client::class

Method Arguments Return Description
setConfig array $config self Set the Client configuration. Take a look at config/imap.php for more inspiration.
getConnection resource $connection resource Get the current imap resource
setReadOnly bool $readOnly self Set read only property and reconnect if it's necessary.
isReadOnly bool Determine if connection is in read only mode.
isConnected bool Determine if connection was established.
checkConnection Determine if connection was established and connect if not.
connect int $attempts Connect to server.
disconnect Disconnect from server.
getFolder string $folder_name, int $attributes = 32, int or null $delimiter Folder Get a Folder instance by name
getFolders bool $hierarchical, string or null $parent_folder FolderCollection Get folders list. If hierarchical order is set to true, it will make a tree of folders, otherwise it will return flat array.
openFolder Folder $folder, integer $attempts Open a given folder.
createFolder string $name boolean Create a new folder.
renameFolder string $old_name, string $new_name boolean Rename a folder.
deleteFolder string $name boolean Delete a folder.
getMessages Folder $folder, string $criteria, bool $fetch_body, bool $fetch_attachment MessageCollection Get messages from folder.
getUnseenMessages Folder $folder, string $criteria, bool $fetch_body, bool $fetch_attachment MessageCollection Get Unseen messages from folder.
searchMessages array $where, Folder $folder, $fetch_options, bool $fetch_body, string $charset, bool $fetch_attachment MessageCollection Get specific messages from a given folder.
getQuota array Retrieve the quota level settings, and usage statics per mailbox
getQuotaRoot string $quota_root array Retrieve the quota settings per user
countMessages int Gets the number of messages in the current mailbox
countRecentMessages int Gets the number of recent messages in current mailbox
getAlerts array Returns all IMAP alert messages that have occurred
getErrors array Returns all of the IMAP errors that have occurred
getLastError string Gets the last IMAP error that occurred during this page request
expunge bool Delete all messages marked for deletion
checkCurrentMailbox object Check current mailbox

Message::class

Method Arguments Return Description
parseBody Message Parse the Message body
delete Delete the current Message
restore Restore a deleted Message
copy string $mailbox, int $options Copy the current Messages to a mailbox
move string $mailbox, int $options Move the current Messages to a mailbox
getContainingFolder Folder or null $folder null Folder
moveToFolder string $mailbox, int $options Move the Message into an other Folder
setFlag string or array $flag boolean Set one or many flags
unsetFlag string or array $flag boolean Unset one or many flags
hasTextBody Check if the Message has a text body
hasHTMLBody Check if the Message has a html body
getTextBody string Get the Message text body
getHTMLBody string Get the Message html body
getAttachments AttachmentCollection Get all message attachments
hasAttachments boolean Checks if there are any attachments present
getClient Client Get the current Client instance
getUid string Get the current UID
getFetchOptions string Get the current fetch option
getMsglist integer Get the current message list
getHeaderInfo object Get the current header_info object
getHeader string Get the current raw header
getMessageId integer Get the current message ID
getMessageNo integer Get the current message number
getSubject string Get the current subject
getReferences mixed Get any potentially present references
getDate Carbon Get the current date object
getFrom array Get the current from information
getTo array Get the current to information
getCc array Get the current cc information
getBcc array Get the current bcc information
getReplyTo array Get the current reply to information
getInReplyTo string Get the current In-Reply-To
getSender array Get the current sender information
getBodies mixed Get the current bodies
getRawBody mixed Get the current raw message body
is boolean Does this message match another one?

Folder::class

Method Arguments Return Description
hasChildren bool Determine if folder has children.
setChildren array $children self Set children.
getMessage integer $uid, integer or null $msglist, int or null fetch_options, bool $fetch_body, bool $fetch_attachment Message Get a specific message from folder.
getMessages string $criteria, bool $fetch_body, bool $fetch_attachment MessageCollection Get messages from folder.
getUnseenMessages string $criteria, bool $fetch_body, bool $fetch_attachment MessageCollection Get Unseen messages from folder.
searchMessages array $where, $fetch_options, bool $fetch_body, string $charset, bool $fetch_attachment MessageCollection Get specific messages from a given folder.
delete Delete the current Mailbox
move string $mailbox Move or Rename the current Mailbox
getStatus integer $options object Returns status information on a mailbox
appendMessage string $message, string $options, string $internal_date bool Append a string message to the current mailbox
getClient Client Get the current Client instance

Attachment::class

Method Arguments Return Description
getContent string or null Get attachment content
getMimeType string or null Get attachment mime type
getExtension string or null Get a guessed attachment extension
getName string or null Get attachment name
getType string or null Get attachment type
getDisposition string or null Get attachment disposition
getContentType string or null Get attachment content type
getImgSrc string or null Get attachment image source as base64 encoded data url
save string $path, string $filename boolean Save the attachment content to your filesystem

MessageCollection::class

Extends Illuminate\Support\Collection::class

Method Arguments Return Description
paginate int $perPage = 15, $page = null, $pageName = 'page' LengthAwarePaginator Paginate the current collection.

AttachmentCollection::class

Extends Illuminate\Support\Collection::class

Method Arguments Return Description
paginate int $perPage = 15, $page = null, $pageName = 'page' LengthAwarePaginator Paginate the current collection.

FolderCollection::class

Extends Illuminate\Support\Collection::class

Method Arguments Return Description
paginate int $perPage = 15, $page = null, $pageName = 'page' LengthAwarePaginator Paginate the current collection.

Known issues

Error Solution
Kerberos error: No credentials cache file found (try running kinit) (...) Uncomment "DISABLE_AUTHENTICATOR" inside config/imap.php
imap_fetchbody() expects parameter 4 to be long, string given (...) Make sure that imap.options.fetch is a valid integer
Use of undefined constant FT_UID - assumed 'FT_UID' (...) Please take a look at #14 #30
DateTime::__construct(): Failed to parse time string (...) Please report any new invalid timestamps to #45
imap_open(): Couldn't open (...) Please log in your web browser: (...) In order to use IMAP on some services (such as Gmail) you need to enable it first. Google help page
imap_headerinfo(): Bad message number This happens if no Message number is available. Please make sure Message::parseHeader() has run before

Milestones & upcoming features

  • Wiki!!

Change log

Please see CHANGELOG for more information what has changed recently.

Security

If you discover any security related issues, please email github@webklex.com instead of using the issue tracker.

Credits

Supporters

A special thanks to Jetbrains for supporting this project through their open source license program.

Jetbrains

License

The MIT License (MIT). Please see License File for more information.