1999-04-17 00:37:12 +00:00
/*
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
2004-01-08 08:18:22 +00:00
| PHP Version 5 |
1999-04-17 00:37:12 +00:00
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
2008-12-31 11:15:49 +00:00
| Copyright ( c ) 1997 - 2009 The PHP Group |
1999-04-17 00:37:12 +00:00
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
2006-01-01 12:51:34 +00:00
| This source file is subject to version 3.01 of the PHP license , |
1999-07-16 13:13:16 +00:00
| that is bundled with this package in the file LICENSE , and is |
2003-06-10 20:04:29 +00:00
| available through the world - wide - web at the following url : |
2006-01-01 12:51:34 +00:00
| http : //www.php.net/license/3_01.txt |
1999-07-16 13:13:16 +00:00
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world - wide - web , please send a note to |
| license @ php . net so we can mail you a copy immediately . |
1999-04-17 00:37:12 +00:00
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
2002-02-28 08:29:35 +00:00
| Author : Rasmus Lerdorf < rasmus @ php . net > |
1999-04-17 00:37:12 +00:00
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
*/
/* $Id$ */
# include <stdlib.h>
# include <ctype.h>
# include <stdio.h>
# include "php.h"
2000-04-05 21:43:03 +00:00
# include "ext/standard/info.h"
2009-01-09 14:59:30 +00:00
# include "ext/standard/php_string.h"
# include "ext/standard/basic_functions.h"
2002-10-24 13:15:49 +00:00
2001-01-21 17:29:15 +00:00
# if HAVE_SYSEXITS_H
2000-08-03 19:26:19 +00:00
# include <sysexits.h>
1999-04-17 00:37:12 +00:00
# endif
2001-01-21 17:29:15 +00:00
# if HAVE_SYS_SYSEXITS_H
# include <sys/sysexits.h>
# endif
2002-10-24 13:15:49 +00:00
2008-10-03 13:32:41 +00:00
# if PHP_SIGCHILD
# if HAVE_SIGNAL_H
# include <signal.h>
# endif
# endif
1999-12-04 19:19:57 +00:00
# include "php_mail.h"
1999-04-17 00:37:12 +00:00
# include "php_ini.h"
2001-07-05 08:47:37 +00:00
# include "safe_mode.h"
2001-07-08 19:09:59 +00:00
# include "exec.h"
1999-04-17 00:37:12 +00:00
2000-02-11 15:59:30 +00:00
# ifdef PHP_WIN32
1999-04-17 00:37:12 +00:00
# include "win32/sendmail.h"
# endif
2002-09-06 07:27:27 +00:00
# ifdef NETWARE
2005-07-28 09:41:34 +00:00
# define EX_OK 0 /* successful termination */
# define EX_TEMPFAIL 75 /* temp failure; user is invited to retry */
2002-09-06 07:27:27 +00:00
# endif
2007-11-06 17:58:53 +00:00
# define SKIP_LONG_HEADER_SEP(str, pos) \
2003-02-24 19:41:18 +00:00
if ( str [ pos ] = = ' \r ' & & str [ pos + 1 ] = = ' \n ' & & ( str [ pos + 2 ] = = ' ' | | str [ pos + 2 ] = = ' \t ' ) ) { \
2007-11-06 17:58:53 +00:00
pos + = 2 ; \
while ( str [ pos + 1 ] = = ' ' | | str [ pos + 1 ] = = ' \t ' ) { \
pos + + ; \
} \
continue ; \
} \
2003-02-24 19:41:18 +00:00
2007-11-06 17:58:53 +00:00
# define MAIL_ASCIIZ_CHECK(str, len) \
p = str ; \
e = p + len ; \
2007-03-27 09:20:27 +00:00
while ( ( p = memchr ( p , ' \0 ' , ( e - p ) ) ) ) { \
2007-11-06 17:58:53 +00:00
* p = ' ' ; \
} \
2007-03-27 00:13:09 +00:00
2009-01-09 14:59:30 +00:00
extern long php_getuid ( void ) ;
2000-06-29 14:07:10 +00:00
/* {{{ proto int ezmlm_hash(string addr)
Calculate EZMLM list hash value . */
PHP_FUNCTION ( ezmlm_hash )
{
2002-08-26 09:47:46 +00:00
char * str = NULL ;
2009-04-15 14:24:38 +00:00
unsigned int h = 5381 ;
2001-12-02 17:57:17 +00:00
int j , str_len ;
2007-11-06 17:58:53 +00:00
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) TSRMLS_CC , " s " , & str , & str_len ) = = FAILURE ) {
2001-12-02 17:57:17 +00:00
return ;
2000-06-29 14:07:10 +00:00
}
2002-08-26 09:47:46 +00:00
for ( j = 0 ; j < str_len ; j + + ) {
h = ( h + ( h < < 5 ) ) ^ ( unsigned long ) ( unsigned char ) tolower ( str [ j ] ) ;
2000-06-29 14:07:10 +00:00
}
2007-11-06 17:58:53 +00:00
2002-08-26 09:47:46 +00:00
h = ( h % 53 ) ;
2007-11-06 17:58:53 +00:00
2000-06-29 14:07:10 +00:00
RETURN_LONG ( ( int ) h ) ;
}
2001-06-05 13:12:10 +00:00
/* }}} */
2000-06-29 14:07:10 +00:00
2001-02-05 21:30:29 +00:00
/* {{{ proto int mail(string to, string subject, string message [, string additional_headers [, string additional_parameters]])
1999-04-17 00:37:12 +00:00
Send an email message */
1999-05-16 11:19:26 +00:00
PHP_FUNCTION ( mail )
1999-04-17 00:37:12 +00:00
{
2002-08-26 09:47:46 +00:00
char * to = NULL , * message = NULL , * headers = NULL ;
char * subject = NULL , * extra_cmd = NULL ;
2008-10-21 22:08:38 +00:00
int to_len , message_len , headers_len = 0 ;
int subject_len , extra_cmd_len = 0 , i ;
2004-08-03 06:25:25 +00:00
char * force_extra_parameters = INI_STR ( " mail.force_extra_parameters " ) ;
2003-10-20 14:22:01 +00:00
char * to_r , * subject_r ;
2007-03-27 00:13:09 +00:00
char * p , * e ;
2002-07-02 13:56:47 +00:00
if ( PG ( safe_mode ) & & ( ZEND_NUM_ARGS ( ) = = 5 ) ) {
2007-09-30 05:49:45 +00:00
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " SAFE MODE Restriction in effect. The fifth parameter is disabled in SAFE MODE " ) ;
2002-07-02 14:22:22 +00:00
RETURN_FALSE ;
2007-11-06 17:58:53 +00:00
}
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) TSRMLS_CC , " sss|ss " , & to , & to_len , & subject , & subject_len , & message , & message_len ,
& headers , & headers_len , & extra_cmd , & extra_cmd_len ) = = FAILURE
) {
2001-12-02 17:57:17 +00:00
return ;
1999-04-17 00:37:12 +00:00
}
2007-03-27 00:13:09 +00:00
/* ASCIIZ check */
MAIL_ASCIIZ_CHECK ( to , to_len ) ;
MAIL_ASCIIZ_CHECK ( subject , subject_len ) ;
MAIL_ASCIIZ_CHECK ( message , message_len ) ;
if ( headers ) {
MAIL_ASCIIZ_CHECK ( headers , headers_len ) ;
}
if ( extra_cmd ) {
MAIL_ASCIIZ_CHECK ( extra_cmd , extra_cmd_len ) ;
}
2002-06-13 18:54:45 +00:00
if ( to_len > 0 ) {
2003-10-20 14:22:01 +00:00
to_r = estrndup ( to , to_len ) ;
2002-08-26 09:47:46 +00:00
for ( ; to_len ; to_len - - ) {
2003-10-20 14:22:01 +00:00
if ( ! isspace ( ( unsigned char ) to_r [ to_len - 1 ] ) ) {
2002-08-26 09:47:46 +00:00
break ;
}
2003-10-20 14:22:01 +00:00
to_r [ to_len - 1 ] = ' \0 ' ;
2002-08-24 11:37:50 +00:00
}
2003-10-20 14:22:01 +00:00
for ( i = 0 ; to_r [ i ] ; i + + ) {
if ( iscntrl ( ( unsigned char ) to_r [ i ] ) ) {
2003-02-24 19:41:18 +00:00
/* According to RFC 822, section 3.1.1 long headers may be separated into
* parts using CRLF followed at least one linear - white - space character ( ' \t ' or ' ' ) .
* To prevent these separators from being replaced with a space , we use the
2007-11-06 17:58:53 +00:00
* SKIP_LONG_HEADER_SEP to skip over them . */
2003-10-20 14:22:01 +00:00
SKIP_LONG_HEADER_SEP ( to_r , i ) ;
to_r [ i ] = ' ' ;
2002-08-24 11:37:50 +00:00
}
2002-06-13 18:54:45 +00:00
}
2003-10-20 14:22:01 +00:00
} else {
to_r = to ;
2007-11-06 17:58:53 +00:00
}
1999-04-17 00:37:12 +00:00
2002-06-13 18:54:45 +00:00
if ( subject_len > 0 ) {
2003-10-20 14:22:01 +00:00
subject_r = estrndup ( subject , subject_len ) ;
2002-08-26 09:47:46 +00:00
for ( ; subject_len ; subject_len - - ) {
2003-10-20 14:22:01 +00:00
if ( ! isspace ( ( unsigned char ) subject_r [ subject_len - 1 ] ) ) {
2002-08-26 09:47:46 +00:00
break ;
}
2003-10-20 14:22:01 +00:00
subject_r [ subject_len - 1 ] = ' \0 ' ;
2002-08-24 11:37:50 +00:00
}
2007-11-06 17:58:53 +00:00
for ( i = 0 ; subject_r [ i ] ; i + + ) {
2003-10-20 14:22:01 +00:00
if ( iscntrl ( ( unsigned char ) subject_r [ i ] ) ) {
SKIP_LONG_HEADER_SEP ( subject_r , i ) ;
subject_r [ i ] = ' ' ;
2002-08-24 11:37:50 +00:00
}
2002-06-13 18:54:45 +00:00
}
2003-11-30 19:56:30 +00:00
} else {
subject_r = subject ;
1999-04-17 00:37:12 +00:00
}
2003-02-26 20:04:16 +00:00
if ( force_extra_parameters ) {
2007-07-10 20:21:24 +00:00
extra_cmd = php_escape_shell_cmd ( force_extra_parameters ) ;
2003-02-26 20:04:16 +00:00
} else if ( extra_cmd ) {
2002-08-26 09:44:31 +00:00
extra_cmd = php_escape_shell_cmd ( extra_cmd ) ;
}
2007-03-27 00:13:09 +00:00
2003-10-20 14:22:01 +00:00
if ( php_mail ( to_r , subject_r , message , headers , extra_cmd TSRMLS_CC ) ) {
2001-07-05 08:47:37 +00:00
RETVAL_TRUE ;
1999-04-17 00:37:12 +00:00
} else {
2001-07-05 08:47:37 +00:00
RETVAL_FALSE ;
1999-04-17 00:37:12 +00:00
}
2001-12-02 17:57:17 +00:00
2002-08-26 09:47:46 +00:00
if ( extra_cmd ) {
efree ( extra_cmd ) ;
}
2004-01-09 01:35:44 +00:00
if ( to_r ! = to ) {
2003-10-20 14:22:01 +00:00
efree ( to_r ) ;
}
2004-01-09 01:35:44 +00:00
if ( subject_r ! = subject ) {
2003-10-20 14:22:01 +00:00
efree ( subject_r ) ;
}
1999-04-17 00:37:12 +00:00
}
/* }}} */
2001-06-05 13:12:10 +00:00
/* {{{ php_mail
*/
2002-03-16 12:45:43 +00:00
PHPAPI int php_mail ( char * to , char * subject , char * message , char * headers , char * extra_cmd TSRMLS_DC )
1999-04-17 00:37:12 +00:00
{
2002-09-06 07:27:27 +00:00
# if (defined PHP_WIN32 || defined NETWARE)
1999-04-17 00:37:12 +00:00
int tsm_err ;
2002-05-14 20:43:48 +00:00
char * tsm_errmsg = NULL ;
2001-07-08 22:30:11 +00:00
# endif
1999-04-17 00:37:12 +00:00
FILE * sendmail ;
int ret ;
char * sendmail_path = INI_STR ( " sendmail_path " ) ;
2001-02-05 21:30:29 +00:00
char * sendmail_cmd = NULL ;
2009-01-09 14:59:30 +00:00
char * mail_log = INI_STR ( " mail.log " ) ;
char * hdr = headers ;
2008-10-03 13:32:41 +00:00
# if PHP_SIGCHILD
void ( * sig_handler ) ( ) = NULL ;
# endif
1999-04-17 00:37:12 +00:00
2009-01-09 14:59:30 +00:00
# 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 : " " ) ;
2009-01-13 21:29:12 +00:00
php_stream * stream = php_stream_open_wrapper ( mail_log , " a " , IGNORE_URL_WIN | REPORT_ERRORS | STREAM_DISABLE_OPEN_BASEDIR , NULL ) ;
2009-01-09 14:59:30 +00:00
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 ' ;
}
2009-01-13 21:29:12 +00:00
if ( stream ) {
php_stream_write ( stream , tmp , l ) ;
php_stream_close ( stream ) ;
}
2009-01-09 14:59:30 +00:00
efree ( tmp ) ;
}
if ( PG ( mail_x_header ) ) {
char * tmp = zend_get_executed_filename ( TSRMLS_C ) ;
char * f ;
size_t f_len ;
2009-01-09 15:08:10 +00:00
php_basename ( tmp , strlen ( tmp ) , NULL , 0 , & f , & f_len TSRMLS_CC ) ;
2009-01-09 14:59:30 +00:00
if ( headers ! = NULL ) {
2009-06-21 15:29:16 +00:00
spprintf ( & hdr , 0 , " X-PHP-Originating-Script: %ld:%s \r \n %s " , php_getuid ( ) , f , headers ) ;
2009-01-09 14:59:30 +00:00
} else {
spprintf ( & hdr , 0 , " X-PHP-Originating-Script: %ld:%s \n " , php_getuid ( ) , f ) ;
}
efree ( f ) ;
}
2001-07-08 22:30:11 +00:00
if ( ! sendmail_path ) {
2002-09-06 07:27:27 +00:00
# if (defined PHP_WIN32 || defined NETWARE)
2001-07-08 22:30:11 +00:00
/* handle old style win smtp sending */
2009-01-09 14:59:30 +00:00
if ( TSendMail ( INI_STR ( " SMTP " ) , & tsm_err , & tsm_errmsg , hdr , subject , to , message , NULL , NULL , NULL TSRMLS_CC ) = = FAILURE ) {
2002-05-14 20:43:48 +00:00
if ( tsm_errmsg ) {
2002-08-24 01:19:28 +00:00
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " %s " , tsm_errmsg ) ;
2002-05-14 20:43:48 +00:00
efree ( tsm_errmsg ) ;
} else {
2002-08-24 01:19:28 +00:00
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " %s " , GetSMErrorText ( tsm_err ) ) ;
2002-05-14 20:43:48 +00:00
}
2009-01-09 14:59:30 +00:00
MAIL_RET ( 0 ) ;
2001-07-08 22:30:11 +00:00
}
2009-01-09 14:59:30 +00:00
MAIL_RET ( 1 ) ;
1999-04-17 00:37:12 +00:00
# else
2009-01-09 14:59:30 +00:00
MAIL_RET ( 0 ) ;
2001-07-08 22:30:11 +00:00
# endif
1999-04-17 00:37:12 +00:00
}
2001-02-05 21:30:29 +00:00
if ( extra_cmd ! = NULL ) {
2007-01-25 00:26:51 +00:00
spprintf ( & sendmail_cmd , 0 , " %s %s " , sendmail_path , extra_cmd ) ;
2001-02-05 21:30:29 +00:00
} else {
sendmail_cmd = sendmail_path ;
}
2008-10-03 13:32:41 +00:00
# if PHP_SIGCHILD
/* Set signal handler of SIGCHLD to default to prevent other signal handlers
* from being called and reaping the return code when our child exits .
* The original handler needs to be restored after pclose ( ) */
sig_handler = ( void * ) signal ( SIGCHLD , SIG_DFL ) ;
if ( sig_handler = = SIG_ERR ) {
sig_handler = NULL ;
}
# endif
2001-07-08 22:30:11 +00:00
# ifdef PHP_WIN32
sendmail = popen ( sendmail_cmd , " wb " ) ;
# else
2002-03-16 12:45:43 +00:00
/* Since popen() doesn't indicate if the internal fork() doesn't work
* ( e . g . the shell can ' t be executed ) we explicitely set it to 0 to be
* sure we don ' t catch any older errno value . */
errno = 0 ;
2001-02-05 21:30:29 +00:00
sendmail = popen ( sendmail_cmd , " w " ) ;
2001-07-08 22:30:11 +00:00
# endif
2007-11-06 17:58:53 +00:00
if ( extra_cmd ! = NULL ) {
2001-02-05 21:30:29 +00:00
efree ( sendmail_cmd ) ;
2007-11-06 17:58:53 +00:00
}
1999-04-17 00:37:12 +00:00
if ( sendmail ) {
2002-03-16 12:45:43 +00:00
# ifndef PHP_WIN32
if ( EACCES = = errno ) {
2003-08-27 23:53:15 +00:00
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " Permission denied: unable to execute shell to run mail delivery binary '%s' " , sendmail_path ) ;
2002-03-16 15:42:34 +00:00
pclose ( sendmail ) ;
2008-10-03 13:32:41 +00:00
# if PHP_SIGCHILD
/* Restore handler in case of error on Windows
Not sure if this applicable on Win but just in case . */
if ( sig_handler ) {
signal ( SIGCHLD , sig_handler ) ;
}
# endif
2009-01-09 14:59:30 +00:00
MAIL_RET ( 0 ) ;
2002-03-16 12:45:43 +00:00
}
# endif
2003-05-07 20:33:53 +00:00
fprintf ( sendmail , " To: %s \n " , to ) ;
fprintf ( sendmail , " Subject: %s \n " , subject ) ;
2009-01-09 14:59:30 +00:00
if ( hdr ! = NULL ) {
fprintf ( sendmail , " %s \n " , hdr ) ;
1999-04-17 00:37:12 +00:00
}
fprintf ( sendmail , " \n %s \n " , message ) ;
ret = pclose ( sendmail ) ;
2007-11-06 17:58:53 +00:00
2008-10-03 13:32:41 +00:00
# if PHP_SIGCHILD
if ( sig_handler ) {
signal ( SIGCHLD , sig_handler ) ;
}
# endif
2001-07-08 22:30:11 +00:00
# ifdef PHP_WIN32
if ( ret = = - 1 )
# else
2001-03-21 15:15:31 +00:00
# if defined(EX_TEMPFAIL)
2002-03-16 15:50:20 +00:00
if ( ( ret ! = EX_OK ) & & ( ret ! = EX_TEMPFAIL ) )
2002-11-28 08:23:36 +00:00
# elif defined(EX_OK)
2002-03-16 15:50:20 +00:00
if ( ret ! = EX_OK )
2002-11-28 08:23:36 +00:00
# else
if ( ret ! = 0 )
2001-07-08 22:30:11 +00:00
# endif
2001-03-21 15:15:31 +00:00
# endif
2001-07-08 22:30:11 +00:00
{
2009-01-09 14:59:30 +00:00
MAIL_RET ( 0 ) ;
1999-04-17 00:37:12 +00:00
} else {
2009-01-09 14:59:30 +00:00
MAIL_RET ( 1 ) ;
1999-04-17 00:37:12 +00:00
}
} else {
2003-08-27 23:53:15 +00:00
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " Could not execute mail delivery program '%s' " , sendmail_path ) ;
2008-10-03 13:32:41 +00:00
# if PHP_SIGCHILD
if ( sig_handler ) {
signal ( SIGCHLD , sig_handler ) ;
}
# endif
2009-01-09 14:59:30 +00:00
MAIL_RET ( 0 ) ;
1999-04-17 00:37:12 +00:00
}
2002-01-27 07:15:07 +00:00
2009-01-09 14:59:30 +00:00
MAIL_RET ( 1 ) ; /* never reached */
1999-04-17 00:37:12 +00:00
}
2001-06-05 13:12:10 +00:00
/* }}} */
1999-04-17 00:37:12 +00:00
2001-06-05 13:12:10 +00:00
/* {{{ PHP_MINFO_FUNCTION
*/
1999-07-26 20:09:08 +00:00
PHP_MINFO_FUNCTION ( mail )
2002-09-22 16:23:44 +00:00
{
2001-07-08 22:30:11 +00:00
char * sendmail_path = INI_STR ( " sendmail_path " ) ;
2001-07-30 06:18:13 +00:00
# ifdef PHP_WIN32
if ( ! sendmail_path ) {
2002-03-16 15:50:20 +00:00
php_info_print_table_row ( 2 , " Internal Sendmail Support for Windows " , " enabled " ) ;
2001-07-30 06:18:13 +00:00
} else {
2002-03-16 15:50:20 +00:00
php_info_print_table_row ( 2 , " Path to sendmail " , sendmail_path ) ;
2001-07-30 06:18:13 +00:00
}
# else
2002-03-16 15:50:20 +00:00
php_info_print_table_row ( 2 , " Path to sendmail " , sendmail_path ) ;
1999-04-17 00:37:12 +00:00
# endif
}
2001-06-05 13:12:10 +00:00
/* }}} */
1999-04-17 00:37:12 +00:00
/*
* Local variables :
* tab - width : 4
2001-06-05 13:12:10 +00:00
* c - basic - offset : 4
1999-04-17 00:37:12 +00:00
* End :
2001-09-09 13:29:31 +00:00
* vim600 : sw = 4 ts = 4 fdm = marker
* vim < 600 : sw = 4 ts = 4
1999-04-17 00:37:12 +00:00
*/