Soo dir iimayl daahday

Waqti sax ma aha? Iimayl goor hore la soo diray? Dib u dhigista iimaylada waxay faa'iido u yeelan karaan xaalado badan: haddii aad naftaada siiso waqti dib u eegis ama inaad si wax ku ool ah u maamusho culeyska shaqadaada - waqtigu wuxuu noqon karaa mid muhiim ah. Waa kuwan saddex siyaabood oo aad dib ugu dhigi karto dirista iimaylka oo aad u wanaajiso xidhiidhkaaga.


Muuqaalka

Microsoft Outlook waxa ay bixisaa sifo ku dhex jirta oo kuu ogolaanaysa in aad dib u dhigto iimaylada. Si tan loo sameeyo waxaad isticmaashaa shaqada "Ikhtiyaarada > Dib u dhigista":

Khasaaraha ugu weyn ee xalkani waa in (xitaa jawiga sarrifka) Muuqaalka waa inuu ku socdaa dhinaca macmiilka wakhtiga dirida.

Google

Gmail waxa uu ku siinayaa xal waxyar ka wanaagsan halkan. Si tan loo sameeyo, aad "Jadwalka Dir" ka hor inta aanad dirin iimaylka.:

Iimayllada horay loo soo diray sidoo kale waa lagu "buri karaa" 30 ilbiriqsi gudahood. Si tan loo sameeyo, marka hore waxaad dejisaa goobta u gaarka ah ee hoos timaada "Call up all settings".:

Haddii aad hadda dirto iimayl, waxaad dib uga noqon kartaa muddadan dhanka bidix ee hoose:

Boomerang

Waxaa jira adeeg bixiyayaasha mushaharka leh sida Boomerang ee Outlook oo, marka lagu daro xasuusinta ama dabagalka tooska ah, sidoo kale bixiya dirista iimaylka oo daahsan.:

Khasaaraha halkan waa in emails-ku ku dhamaanayaan server-yada qolo saddexaad oo ay jirto kharash isticmaalkooda.

PHP

Sababta kugu filan inaad wax u dhisto: Waxa kale oo aad ku guulaysan kartaa waxaad rabto adiga oo la kaashanayo qoraal yar oo PHP ah . Marka hore, waxaan ku abuurnaa qaab-dhismeedka gal sanduuqa boostada:

Tani waxay ka tarjumaysaa wakhtiga rarida ee la rabo. Socodka shaqadu hadda waxa uu ka kooban yahay kaydinta iimaylka qoran sidii qabyo ahaan intii la diri lahaa oo loo rari lahaa gal ku habboon. Waxaan markaa rakibnaa dhammaan xirmooyinka PHP ee loo baahan yahay:

composer require php-imap/php-imap phpmailer/phpmailer vlucas/phpdotenv

Ugu dambeyntii waxaan abuurnaa mid .env-Fayl leh xogta gelitaanka iyo dejinta:

HOST_SMTP="xxx"
PORT_SMTP=465
HOST_IMAP="xxx"
PORT_IMAP=993
USERNAME="foo@bar.com"
PASSWORD="xxx"
ENCRYPTION="ssl"
FROM_ADDRESS="foo@bar.com"
FROM_NAME="Foo Bar"
FOLDER_INBOX="INBOX/DELAY"
FOLDER_OUTBOX="Gesendete Elemente"
PHP_EXECUTABLE="/usr/bin/php"

Qoraalka PHP ee soo socda ayaa markaa sameeya inta soo hartay:

<?php
require_once __DIR__ . '/vendor/autoload.php';
class MailDelay
{
    private \PhpImap\Mailbox $mailbox;
    private array $folders;
    public function init(): void
    {
        $this->loadEnvironmentVariables();
        $this->initMailbox();
        $this->initFolders();
        $this->processFolders();
    }
    private function loadEnvironmentVariables(): void
    {
        $dotenv = \Dotenv\Dotenv::createImmutable(__DIR__);
        $dotenv->load();
    }
    private function initMailbox(): void
    {
        $this->mailbox = new \PhpImap\Mailbox(
            '{' . $_SERVER['HOST_IMAP'] . ':' . $_SERVER['PORT_IMAP'] . '/imap/ssl}' . $_SERVER['FOLDER_INBOX'],
            $_SERVER['USERNAME'],
            $_SERVER['PASSWORD'],
            sys_get_temp_dir(),
            'UTF-8'
        );
    }
    private function initFolders(): void
    {
        $this->folders = [];
        $folders = $this->mailbox->getMailboxes('*');
        foreach ($folders as $folder) {
            if ($folder['shortpath'] === $_SERVER['FOLDER_INBOX']) {
                continue;
            }
            $this->folders[] = (object) $folder;
        }
    }
    private function processFolders(): void
    {
        foreach ($this->folders as $folder) {
            $this->mailbox->switchMailbox($folder->fullpath);
            $mailIds = $this->mailbox->searchMailbox('ALL');
            foreach ($mailIds as $mailId) {
                $preparedMail = $this->prepareMailData($mailId, $folder->shortpath);
                if (
                    $preparedMail->subject !== 'Dies ist Plain Text' &&
                    strtotime($preparedMail->time_to_send) > strtotime('now')
                ) {
                    continue;
                }
                try {
                    $this->sendMail($preparedMail);
                    echo 'Successfully sent mail #' . $preparedMail->id . '.' . PHP_EOL;
                } catch (\Exception $e) {
                    echo 'Error in sending mail #' . $preparedMail->id . ': ' . $e->getMessage() . PHP_EOL;
                }
            }
        }
        echo 'All mails have been processed.' . PHP_EOL;
    }
    private function prepareMailData(int $id, string $folder): object
    {
        $mail = $this->mailbox->getMail($id, false); // don't mark as unread
        return (object) [
            'id' => (string) $mail->id,
            'to' => $this->formatEmailAddresses($mail->to),
            'cc' => $this->formatEmailAddresses($mail->cc),
            'bcc' => $this->formatEmailAddresses($mail->bcc),
            'subject' => (string) $mail->subject,
            'content_html' => $this->convertEncoding($mail->textHtml),
            'content_plain' => $this->convertEncoding($mail->textPlain),
            'attachments' => $this->determineAttachments($mail->getAttachments()),
            'time_to_send' => $this->determineTimeToSend(explode('/', $folder)[2], $mail->date)
        ];
    }
    private function formatEmailAddresses(?array $addresses): ?array
    {
        if (empty($addresses)) {
            return null;
        }
        return array_map(
            function ($key, $value) {
                return [
                    'email' => $key,
                    'name' => $key === $value ? null : str_replace(' (' . $key . ')', '', $value)
                ];
            },
            array_keys($addresses),
            $addresses
        );
    }
    private function convertEncoding(string $text): string
    {
        return mb_detect_encoding($text, 'UTF-8, ISO-8859-1') !== 'UTF-8'
            ? \UConverter::transcode($text, 'UTF8', 'ISO-8859-1')
            : $text;
    }
    private function determineAttachments(array $attachmentsImap): array
    {
        $attachments = [];
        if (!empty($attachmentsImap)) {
            foreach ($attachmentsImap as $attachment) {
                $attachments[] = [
                    'name' => $attachment->name,
                    'file' => $attachment->filePath,
                    'disposition' => $attachment->disposition,
                    'inline_id' => $attachment->contentId
                ];
            }
        }
        return $attachments;
    }
    private function determineTimeToSend(string $delayTime, string $date): ?string
    {
        $timeToSend = null;
        if ($delayTime === 'THIS EVENING') {
            $timeToSend = date('Y-m-d', strtotime($date)) . ' 18:00:00';
        } elseif ($delayTime === 'THIS NIGHT') {
            $timeToSend =
                date('Y-m-d', strtotime($date . (date('H', strtotime($date)) >= 4 ? ' + 1 day' : ''))) . ' 03:42:00';
        } elseif ($delayTime === 'NEXT MORNING') {
            $timeToSend =
                date('Y-m-d', strtotime($date . (date('H', strtotime($date)) >= 9 ? ' + 1 day' : ''))) . ' 09:00:00';
        } elseif ($delayTime === 'NEXT WEEK') {
            $date = new \DateTime(date('Y-m-d', strtotime($date)));
            $date->modify('next monday');
            $timeToSend = $date->format('Y-m-d') . ' 09:00:00';
        }
        return $timeToSend;
    }
    private function sendMail(object $preparedMail): void
    {
        $mail = new \PHPMailer\PHPMailer\PHPMailer(true);
        $mail->isSMTP();
        $mail->Host = $_SERVER['HOST_SMTP'];
        $mail->Port = $_SERVER['PORT_SMTP'];
        $mail->Username = $_SERVER['USERNAME'];
        $mail->Password = $_SERVER['PASSWORD'];
        $mail->SMTPSecure = $_SERVER['ENCRYPTION'];
        $mail->setFrom($_SERVER['FROM_ADDRESS'], $_SERVER['FROM_NAME']);
        $mail->SMTPAuth = true;
        $mail->SMTPOptions = [
            'tls' => ['verify_peer' => false, 'verify_peer_name' => false, 'allow_self_signed' => true],
            'ssl' => ['verify_peer' => false, 'verify_peer_name' => false, 'allow_self_signed' => true]
        ];
        $mail->CharSet = 'utf-8';
        $this->addRecipients($mail, $preparedMail->to, 'addAddress');
        $this->addRecipients($mail, $preparedMail->cc, 'addCC');
        $this->addRecipients($mail, $preparedMail->bcc, 'addBCC');
        $mail->isHTML(!empty($preparedMail->content_html));
        $mail->Subject = $preparedMail->subject;
        if (!empty($preparedMail->content_html)) {
            $mail->Body = $preparedMail->content_html;
            $mail->AltBody = !empty($preparedMail->content_plain)
                ? $preparedMail->content_plain
                : strip_tags(str_replace(['<br>', '<br/>', '<br />'], "\r\n", $preparedMail->content_html));
        } else {
            $mail->Body = $preparedMail->content_plain;
        }
        $this->addAttachments($mail, $preparedMail->attachments);
        $mail->send();
        $this->mailbox->moveMail($preparedMail->id, $_SERVER['FOLDER_OUTBOX']);
    }
    private function addRecipients(\PHPMailer\PHPMailer\PHPMailer $mail, ?array $recipients, string $method): void
    {
        if (!empty($recipients)) {
            foreach ($recipients as $recipient) {
                $mail->$method($recipient['email'], $recipient['name']);
            }
        }
    }
    private function addAttachments(\PHPMailer\PHPMailer\PHPMailer $mail, array $attachments): void
    {
        if (!empty($attachments)) {
            foreach ($attachments as $attachment) {
                if (!empty($attachment['file']) && !empty($attachment['name']) && file_exists($attachment['file'])) {
                    if ($attachment['disposition'] === 'attachment') {
                        $mail->addAttachment($attachment['file'], $attachment['name']);
                    } elseif ($attachment['disposition'] === 'inline') {
                        $mail->AddEmbeddedImage(
                            $attachment['file'],
                            $attachment['inline_id'],
                            $attachment['name'],
                            'base64',
                            'image/png'
                        );
                    }
                }
            }
        }
    }
}
$md = new MailDelay();
$md->init();

Si qoraalkani u socdo si isdaba joog ah, waxaanu abuurnaa faylka bash:

#!/usr/bin/env bash
source $(dirname "$0")/.env
"$PHP_EXECUTABLE" $(dirname "$0")/maildelay.php

Ka dib waxaan ku socodsiineynaa qoraalkan 10-kii daqiiqoba mar anagoo adeegsanayna shaqada cron:

*/10 * * * * /path/to/maildelay/maildelay.sh 2>&1

Xalkani si dabacsanaan leh ayaa loo habeyn karaa, sir-saaxiibtinimo waana bilaash. Waxay la shaqaysaa akoon kasta (IMAP ku habboon) Laakin iyada oo aan loo eegin haddii aad isticmaasho shaqada isku dhafan ee Outlook ama Gmail, isticmaal qalab horumarsan sida Boomerang ama hirgelin xal shakhsi - dirida emails wakhti wakhti ah waa qalab qiimo leh oo lagu kordhinayo wax soo saarkaaga.

Dib u laabo