barbushin / php-imap

Manage mailboxes, filter/get/delete emails in PHP (supports IMAP/POP3/NNTP)
MIT License
1.65k stars 459 forks source link

#585: Avoid fetching attachments when they are already downloaded #654

Closed Sebbo94BY closed 2 years ago

Sebbo94BY commented 2 years ago

This change implements the suggestion from @yrccondor, which avoids downloading the attachments multiple times, when it's already downloaded. This improves the performance by saving time and reduces the required/used hardware resources.

Code to test it:

<?php
    require_once __DIR__.'/../vendor/autoload.php';

    use PhpImap\Exceptions\ConnectionException;
    use PhpImap\Mailbox;

    $mailbox = new Mailbox(
        '{imap.gmail.com:993/imap/ssl}INBOX', // IMAP server and mailbox folder
        'some@gmail.com', // Username for the before configured mailbox
        '*********', // Password for the before configured username
        __DIR__.'/files/', // Directory, where attachments will be saved (optional)
        'US-ASCII' // Server encoding (optional)
    );

    try {
        $mail_ids = $mailbox->searchMailbox('ALL');
    } catch (ConnectionException $ex) {
        exit('IMAP connection failed: '.$ex->getErrors('first'));
    } catch (Exception $ex) {
        exit('An error occured: '.$ex->getMessage());
    }

    echo 'Found '.\count($mail_ids)." email(s)...\n";

    $start = microtime(true);
    $attachments_counter_total = 0;

    foreach ($mail_ids as $mail_id) {
        echo "+------ P A R S I N G ------+\n";

        $email = $mailbox->getMail(
            $mail_id, // ID of the email, you want to get
            false // Do NOT mark emails as seen (optional)
        );

        echo 'from-name: '.(string) ($email->fromName ?? $email->fromAddress)."\n";
        echo 'from-email: '.(string) $email->fromAddress."\n";
        echo 'to: '.(string) $email->toString."\n";
        echo 'subject: '.(string) $email->subject."\n";
        echo 'message_id: '.(string) $email->messageId."\n";

        echo 'mail has attachments? ';
        if ($email->hasAttachments()) {
            echo "Yes\n";
        } else {
            echo "No\n";
        }

        if (!empty($email->getAttachments())) {
            $attachments_counter = \count($email->getAttachments());
            $attachments_counter_total += $attachments_counter;

            echo "$attachments_counter attachements\n";
        }
    }

    $mailbox->disconnect();

    echo "Total attachments: $attachments_counter_total\n";
    echo 'Execution time: '.(microtime(true) - $start).' sec.';

Results:

Before After
Found emails (counter) 25 25
Total attachments 26 26
ls -l files/ \| grep -Ev "^total" \| wc -l 26 26
Execution time (seconds) 18.500550985336 9.8069841861725

Solves #585.