From 905a5c0590fcb266e0adad0527de681418f0d73f Mon Sep 17 00:00:00 2001 From: Ilia Alshanetsky Date: Fri, 9 Jan 2009 14:59:30 +0000 Subject: [PATCH] [DOC] Added mail logging functionality that allows logging of mail sent via mail() function THe logging functionality is disabled by default but can be enabled on a per-directory or globaly via 2 INI settings. The mail.log directive allows you to specify the file where each call to mail() will be logged. The log file will contain the path and line # of the calling script in addition to all of the headers indicated by the user. The mail.add_x_header directive will introduce a X-PHP-Originating-Script header that will contain the file name (no path) of the calling script and the uid of the script. This combination should be sufficient for the admin to locate the sending script. --- NEWS | 2 ++ ext/standard/mail.c | 62 +++++++++++++++++++++++++++++++++++++-------- main/main.c | 2 ++ main/php_globals.h | 3 +++ php.ini-dist | 6 +++++ php.ini-recommended | 6 +++++ 6 files changed, 70 insertions(+), 11 deletions(-) diff --git a/NEWS b/NEWS index 4ff96f6fff..e4f203c2fb 100644 --- a/NEWS +++ b/NEWS @@ -15,6 +15,8 @@ PHP NEWS - Changed open_basedir to allow tightening in runtime contexts. (Sara) - Re-enabled socket_create_pair() on Windows (Kalle) +- Added mail logging functionality that allows logging of mail sent via + mail() function. (Ilia) - Added json_last_error() to return any error information from json_decode(). (Scott) - Added gethostname() to return the current system host name. (Ilia) diff --git a/ext/standard/mail.c b/ext/standard/mail.c index 832287e1bf..2c6f3526af 100644 --- a/ext/standard/mail.c +++ b/ext/standard/mail.c @@ -23,6 +23,8 @@ #include #include "php.h" #include "ext/standard/info.h" +#include "ext/standard/php_string.h" +#include "ext/standard/basic_functions.h" #if HAVE_SYSEXITS_H #include @@ -67,6 +69,8 @@ *p = ' '; \ } \ +extern long php_getuid(void); + /* {{{ proto int ezmlm_hash(string addr) Calculate EZMLM list hash value. */ PHP_FUNCTION(ezmlm_hash) @@ -199,25 +203,61 @@ PHPAPI int php_mail(char *to, char *subject, char *message, char *headers, char int ret; char *sendmail_path = INI_STR("sendmail_path"); char *sendmail_cmd = NULL; + char *mail_log = INI_STR("mail.log"); + char *hdr = headers; #if PHP_SIGCHILD void (*sig_handler)() = NULL; #endif +#define MAIL_RET(val) \ + if (hdr != headers) { \ + efree(hdr); \ + } \ + return val; \ + + if (mail_log) { + char *tmp; + int l = spprintf(&tmp, 0, "mail() on [%s:%d]: To: %s -- Headers: %s\n", zend_get_executed_filename(TSRMLS_C), zend_get_executed_lineno(TSRMLS_C), to, hdr ? hdr : ""); + if (hdr) { /* find all \r\n instances and replace them with spaces, so a log line is always one line long */ + char *p = tmp; + while ((p = strpbrk(p, "\r\n"))) { + *p = ' '; + } + tmp[l - 1] = '\n'; + } + _php_error_log(3, tmp, mail_log, NULL TSRMLS_CC); + efree(tmp); + } + if (PG(mail_x_header)) { + char *tmp = zend_get_executed_filename(TSRMLS_C); + char *f; + size_t f_len; + + php_basename(tmp, strlen(tmp), NULL, 0,&f, &f_len); + + if (headers != NULL) { + spprintf(&hdr, 0, "%s\r\nX-PHP-Originating-Script: %ld:%s\n", headers, php_getuid(), f); + } else { + spprintf(&hdr, 0, "X-PHP-Originating-Script: %ld:%s\n", php_getuid(), f); + } + efree(f); + } + if (!sendmail_path) { #if (defined PHP_WIN32 || defined NETWARE) /* handle old style win smtp sending */ - if (TSendMail(INI_STR("SMTP"), &tsm_err, &tsm_errmsg, headers, subject, to, message, NULL, NULL, NULL TSRMLS_CC) == FAILURE) { + if (TSendMail(INI_STR("SMTP"), &tsm_err, &tsm_errmsg, hdr, subject, to, message, NULL, NULL, NULL TSRMLS_CC) == FAILURE) { if (tsm_errmsg) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", tsm_errmsg); efree(tsm_errmsg); } else { php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", GetSMErrorText(tsm_err)); } - return 0; + MAIL_RET(0); } - return 1; + MAIL_RET(1); #else - return 0; + MAIL_RET(0); #endif } if (extra_cmd != NULL) { @@ -261,13 +301,13 @@ PHPAPI int php_mail(char *to, char *subject, char *message, char *headers, char signal(SIGCHLD, sig_handler); } #endif - return 0; + MAIL_RET(0); } #endif fprintf(sendmail, "To: %s\n", to); fprintf(sendmail, "Subject: %s\n", subject); - if (headers != NULL) { - fprintf(sendmail, "%s\n", headers); + if (hdr != NULL) { + fprintf(sendmail, "%s\n", hdr); } fprintf(sendmail, "\n%s\n", message); ret = pclose(sendmail); @@ -290,9 +330,9 @@ PHPAPI int php_mail(char *to, char *subject, char *message, char *headers, char #endif #endif { - return 0; + MAIL_RET(0); } else { - return 1; + MAIL_RET(1); } } else { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not execute mail delivery program '%s'", sendmail_path); @@ -301,10 +341,10 @@ PHPAPI int php_mail(char *to, char *subject, char *message, char *headers, char signal(SIGCHLD, sig_handler); } #endif - return 0; + MAIL_RET(0); } - return 1; /* never reached */ + MAIL_RET(1); /* never reached */ } /* }}} */ diff --git a/main/main.c b/main/main.c index 7ab84d2c2c..a1cd4ca0e7 100644 --- a/main/main.c +++ b/main/main.c @@ -447,6 +447,8 @@ PHP_INI_BEGIN() PHP_INI_ENTRY("SMTP", "localhost",PHP_INI_ALL, NULL) PHP_INI_ENTRY("smtp_port", "25", PHP_INI_ALL, NULL) + STD_PHP_INI_BOOLEAN("mail.add_x_header", "0", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateBool, mail_x_header, php_core_globals, core_globals) + STD_PHP_INI_ENTRY("mail.log", NULL, PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateString, mail_log, php_core_globals, core_globals) PHP_INI_ENTRY("browscap", NULL, PHP_INI_SYSTEM, NULL) PHP_INI_ENTRY("memory_limit", "128M", PHP_INI_ALL, OnChangeMemoryLimit) PHP_INI_ENTRY("precision", "14", PHP_INI_ALL, OnSetPrecision) diff --git a/main/php_globals.h b/main/php_globals.h index 8c1f0951e6..64b2f734a9 100644 --- a/main/php_globals.h +++ b/main/php_globals.h @@ -165,6 +165,9 @@ struct _php_core_globals { long user_ini_cache_ttl; char *request_order; + + zend_bool mail_x_header; + char *mail_log; }; diff --git a/php.ini-dist b/php.ini-dist index ddb236c6c4..a77fd2048a 100644 --- a/php.ini-dist +++ b/php.ini-dist @@ -747,6 +747,12 @@ smtp_port = 25 ; the 5th parameter to mail(), even in safe mode. ;mail.force_extra_parameters = +; Add X-PHP-Originaiting-Script: that will include uid of the script followed by the filename +mail.add_x_header = Off + +; Log all mail() calls including the full path of the script, line #, to address and headers +mail.log = + [SQL] sql.safe_mode = Off diff --git a/php.ini-recommended b/php.ini-recommended index f888e666f4..fbe046b752 100644 --- a/php.ini-recommended +++ b/php.ini-recommended @@ -799,6 +799,12 @@ smtp_port = 25 ; the 5th parameter to mail(), even in safe mode. ;mail.force_extra_parameters = +; Add X-PHP-Originaiting-Script: that will include uid of the script followed by the filename +mail.add_x_header = On + +; Log all mail() calls including the full path of the script, line #, to address and headers +mail.log = + [SQL] sql.safe_mode = Off -- 2.40.0