Глобально отключить вызов функции, кроме одного места

У меня довольно своеобразная ситуация. Пользователь на моем сайте, который указан для получения уведомлений по электронной почте, не получает свои электронные письма. После некоторого дальнейшего исследования кажется, что это вызвано тем фактом, что exim (по умолчанию) устанавливает 'envelope-from' на @, что не может быть проверено почтовым провайдером пользователя. Вот почему я написал структуру для обработки всех электронных писем некоторое время назад (до того, как я узнал об этом пользователе). Эта функция устанавливает правильные заголовки и устанавливает дополнительный параметр -f, чтобы exim установил правильный адрес электронной почты в качестве адреса отправителя конверта.

Однако по совершенно неизвестным мне причинам этот пользователь, похоже, не получает свои электронные письма, сгенерированные этой функцией. Я тщательно просмотрел свои сценарии и на 99,99% уверен, что нет другого места, откуда этот пользователь мог бы получать свои электронные письма, не говоря уже о том, что нет даже другого вызова функции mail() где-либо в пределах досягаемости. / автоматизированные скрипты. Я хотел бы сказать, что я уверен в этом на 100%, но тот факт, что пользователь по-прежнему получает плохо составленные электронные письма (неправильный конверт и отсутствующие заголовки), как-то противоречит этому. Я написал другой обработчик error_handler, который выполняет расширенную регистрацию, поэтому я знаю, что электронная почта не создается таким образом из-за какой-то ошибки.

Вот почему я хотел бы отключить функцию mail() глобально, чтобы любые вызовы к ней не выполнялись, за исключением одного места в моей почтовой структуре. Поскольку параметр ini disable_functions может быть установлен только в php.ini, я не могу динамически изменить его с помощью ini_set()/ini_restore(). Таким образом, мой вопрос в том, как мне этого добиться?


person Battle_707    schedule 25.08.2011    source источник
comment
Насколько мне известно, это невозможно и было бы непрактично. Вы можете разрешить переопределение INI, но тогда любой, кто знает об INI, может снять ограничения на почтовую функцию для себя.   -  person Bailey Parker    schedule 25.08.2011


Ответы (2)


Настройка disable_functions помечена как изменяемая с PHP_INI_ALL. Это означает, что вы можете установить его с помощью ini_set. Вы также можете добавить его в свой .htaccess файл.

Вы можете использовать override_function, чтобы перехватывать любые вызовы на mail() и перенаправлять их на ваш собственная библиотека.

person Sander Marechal    schedule 25.08.2011
comment
Нет, это не так: us.php.net/manual/en/ini.list .php и us.php.net /manual/en/ini.core.php#ini.disable-functions Его можно установить глобально только в PHP.ini. - person Battle_707; 25.08.2011
comment
Мои извинения, вы правы. Я, должно быть, читал таблицу с перекосом. Позвольте мне дать вам решение, которое работает (см. отредактированный ответ) - person Sander Marechal; 25.08.2011
comment
На самом деле это очень разумное решение. Такое, что, кажется, ускользает от вашего внимания... хех (по крайней мере, так было со мной). Интересно, могу ли я использовать функцию переопределения и отключить функцию в php.ini. Я не уверен, как это структурировано в PHP, но, поскольку disable_functions не отключает пользовательские функции, переопределение его с помощью пользовательской функции должно позволить использовать эту функцию. Я полагаю, это зависит от того, что проверяется в первую очередь. Я проверю и дам вам знать. - person Battle_707; 25.08.2011
comment
На самом деле, у меня возникли трудности с установкой необходимого модуля APD PECL... Он дает мне список вызовов устаревшей функции (zend_get_parameters_ex). Затем он выводит ошибку '# make: *** [php_apd.lo] Error 1 # ERROR: 'make' failed'. Итак... кажется, эта неделя продолжает бросать яйца мне в лицо. - person Battle_707; 26.08.2011
comment
Есть еще одна альтернатива, которую я могу придумать. Поскольку вы можете создавать и устанавливать расширения PECL, я предполагаю, что у вас есть права администратора (root) на вашем компьютере. Вы можете настроить php-fcgi вместо mod_php. Затем вы можете запустить этот сайт под PHP, используя другой файл php.ini и использовать настройку disable_functions ini. Другим вариантом может быть установка xdebug и включение профилировщика. Затем проверьте выходные данные профилировщика на наличие вызовов mail(). - person Sander Marechal; 26.08.2011

Я думаю, вы можете отключить функцию mail() глобально и изменить свой вызов mail(), когда вам нужен какой-то вызов класса, который не использует mail() (должны быть возможные сокеты ведьм) или просто вызов sendmail/qmail/? с exec/системой и т. д.

Вы также можете вызвать другой php-скрипт с помощью exec/system/etc. который использует другой файл конфигурации. Пример скрипта:

<?php
if($argc < 4) {
    die('Usage: php this_script.php mail_to mail_subject mail_message [mail_additional_headers]');
}
mail($argv[1],$argv[2],$argv[3],isset($argv[4])?$argv[4]:NULL);

Пример вызова скрипта:

exec('php  -c path_to_config_file_without_disable_function.ini that_script.php "[email protected]" "some mail subject" "mail body";');
person XzKto    schedule 25.08.2011
comment
У меня нет выделенного почтового сервера, поэтому я не могу вызвать его для отправки почты, и, честно говоря, настройка другого httpd для запуска второй установки PHP действительно не похожа на решение (было бы вопросы безопасности, внешние звонки и т.д.... очень противно). Или, может быть, я совершенно неправильно понимаю, что вы хотите сказать (в этом случае, пожалуйста, объясните подробнее). Я полагаю, что можно было бы отключить функцию php, а затем отправить почту прямо через exim, но, поскольку я не знаком с тем, как это сделать, я бы предпочел решение на основе PHP. - person Battle_707; 25.08.2011
comment
Я обновил свой пост, чтобы немного прояснить его. TLDR: вам не нужен веб-сервер для запуска php-скрипта. - person XzKto; 25.08.2011
comment
Хмммм, ааа... да, это тоже вариант. Я подумал, что вы имели в виду вызов включенного скрипта извне (через вроде curl()) или, в качестве альтернативы, просто полностью обойти почтовую функцию PHP и использовать exec(exim ‹commands›); для отправки писем. Ваш вариант действительно не требует второго httpd. - person Battle_707; 25.08.2011