Как правильно настроить уникальные адреса электронной почты для каждого пользователя, которые все перенаправляются на php-скрипт?

У меня есть веб-приложение с ок. 30 тысяч пользователей и быстро растет. Мы хотим включить некоторые функции по электронной почте, что означает назначение каждому пользователю уникального адреса электронной почты (из соображений безопасности). Письма, отправленные на эти уникальные адреса, должны перенаправляться на PHP-скрипт. PHP-скрипту необходим доступ ко всем частям электронного письма — заголовкам, телу и любым вложениям. Я не уверен, как правильно это настроить. В настоящее время мы используем sendmail и предпочли бы придерживаться его (если это имеет значение, это Linux). Мне удалось получить индивидуальную переадресацию электронной почты в сценарий, но он не масштабируется (на мой взгляд) для создания псевдонимов 30k, а затем нового каждый раз, когда новый пользователь регистрируется. Я был бы намного счастливее с каким-то универсальным решением на основе RegEx, которое просто сообщает скрипту PHP уникальный адрес электронной почты, который был получателем, что позволило бы нам найти пользователя.


person Dave    schedule 06.09.2012    source источник


Ответы (3)


30 000 аккаунтов не предоставляют нам никакой информации о трафике, который вы ожидаете обрабатывать. Но допустим, это другой вопрос.

Вы можете создать учетную запись типа catch all, которая будет просто принимать любую электронную почту в домене, в котором вы создаете адреса своих пользователей (в основном *@domain). Затем вы можете запустить свой сценарий обработки для каждой входящей почты (обычно вы можете получить все тело почты из потока stdin (в PHP, доступном через php://stdin) и обработать его по своему усмотрению. Но это плохо, если вы хотите использовать PHP (или почти любой скриптовый язык), так как каждое письмо должно будет порождать новый PHP-процесс, инициализировать все расширения и т. д. Все это требует времени и ресурсов, а один большой спам-флуд — и ваш ящик почти поджарен.

В качестве альтернативы вы можете собирать свою почту в почтовом ящике, как и любую другую почту, а затем ваш скрипт получает ее оттуда (либо напрямую, копаясь в maildir, либо через почтовые протоколы, такие как IMAP или POP). Это выглядит лучше с точки зрения администрирования, и пока ваш почтовый сервер может принимать входящие письма, вся ваша система все еще работает. Вы даже можете попытаться «разбить» свою систему, установив некоторые правила фильтрации (на уровне MTA) и доставлять входящие письма не в один почтовый ящик, а в несколько. Тогда вы сможете обрабатывать эти письма параллельно с меньшими трудностями (не нужно беспокоиться об обработке одной и той же почты более чем одним экземпляром и т. д.). Схема «раздела» может быть совершенно любой, т. е. в зависимости от вашей схемы именования полных адресов, если на основе букв, это будет отдельный почтовый ящик для a*@, b*@ или [a-d]*@] (зависит от трафика), на самом деле не имеет значения.

В качестве альтернативы вы можете попытаться поместить тела входящих писем в базу данных, а затем обработать их, как описано выше, без какой-либо обработки POP/IMAP.

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

EDIT: (чтобы ответить на вопрос комментария и не превышать лимит размера комментария)

Я недостаточно знаком с Sendmail, чтобы давать вам точные директивы по настройке (я работаю с настроенным qmail), но надеюсь, что некоторые общие подсказки будут применимы. Во-первых, я считаю, что Sendmail поддерживает виртуальных пользователей (что означает почтовые ящики для пользователей, которых нет в /etc/passwd). Если это так, то MTA обычно должен позволять вам запрашивать БД (чтобы узнать, действителен ли целевой адрес электронной почты и где находится домашний каталог этого пользователя, чтобы поместить почту) с помощью некоторых встроенных провайдеров. Или (что еще лучше) вызвать для этого внешнюю программу. Последний здесь является победителем, потому что пользователей на самом деле нет, поэтому вы можете написать небольшой скрипт или (опять же, лучше для производительности) приложение C, которое сделает свое дело. Поскольку все, что вам нужно, это «разделить» входящую почту на несколько физических почтовых ящиков на основе некоторых простых предопределенных правил, пару if()s + substr()s и все готово. Пара строк, БД не нужна, довольно быстро. Или, что еще лучше, вы могли бы даже попробовать здесь самый глупый подход roundrobin — на самом деле не имеет значения, попадает ли почта в accountA или accountB, если 50% писем заканчиваются на A, а другие 50% на B (или 25%, если вы пойти на 4 целевых аккаунта и т. д.) и это единственное условие, которое вас должно волновать, я думаю. Вы можете попробовать использовать для этого procmail, но я думаю, что это бессмысленно и не лучше для производительности.

Что касается помещения писем в базу данных. Это зависит от MTA - по умолчанию никто так не делает, так как это медленнее, чем размещение почты в почтовых каталогах (поскольку БД обычно является другим хостом), но все же есть пара решений. Либо ищите сторонние патчи для Sendmail, которые делают это, либо добавьте другой скрипт/приложение, которое будет «копировать» почту из физических почтовых ящиков в БД. Вы можете сказать - но это было бы медленнее. Конечно, но опять же - я не знаю, действительно ли обработка не в реальном времени имеет значение в вашем случае (моя слепая догадка - нет), так зачем на самом деле беспокоиться. Если вы сэкономите здесь пару миллисекунд, но потеряете минуты на дальнейшее обслуживание всего решения, то выбор вполне очевиден.

Кстати: на всякий случай - всякий раз, когда я писал mailbox, я определенно имел в виду контейнер для почты пользователя, а НЕ формат файла mailbox. Что касается формата файла maildir (или что-то производное), то это гораздо лучший выбор.

person Marcin Orlowski    schedule 10.09.2012
comment
Определенно верно. Универсальная учетная запись — лучшее решение. - person Alain Tiemblo; 11.09.2012
comment
Кажется, это имеет смысл. Знаете ли вы больше о том, как разделить систему с помощью sendmail и создать правила фильтрации? Можно ли это сделать с помощью какого-либо типа RegEx? Это было бы идеальным решением. В качестве альтернативы, что вы имеете в виду, когда говорите, что можете помещать входящие письма в БД, а затем обрабатывать? Как бы я сделал это без непосредственного участия PHP-скрипта? - person Dave; 11.09.2012

Вы действительно хотите раскошелиться на PHP для каждого входящего письма? Это может дорого обойтись, если вы имеете дело с приличным объемом почты. Почему бы не иметь собственный обратный вызов на вашем почтовом сервере, который обрабатывает входящую почту и вставляет ее в базу данных, а затем рабочий сценарий, который постоянно опрашивает новые сообщения для обработки?

Часть mail-to-db должна быть намного легче, чем вся обработка, и это дает вам свободную очередь, так что, если вы получаете кучу запросов почти в одно и то же время, ваша система не падает, пытаясь обработать их все сразу.

person Tyler Eaves    schedule 10.09.2012

сделал аналогичную реализацию этого, хотя и в меньшем масштабе... должен масштабироваться, чтобы соответствовать вашим целям.

две отдельные проблемы

(1) почта - всеобъемлющее, как уже упоминалось, является хорошим решением, хотя вам придется иметь дело со спамом и неправильно сформированными адресами электронной почты (что может быть как хорошо, так и плохо). Если вы являетесь владельцем сервера, простое присвоение псевдонимов «фиктивным» учетным записям и указание почтовому серверу поместить их все в один и тот же центральный почтовый ящик выполнит задачу, поскольку вам не нужны отдельные фактические учетные записи, а информация заголовка останется нетронутой. особенности зависят от вашего почтового решения, но любой почтовый сервер должен быть более чем оборудован для выполнения этой задачи и объема, и вы должны быть в состоянии написать сценарий создания псевдонима... в противном случае вернитесь к универсальному

(2) Анализ и обработка PHP - встроенные функции PHP pop3 могут легко обрабатывать проверку (теперь) одной учетной записи электронной почты и обработку сообщений; Некоторые примеры функций, которые я использовал для этого:

function pop3_login($host,$port,$user,$pass,$folder="INBOX",$ssl=false){
        $ssl=($ssl==false)?"/novalidate-cert":"";
        return (imap_open("{"."$host:$port/pop3$ssl"."}$folder",$user,$pass,OP_SILENT));
}
function pop3_stat($connection){
        $check = imap_mailboxmsginfo($connection); # changed from $imap
        return ((array)$check);
}
function pop3_retr($connection,$message,$section='1'){
        return(quoted_printable_decode(imap_fetchbody($connection,$message,$section)));
}
function pop3_dele($connection,$message){
        return(imap_delete($connection,$message));
}
function pop3_close($connection){
        return(imap_close($connection,CL_EXPUNGE));
}

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

person Dave    schedule 14.09.2012