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

Имам доста странна ситуация. Потребител на моя сайт, който е посочен за получаване на уведомителни имейли, не получава своите имейли. След известно по-нататъшно разследване изглежда, че това е причинено от факта, че 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] Грешка 1 # ГРЕШКА: `make' неуспешно'. И така... изглежда тази седмица продължава да хвърля яйца в лицето ми. - 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
Хмммм, ааа...да, това също би било вариант. Реших, че имате предвид външно извикване на активирания скрипт (чрез like curl()) или, алтернативно, просто заобикаляне напълно на функцията за поща на PHP и използване на exec(exim ‹commands›); за изпращане на имейлите. Вашата опция наистина не изисква втори httpd по никакъв начин. - person Battle_707; 25.08.2011