Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

[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.
  • Loading branch information...
commit 905a5c0590fcb266e0adad0527de681418f0d73f 1 parent 7d3d47f
Ilia Alshanetsky authored
2  NEWS
View
@@ -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)
62 ext/standard/mail.c
View
@@ -23,6 +23,8 @@
#include <stdio.h>
#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 <sysexits.h>
@@ -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 */
}
/* }}} */
2  main/main.c
View
@@ -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)
3  main/php_globals.h
View
@@ -165,6 +165,9 @@ struct _php_core_globals {
long user_ini_cache_ttl;
char *request_order;
+
+ zend_bool mail_x_header;
+ char *mail_log;
};
6 php.ini-dist
View
@@ -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
6 php.ini-recommended
View
@@ -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
Please sign in to comment.
Something went wrong with that request. Please try again.