Пересылка писем с помощью скрипта PHP

У нас есть cron'ed PHP-скрипт, который проверяет входящие сообщения каждые десять минут. Целью этого скрипта является обработка функции "STOP для выхода" для нашего сервиса SMS-уведомлений, который мы предоставляем. Если скрипт находит какие-либо электронные письма со словом "СТОП" в начале электронного письма, мы удаляем пользователя из нашей базы данных уведомлений.

Чтобы охватить наши базы, мы хотели бы, чтобы любые электронные письма, которые не соответствуют вышеуказанным критериям, пересылались на другой адрес электронной почты (который является псевдонимом), который несколько человек получают и проверяют ежечасно. Однако у нас возникают проблемы с пересылкой писем из этого скрипта PHP.

Зная, как mail Функция PHP работает, совершенно очевидно, что нам нужно заново вставить заголовки перед отправкой по почте. Однако многокомпонентные электронные письма MIME всегда отправляются в виде искаженного текста, включая барьеры и любые вложения, закодированные в base64.

Кто-нибудь знает простой способ получить сообщение электронной почты и правильно переслать его с помощью сценария PHP?

Мы используем встроенные функции IMAP, встроенные в PHP 5. У нас также есть доступ к модулю PEAR Mail. Однако мы не смогли найти ни одного примера или людей, выполняющих аналогичные задачи, выполнив поиск в Google.

5 ответов

Решение

Я давно кодировал этот метод, чтобы разобрать сообщение электронной почты на соответствующие части с помощью IMAP:

function Message_Parse($id)
{
    if (is_resource($this->connection))
    {
        $result = array
        (
            'text' => null,
            'html' => null,
            'attachments' => array(),
        );

        $structure = imap_fetchstructure($this->connection, $id, FT_UID);

        if (array_key_exists('parts', $structure))
        {
            foreach ($structure->parts as $key => $part)
            {
                if (($part->type >= 2) || (($part->ifdisposition == 1) && ($part->disposition == 'ATTACHMENT')))
                {
                    $filename = null;

                    if ($part->ifparameters == 1)
                    {
                        $total_parameters = count($part->parameters);

                        for ($i = 0; $i < $total_parameters; $i++)
                        {
                            if (($part->parameters[$i]->attribute == 'NAME') || ($part->parameters[$i]->attribute == 'FILENAME'))
                            {
                                $filename = $part->parameters[$i]->value;

                                break;
                            }
                        }

                        if (is_null($filename))
                        {
                            if ($part->ifdparameters == 1)
                            {
                                $total_dparameters = count($part->dparameters);

                                for ($i = 0; $i < $total_dparameters; $i++)
                                {
                                    if (($part->dparameters[$i]->attribute == 'NAME') || ($part->dparameters[$i]->attribute == 'FILENAME'))
                                    {
                                        $filename = $part->dparameters[$i]->value;

                                        break;
                                    }
                                }
                            }
                        }
                    }

                    $result['attachments'][] = array
                    (
                        'filename' => $filename,
                        'content' => str_replace(array("\r", "\n"), '', trim(imap_fetchbody($this->connection, $id, ($key + 1), FT_UID))),
                    );
                }

                else
                {
                    if ($part->subtype == 'PLAIN')
                    {
                        $result['text'] = imap_fetchbody($this->connection, $id, ($key + 1), FT_UID);
                    }

                    else if ($part->subtype == 'HTML')
                    {
                        $result['html'] = imap_fetchbody($this->connection, $id, ($key + 1), FT_UID);
                    }

                    else
                    {
                        foreach ($part->parts as $alternative_key => $alternative_part)
                        {
                            if ($alternative_part->subtype == 'PLAIN')
                            {
                                echo '<h2>' . $alternative_part->subtype . ' ' . $alternative_part->encoding . '</h2>';

                                $result['text'] = imap_fetchbody($this->connection, $id, ($key + 1) . '.' . ($alternative_key + 1), FT_UID);
                            }

                            else if ($alternative_part->subtype == 'HTML')
                            {
                                echo '<h2>' . $alternative_part->subtype . ' ' . $alternative_part->encoding . '</h2>';

                                $result['html'] = imap_fetchbody($this->connection, $id, ($key + 1) . '.' . ($alternative_key + 1), FT_UID);
                            }
                        }
                    }
                }
            }
        }

        else
        {
            $result['text'] = imap_body($this->connection, $id, FT_UID);
        }

        $result['text'] = imap_qprint($result['text']);
        $result['html'] = imap_qprint(imap_8bit($result['html']));

        return $result;
    }

    return false;
}

Я никогда не тестировал его глубоко, и я уверен, что в нем есть некоторые ошибки, но это может быть началом... После адаптации этого кода вы сможете использовать $result индексы (text, html, attachments) с вашим сценарием пересылки (например, с использованием SwiftMailer), не беспокоясь о сохранности границ MIME.

На самом деле это не ответ, а предложение альтернативного метода. Я думаю, что было бы намного проще и менее подвержено ошибкам (то есть, никаких проблем с доставкой), если бы вы просто перемещали сообщения в разные папки существующей учетной записи. Т.е. cron запускает и обрабатывает все электронные письма в INBOX. Если if находит STOP, он выполняет требуемую работу, а затем (через функции IMAP) просто перемещает электронное письмо в подпапку с именем "Обработано" или аналогичную. В противном случае он перемещает электронное письмо в подпапку с именем "Проверить эти" или аналогичную. Тогда вам не нужно беспокоиться о переадресации, дальнейших доставках или второй учетной записи, и каждый может непосредственно следить за обработанной, необработанной и ожидающей почтой.

Это случилось со мной раньше. Чтобы это исправить, мне нужно было выполнить imap_base64() в теле письма после того, как я использовал imap_fetchbody().

$body = imap_fetchbody($imap, 1, 1);
$headers = imap_headerinfo($imap, 1);
$body = imap_base64($body);

Вы взглянули на функциональность, используя библиотеку Swiftmailer?

http://swiftmailer.org/

Я использовал это в прошлом и получил хороший результат, хотя и не в приложении, как вы описали, однако я использовал его для "списков рассылки" на основе PHP, где я проверил тему и отправил в соответствующую группу.

Но я создал новое сообщение, не перешли. Надеюсь, это поможет.

Используйте обработчик ввода-вывода, чтобы захватить содержимое письма в виде строки, разделить заголовки и затем использовать функцию php 'mail()' для отправки.

Иначе, если вы действительно хотите сделать это с php-imap,

Расширением php-imap является libc-client, который является частью программного обеспечения почтового клиента pine. Выясните, какие шаги необходимо выполнить вручную, используя pine, а затем посмотрите на вызовы c-client, которые pine делает для этого. это даст вам шаги, необходимые в php.

документация c-client довольно минимальна, лучше узнать подробности об использовании исходного кода сосны.

Я думаю, вы можете обнаружить, что автор расширения php "для вашего удобства или защиты" пропустил или изменил материал, который блокирует этот путь.

Другие вопросы по тегам