php-imap

repository·master·Indexed 19 days ago

https://github.com/webklex/php-imap

A pure PHP implementation of the IMAP protocol that allows developers to interact with mailboxes without requiring the native PHP IMAP extension. It supports modern features such as IMAP IDLE and OAuth authentication. The library provides tools for managing IMAP folders, processing messages, and handling email attachments via the Attachment class.

Tokens
11.6K
Snippets
42
Records
59
Agent score
65%

What's inside php-imap

  1. Overview of PHP-IMAP

    master

    PHP-IMAP is a PHP wrapper for IMAP communication that does not require the php-imap extension to be installed or enabled. It provides full protocol integration, supporting the IMAP IDLE operation and modern oAuth authentication processes.

    While the extension is not required, enabling the php-imap module can improve message decoding quality and is necessary if you need to use legacy protocols like POP3.

  2. Detect email spoofing

    master

    The Header class can detect potential spoofing by comparing addresses found in from, reply_to, return_path, sender, and envelope_from headers.

    If multiple distinct senders are detected, the header is marked as spoofed via $header->set('spoofed', true).

    If the configuration key security.detect_spoofing_exception is set to true, the library will throw a Webklex\\PHPIMAP\\Exceptions\\SpoofingAttemptDetectedException instead of just marking the attribute.

  3. Proxy calls to the default account

    master

    The ClientManager implements the __call magic method, allowing you to call methods directly on the manager as if you were calling them on the default Client instance. This is a convenience feature to avoid calling ->account()->method() repeatedly.

    // Instead of this:
    $manager->account()->getFolder('INBOX');
    
    // You can do this (proxies to the default account):
    $manager->getFolder('INBOX');
  4. Handle errors during message fetching

    master

    When fetching large collections of messages, individual message retrieval might fail (e.g., due to corrupted content). The Query class handles this via a soft_fail mode:

    • Soft Fail (Default/Enabled): If soft_fail is true, the query will continue even if some messages fail to fetch. You can check for errors using hasErrors() or hasError($uid) and retrieve them via errors() or error($uid).
    • Hard Fail: If soft_fail is false, the first error encountered during get() or populate() will throw a GetMessagesFailedException.

    To enable soft fail: $query->softFail(true);.

  5. Use the Attribute class to manage IMAP response data

    master

    The Webklex\PHPIMAP\\Attribute class represents a single attribute within an IMAP response. It acts as a container for an attribute name and one or more associated values. It implements ArrayAccess, allowing you to interact with it like an array, and provides helper methods for common data transformations like converting to a date or a string.

    use Webklex\PHPIMAP\Attribute;
    
    // Create a new attribute with a name and a single value
    $attribute = new Attribute('Subject', 'Hello World');
    
    // Add more values
    $attribute->add('Second Value');
    
    // Access values like an array
    $firstValue = $attribute[0];
    
    // Convert to string (comma-separated values)
    echo $attribute->toString(); // "Hello World, Second Value"
    
    // Convert to array
    $array = $attribute->toArray();
  6. Troubleshooting Kerberos errors

    master

    If you encounter the error Kerberos error: No credentials cache file found (try running kinit) (...), you can resolve it by:

    1. Opening your configuration file.
    2. Uncommenting the DISABLE_AUTHENTICATOR option.
    3. Using the legacy-imap protocol.
  7. Basic usage example with ClientManager

    master

    To use the library, instantiate a Webklex\PHPIMAP\ClientManager with a path to your configuration file. You can then access specific accounts, connect to the server, iterate through folders, and process messages.

    Common tasks include:

    • Connecting to the server via $client->connect().
    • Retrieving folders via $client->getFolders().
    • Fetching messages from a folder using $folder->messages()->all()->get().
    • Accessing message properties like getSubject(), getHTMLBody(), and getAttachments().
    • Moving messages using $message->move('FOLDER_NAME').
    use Webklex\\PHPIMAP\\ClientManager;
    
    require_once "vendor/autoload.php";
    
    $cm = new ClientManager('path/to/config/imap.php');
    
    /** @var \\Webklex\\PHPIMAP\\Client $client */
    $client = $cm->account('account_identifier');
    
    //Connect to the IMAP Server
    $client->connect();
    
    //Get all Mailboxes
    /** @var \\Webklex\\PHPIMAP\\Support\\FolderCollection $folders */
    $folders = $client->getFolders();
    
    //Loop through every Mailbox
    /** @var \\Webklex\\PHPIMAP\\Folder $folder */
    foreach($folders as $folder){
    
        //Get all Messages of the current Mailbox $folder
        /** @var \\Webklex\\PHPIMAP\\Support\\MessageCollection $messages */
        $messages = $folder->messages()->all()->get();
        
        /** @var \\Webklex\\PHPIMAP\\Message $message */
        foreach($messages as $message){
            echo $message->getSubject().'<br />';
            echo 'Attachments: '.$message->getAttachments()->count().'<br />';
            echo $message->getHTMLBody();
            
            //Move the current Message to 'INBOX.read'
            if($message->move('INBOX.read') == true){
                echo 'Message has been moved';
            }else{
                echo 'Message could not be moved';
            }
        }
    }
  8. Configure Header parsing options

    master

    You can modify the behavior of the Header instance by providing custom options via setOptions(array $config).

    Key options include:

    • boundary: A custom regex pattern used by getBoundary().
    • rfc822: A boolean determining if the PHP imap_rfc822_parse_headers extension should be used if available.
    • fallback_date: A string used as a fallback date if the message date fails to parse, preventing an InvalidMessageDateException.
    $header->setOptions([
        'fallback_date' => 'now',
        'rfc822' => true
    ]);
  9. Create a Message from raw strings or files

    master

    If you have raw email data (headers, body, flags) or a local file, you can instantiate a Message object without an active IMAP connection using these static methods:

    • Message::make(...): Use this when you have the raw header, raw body, and raw flags separately. This method bypasses the constructor and uses reflection to avoid re-fetching from a server.
    • Message::fromString(string $blob, ?Config $config = null): Use this to parse a single raw email string (blob). It automatically splits the header from the body.
    • Message::fromFile(string $filename, ?Config $config = null): Use this to load a message directly from a local file path.
    // From raw components
    $message = Message::make($uid, $msglist, $client, $raw_header, $raw_body, $raw_flags);
    
    // From a raw string blob
    $message = Message::fromString($raw_email_blob);
    
    // From a file
    $message = Message::fromFile('/path/to/email.eml');
  10. Access message attachments

    master

    To work with files attached to an email, use the following methods on a Message instance:

    • hasAttachments(): Returns true if the message contains any attachments.
    • attachments() or getAttachments(): Returns an AttachmentCollection containing all attachments.
    if ($message->hasAttachments()) {
        foreach ($message->attachments() as $attachment) {
            // Process attachment
            echo $attachment->getName();
        }
    }
  11. Manage IMAP folders

    master

    The Client provides several methods to interact with mail folders:

    • getFolders(bool $hierarchical = true, ?string $parent_folder = null, bool $soft_fail = false): Returns a FolderCollection. If $hierarchical is true, it returns a tree structure.
    • getFoldersWithStatus(...): Similar to getFolders, but calls loadStatus() on each folder.
    • getFolder(string $folder_name, ?string $delimiter = null, bool $utf7 = false): Retrieves a folder by name or path (if a delimiter is present).
    • getFolderByName(string $folder_name, bool $soft_fail = false): Retrieves a folder by its exact name.
    • getFolderByPath(string $folder_path, bool $utf7 = false, bool $soft_fail = false): Retrieves a folder by its path, automatically converting to UTF-7 if $utf7 is false.
    • openFolder(string $folder_path, bool $force_select = false): Selects and opens a folder for interaction.
    • createFolder(string $folder_path, bool $expunge = true, bool $utf7 = false): Creates a new folder.
    • deleteFolder(string $folder_path, bool $expunge = true): Deletes a folder.
    • checkFolder(string $folder_path): Examines a folder.