1999-04-08 05:05:13 +08:00
/*
* PHP Sendmail for Windows .
*
* This file is rewriten specificly for PHPFI . Some functionality
* has been removed ( MIME and file attachments ) . This code was
* modified from code based on code writen by Jarle Aase .
*
* This class is based on the original code by Jarle Aase , see bellow :
* wSendmail . cpp It has been striped of some functionality to match
* the requirements of phpfi .
*
* Very simple SMTP Send - mail program for sending command - line level
* emails and CGI - BIN form response for the Windows platform .
*
2000-08-04 12:49:45 +08:00
* The complete wSendmail package with source code can be located
* from http : //www.jgaa.com
1999-04-08 05:05:13 +08:00
*
*/
2001-12-21 02:06:13 +08:00
/* $Id$ */
1999-04-08 05:05:13 +08:00
# include "php.h" /*php specific */
# include <stdio.h>
# include <stdlib.h>
2003-01-03 23:17:43 +08:00
# ifndef NETWARE
2003-02-16 11:48:49 +08:00
# include <winsock2.h>
2005-02-25 13:57:41 +08:00
# include "time.h"
2012-03-04 23:08:12 +08:00
# include <Ws2tcpip.h>
2003-01-03 23:17:43 +08:00
# else /* NETWARE */
2005-02-25 13:57:41 +08:00
# include <netware/sendmail_nw.h>
2003-01-03 23:17:43 +08:00
# endif /* NETWARE */
1999-04-08 05:05:13 +08:00
# include <string.h>
2003-07-24 00:03:10 +08:00
# include <math.h>
2003-01-03 23:17:43 +08:00
# ifndef NETWARE
1999-04-08 05:05:13 +08:00
# include <malloc.h>
# include <memory.h>
# include <winbase.h>
2003-01-03 23:17:43 +08:00
# endif /* NETWARE */
1999-04-08 05:05:13 +08:00
# include "sendmail.h"
1999-04-10 21:32:47 +08:00
# include "php_ini.h"
2009-06-30 19:39:15 +08:00
# include "inet.h"
1999-04-08 05:05:13 +08:00
2002-06-06 01:08:38 +08:00
# if HAVE_PCRE || HAVE_BUNDLED_PCRE
# include "ext/pcre/php_pcre.h"
# endif
2003-07-24 00:03:10 +08:00
# include "ext/standard/php_string.h"
2005-08-08 06:06:29 +08:00
# include "ext/date/php_date.h"
2003-07-24 00:03:10 +08:00
1999-04-08 05:05:13 +08:00
/*enum
{
DO_CONNECT = WM_USER + 1
} ;
*/
2002-05-15 04:40:39 +08:00
/* '*error_message' has to be passed around from php_mail() */
# define SMTP_ERROR_RESPONSE_SPEC "SMTP server response: %s"
/* Convinient way to handle error messages from the SMTP server.
response is ecalloc ( ) d in Ack ( ) itself and efree ( ) d here
because the content is in * error_message now */
# define SMTP_ERROR_RESPONSE(response) { \
2002-07-03 07:44:06 +08:00
if ( response & & error_message ) { \
if ( NULL ! = ( * error_message = ecalloc ( 1 , sizeof ( SMTP_ERROR_RESPONSE_SPEC ) + strlen ( response ) ) ) ) { \
snprintf ( * error_message , sizeof ( SMTP_ERROR_RESPONSE_SPEC ) + strlen ( response ) , SMTP_ERROR_RESPONSE_SPEC , response ) ; \
} \
efree ( response ) ; \
2002-05-15 04:40:39 +08:00
} \
}
2003-07-24 00:03:10 +08:00
# define SMTP_SKIP_SPACE(str) { while (isspace(*str)) { str++; } }
2002-05-15 04:40:39 +08:00
1999-04-08 05:05:13 +08:00
# ifndef THREAD_SAFE
char Buffer [ MAIL_BUFFER_SIZE ] ;
2000-06-17 02:24:02 +08:00
/* socket related data */
1999-04-08 05:05:13 +08:00
SOCKET sc ;
2003-01-03 23:17:43 +08:00
# ifndef NETWARE
1999-04-08 05:05:13 +08:00
WSADATA Data ;
struct hostent * adr ;
int WinsockStarted ;
2000-06-17 02:24:02 +08:00
/* values set by the constructor */
1999-04-08 05:05:13 +08:00
char * AppName ;
2003-01-03 23:17:43 +08:00
# endif /* NETWARE */
2005-07-28 17:44:13 +08:00
SOCKADDR_IN sock_in ;
1999-04-08 05:05:13 +08:00
char MailHost [ HOST_NAME_LEN ] ;
char LocalHost [ HOST_NAME_LEN ] ;
# endif
char seps [ ] = " , \t \n " ;
2003-01-03 23:17:43 +08:00
# ifndef NETWARE
2014-09-20 09:27:40 +08:00
char * php_mailer = " PHP 7 WIN32 " ;
2003-01-03 23:17:43 +08:00
# else
2014-09-20 09:27:40 +08:00
char * php_mailer = " PHP 7 NetWare " ;
2003-01-03 23:17:43 +08:00
# endif /* NETWARE */
1999-04-08 05:05:13 +08:00
2000-06-17 02:24:02 +08:00
/* Error messages */
1999-04-08 05:05:13 +08:00
static char * ErrorMessages [ ] =
{
2002-05-14 21:52:18 +08:00
{ " Success " } , /* 0 */
{ " Bad arguments from form " } , /* 1 */
1999-04-08 05:05:13 +08:00
{ " Unable to open temporary mailfile for read " } ,
{ " Failed to Start Sockets " } ,
{ " Failed to Resolve Host " } ,
2002-05-14 21:52:18 +08:00
{ " Failed to obtain socket handle " } , /* 5 */
{ " Failed to connect to mailserver, verify your \" SMTP \" setting in php.ini " } ,
1999-04-08 05:05:13 +08:00
{ " Failed to Send " } ,
{ " Failed to Receive " } ,
{ " Server Error " } ,
2002-05-14 21:52:18 +08:00
{ " Failed to resolve the host IP name " } , /* 10 */
1999-04-08 05:05:13 +08:00
{ " Out of memory " } ,
{ " Unknown error " } ,
{ " Bad Message Contents " } ,
{ " Bad Message Subject " } ,
2002-05-14 21:52:18 +08:00
{ " Bad Message destination " } , /* 15 */
1999-04-08 05:05:13 +08:00
{ " Bad Message Return Path " } ,
{ " Bad Mail Host " } ,
{ " Bad Message File " } ,
2002-05-15 04:40:39 +08:00
{ " \" sendmail_from \" not set in php.ini or custom \" From: \" header missing " } ,
2002-06-06 01:08:38 +08:00
{ " Mailserver rejected our \" sendmail_from \" setting " } , /* 20 */
{ " Error while trimming mail header with PCRE, please file a bug report at http://bugs.php.net/ " } /* 21 */
1999-04-08 05:05:13 +08:00
} ;
2013-06-11 05:20:18 +08:00
/* This pattern converts all single occurrences of \n (Unix)
* withour a leading \ r to \ r \ n and all occurrences of \ r ( Mac )
2002-06-06 01:08:38 +08:00
* without a trailing \ n to \ r \ n
* Thx to Nibbler from ircnet / # linuxger
*/
# define PHP_WIN32_MAIL_UNIFY_PATTERN " / (\r\n?)|\n / "
# define PHP_WIN32_MAIL_UNIFY_REPLACE "\r\n"
/* This pattern removes \r\n from the start of the string,
* \ r \ n from the end of the string and also makes sure every line
* is only wrapped with a single \ r \ n ( thus reduces multiple
2013-06-11 05:20:18 +08:00
* occurrences of \ r \ n between lines to a single \ r \ n ) */
2002-06-06 01:08:38 +08:00
# define PHP_WIN32_MAIL_RMVDBL_PATTERN " / ^\r\n|(\r\n)+$ / m"
# define PHP_WIN32_MAIL_RMVDBL_REPLACE ""
2003-07-24 00:03:10 +08:00
/* This pattern escapes \n. inside the message body. It prevents
* premature end of message if \ n . \ n or \ r \ n . \ r \ n is encountered
* and ensures that \ n . sequences are properly displayed in the
* message body . */
# define PHP_WIN32_MAIL_DOT_PATTERN "\n."
# define PHP_WIN32_MAIL_DOT_REPLACE "\n.."
2002-06-06 01:08:38 +08:00
/* This function is meant to unify the headers passed to to mail()
2013-06-11 05:20:18 +08:00
* This means , use PCRE to transform single occurrences of \ n or \ r in \ r \ n
* As a second step we also eleminate all \ r \ n occurrences which are :
2002-06-06 01:08:38 +08:00
* 1 ) At the start of the header
* 2 ) At the end of the header
2013-06-11 05:20:18 +08:00
* 3 ) Two or more occurrences in the header are removed so only one is left
2002-06-06 01:08:38 +08:00
*
* Returns NULL on error , or the new char * buffer on success .
* You have to take care and efree ( ) the buffer on your own .
*/
2014-05-13 12:51:11 +08:00
static zend_string * php_win32_mail_trim_header ( char * header TSRMLS_DC )
2002-06-06 01:08:38 +08:00
{
# if HAVE_PCRE || HAVE_BUNDLED_PCRE
2014-05-13 12:51:11 +08:00
zend_string * result , * result2 ;
zval replace ;
zend_string * regex ;
1999-04-08 05:05:13 +08:00
2002-06-06 01:08:38 +08:00
if ( ! header ) {
return NULL ;
}
2014-05-13 12:51:11 +08:00
ZVAL_STRINGL ( & replace , PHP_WIN32_MAIL_UNIFY_REPLACE , strlen ( PHP_WIN32_MAIL_UNIFY_REPLACE ) ) ;
2014-08-26 01:24:55 +08:00
regex = zend_string_init ( PHP_WIN32_MAIL_UNIFY_REPLACE , sizeof ( PHP_WIN32_MAIL_UNIFY_REPLACE ) - 1 , 0 ) ;
2002-06-06 01:08:38 +08:00
2014-05-13 12:51:11 +08:00
//zend_string *php_pcre_replace(zend_string *regex, char *subject, int subject_len, zval *replace_val, int is_callable_replace, int limit, int *replace_count TSRMLS_DC);
result = php_pcre_replace ( regex ,
2014-10-29 02:25:55 +08:00
header , ( int ) strlen ( header ) ,
2014-05-13 12:51:11 +08:00
& replace ,
2002-06-06 01:08:38 +08:00
0 ,
2005-03-12 20:03:50 +08:00
- 1 ,
NULL TSRMLS_CC ) ;
2014-05-13 12:51:11 +08:00
2002-06-06 01:08:38 +08:00
if ( NULL = = result ) {
2014-05-13 12:51:11 +08:00
zval_ptr_dtor ( & replace ) ;
2014-08-26 01:24:55 +08:00
zend_string_free ( regex ) ;
2002-06-06 01:08:38 +08:00
return NULL ;
}
2014-05-13 12:51:11 +08:00
ZVAL_STRING ( & replace , PHP_WIN32_MAIL_RMVDBL_PATTERN ) ;
2014-08-26 01:24:55 +08:00
regex = zend_string_init ( PHP_WIN32_MAIL_RMVDBL_PATTERN , sizeof ( PHP_WIN32_MAIL_RMVDBL_PATTERN ) - 1 , 0 ) ;
2002-06-06 01:08:38 +08:00
2014-05-13 12:51:11 +08:00
result2 = php_pcre_replace ( regex ,
2014-10-29 02:25:55 +08:00
result - > val , ( int ) result - > len ,
2014-05-13 12:51:11 +08:00
& replace ,
0 ,
- 1 ,
NULL TSRMLS_CC ) ;
return result ;
2002-06-06 01:08:38 +08:00
# else
/* In case we don't have PCRE support (for whatever reason...) simply do nothing and return the unmodified header */
return estrdup ( header ) ;
# endif
}
1999-04-08 05:05:13 +08:00
2000-06-17 02:24:02 +08:00
/*********************************************************************
1999-04-08 05:05:13 +08:00
// Name: TSendMail
// Input: 1) host: Name of the mail host where the SMTP server resides
// max accepted length of name = 256
// 2) appname: Name of the application to use in the X-mailer
// field of the message. if NULL is given the application
// name is used as given by the GetCommandLine() function
// max accespted length of name = 100
// Output: 1) error: Returns the error code if something went wrong or
// SUCCESS otherwise.
//
// See SendText() for additional args!
2000-06-17 02:24:02 +08:00
//********************************************************************/
2003-12-09 06:10:42 +08:00
PHPAPI int TSendMail ( char * host , int * error , char * * error_message ,
2002-07-03 06:29:13 +08:00
char * headers , char * Subject , char * mailTo , char * data ,
2005-08-08 06:06:29 +08:00
char * mailCc , char * mailBcc , char * mailRPath TSRMLS_DC )
1999-04-08 05:05:13 +08:00
{
int ret ;
char * RPath = NULL ;
2014-05-13 12:51:11 +08:00
zend_string * headers_lc = NULL ; /* headers_lc is only created if we've a header at all */
2005-01-20 01:38:20 +08:00
char * pos1 = NULL , * pos2 = NULL ;
1999-04-08 05:05:13 +08:00
2003-01-03 23:17:43 +08:00
# ifndef NETWARE
1999-04-24 08:12:00 +08:00
WinsockStarted = FALSE ;
2003-01-03 23:17:43 +08:00
# endif
1999-04-08 05:05:13 +08:00
if ( host = = NULL ) {
* error = BAD_MAIL_HOST ;
2002-05-15 04:40:39 +08:00
return FAILURE ;
1999-04-08 05:05:13 +08:00
} else if ( strlen ( host ) > = HOST_NAME_LEN ) {
* error = BAD_MAIL_HOST ;
2002-05-15 04:40:39 +08:00
return FAILURE ;
1999-04-08 05:05:13 +08:00
} else {
1999-04-24 08:12:00 +08:00
strcpy ( MailHost , host ) ;
1999-04-08 05:05:13 +08:00
}
2002-05-14 23:29:28 +08:00
if ( headers ) {
char * pos = NULL ;
2002-05-18 00:16:27 +08:00
size_t i ;
2014-05-13 12:51:11 +08:00
zend_string * headers_trim ;
2002-06-06 01:08:38 +08:00
/* Use PCRE to trim the header into the right format */
2014-05-13 12:51:11 +08:00
if ( NULL = = ( headers_trim = php_win32_mail_trim_header ( headers TSRMLS_CC ) ) ) {
2002-06-06 01:08:38 +08:00
* error = W32_SM_PCRE_ERROR ;
return FAILURE ;
}
2002-05-18 00:16:27 +08:00
/* Create a lowercased header for all the searches so we're finally case
* insensitive when searching for a pattern . */
2014-08-26 01:24:55 +08:00
if ( NULL = = ( headers_lc = zend_string_copy ( headers_trim ) ) ) {
2002-05-18 00:16:27 +08:00
* error = OUT_OF_MEMORY ;
return FAILURE ;
}
2014-05-13 12:51:11 +08:00
for ( i = 0 ; i < headers_lc - > len ; i + + ) {
headers_lc - > val [ i ] = tolower ( headers_lc - > val [ i ] ) ;
2002-05-18 00:16:27 +08:00
}
2002-05-14 23:29:28 +08:00
}
/* Fall back to sendmail_from php.ini setting */
2002-07-03 06:29:13 +08:00
if ( mailRPath & & * mailRPath ) {
RPath = estrdup ( mailRPath ) ;
2005-01-20 01:38:20 +08:00
} else if ( INI_STR ( " sendmail_from " ) ) {
2002-06-03 06:54:48 +08:00
RPath = estrdup ( INI_STR ( " sendmail_from " ) ) ;
2005-01-20 01:38:20 +08:00
} else if ( headers_lc & &
2014-05-13 12:51:11 +08:00
( pos1 = strstr ( headers_lc - > val , " from: " ) ) & &
( ( pos1 = = headers_lc - > val ) | | ( * ( pos1 - 1 ) = = ' \n ' ) )
2005-01-20 01:38:20 +08:00
) {
/* Real offset is memaddress from the original headers + difference of
* string found in the lowercase headrs + 5 characters to jump over
* the from : */
2014-05-13 12:51:11 +08:00
pos1 = headers + ( pos1 - headers_lc - > val ) + 5 ;
2005-01-20 01:38:20 +08:00
if ( NULL = = ( pos2 = strstr ( pos1 , " \r \n " ) ) ) {
RPath = estrndup ( pos1 , strlen ( pos1 ) ) ;
} else {
2006-01-06 10:04:33 +08:00
RPath = estrndup ( pos1 , pos2 - pos1 ) ;
2005-01-20 01:38:20 +08:00
}
2002-06-03 06:54:48 +08:00
} else {
2014-05-13 12:51:11 +08:00
if ( headers_lc ) {
2014-08-26 01:24:55 +08:00
zend_string_free ( headers_lc ) ;
2002-05-14 23:29:28 +08:00
}
2002-06-03 06:54:48 +08:00
* error = W32_SM_SENDMAIL_FROM_NOT_SET ;
return FAILURE ;
1999-04-08 05:05:13 +08:00
}
2000-06-17 02:24:02 +08:00
/* attempt to connect with mail host */
1999-04-08 05:05:13 +08:00
* error = MailConnect ( ) ;
if ( * error ! = 0 ) {
2002-05-15 04:40:39 +08:00
if ( RPath ) {
efree ( RPath ) ;
}
2002-06-06 01:08:38 +08:00
if ( headers ) {
efree ( headers ) ;
2002-05-18 00:16:27 +08:00
efree ( headers_lc ) ;
}
2002-05-15 18:11:33 +08:00
/* 128 is safe here, the specifier in snprintf isn't longer than that */
2002-05-15 04:40:39 +08:00
if ( NULL = = ( * error_message = ecalloc ( 1 , HOST_NAME_LEN + 128 ) ) ) {
return FAILURE ;
}
2002-06-03 01:13:48 +08:00
snprintf ( * error_message , HOST_NAME_LEN + 128 ,
2002-09-21 23:03:24 +08:00
" Failed to connect to mailserver at \" %s \" port %d, verify your \" SMTP \" "
2002-06-03 01:13:48 +08:00
" and \" smtp_port \" setting in php.ini or use ini_set() " ,
MailHost , ! INI_INT ( " smtp_port " ) ? 25 : INI_INT ( " smtp_port " ) ) ;
2002-05-15 04:40:39 +08:00
return FAILURE ;
1999-04-08 05:05:13 +08:00
} else {
2014-05-13 12:51:11 +08:00
ret = SendText ( RPath , Subject , mailTo , mailCc , mailBcc , data , headers , headers_lc - > val , error_message TSRMLS_CC ) ;
1999-04-08 05:05:13 +08:00
TSMClose ( ) ;
2002-05-15 04:40:39 +08:00
if ( RPath ) {
efree ( RPath ) ;
}
2002-06-06 01:08:38 +08:00
if ( headers ) {
efree ( headers ) ;
2002-05-18 00:16:27 +08:00
efree ( headers_lc ) ;
}
1999-04-08 05:05:13 +08:00
if ( ret ! = SUCCESS ) {
* error = ret ;
2002-05-15 04:40:39 +08:00
return FAILURE ;
1999-04-08 05:05:13 +08:00
}
2002-05-15 04:40:39 +08:00
return SUCCESS ;
1999-04-08 05:05:13 +08:00
}
}
2000-06-17 22:48:03 +08:00
//********************************************************************
1999-04-08 05:05:13 +08:00
// Name: TSendMail::~TSendMail
// Input:
// Output:
// Description: DESTRUCTOR
// Author/Date: jcar 20/9/96
// History:
2000-06-17 02:24:02 +08:00
//********************************************************************/
2003-12-09 06:10:42 +08:00
PHPAPI void TSMClose ( )
1999-04-08 05:05:13 +08:00
{
2000-07-10 22:49:20 +08:00
Post ( " QUIT \r \n " ) ;
2002-05-15 04:40:39 +08:00
Ack ( NULL ) ;
2000-06-17 02:24:02 +08:00
/* to guarantee that the cleanup is not made twice and
compomise the rest of the application if sockets are used
elesewhere
*/
2000-07-28 20:21:44 +08:00
shutdown ( sc , 0 ) ;
closesocket ( sc ) ;
1999-04-08 05:05:13 +08:00
}
2000-06-17 02:24:02 +08:00
/*********************************************************************
1999-04-08 05:05:13 +08:00
// Name: char *GetSMErrorText
// Input: Error index returned by the menber functions
// Output: pointer to a string containing the error description
// Description:
// Author/Date: jcar 20/9/96
// History:
2000-06-17 02:24:02 +08:00
//*******************************************************************/
2003-12-09 06:10:42 +08:00
PHPAPI char * GetSMErrorText ( int index )
1999-04-08 05:05:13 +08:00
{
2002-05-14 21:52:18 +08:00
if ( MIN_ERROR_INDEX < = index & & index < MAX_ERROR_INDEX ) {
1999-04-08 05:05:13 +08:00
return ( ErrorMessages [ index ] ) ;
2002-05-14 23:32:15 +08:00
2002-05-14 21:52:18 +08:00
} else {
return ( ErrorMessages [ UNKNOWN_ERROR ] ) ;
2002-05-14 23:32:15 +08:00
2002-05-14 21:52:18 +08:00
}
1999-04-08 05:05:13 +08:00
}
2014-08-26 19:20:21 +08:00
PHPAPI zend_string * php_str_to_str ( char * haystack , size_t length , char * needle ,
size_t needle_len , char * str , size_t str_len ) ;
2014-08-16 17:16:11 +08:00
1999-04-08 05:05:13 +08:00
2000-06-17 02:24:02 +08:00
/*********************************************************************
2006-01-06 10:04:33 +08:00
// Name: SendText
1999-04-08 05:05:13 +08:00
// Input: 1) RPath: return path of the message
// Is used to fill the "Return-Path" and the
// "X-Sender" fields of the message.
// 2) Subject: Subject field of the message. If NULL is given
// the subject is set to "No Subject"
// 3) mailTo: Destination address
// 4) data: Null terminated string containing the data to be send.
2002-05-18 00:16:27 +08:00
// 5,6) headers of the message. Note that the second
// parameter, headers_lc, is actually a lowercased version of
// headers. The should match exactly (in terms of length),
// only differ in case
1999-04-08 05:05:13 +08:00
// Output: Error code or SUCCESS
// Description:
// Author/Date: jcar 20/9/96
// History:
2000-06-17 02:24:02 +08:00
//*******************************************************************/
2005-08-08 06:06:29 +08:00
static int SendText ( char * RPath , char * Subject , char * mailTo , char * mailCc , char * mailBcc , char * data ,
char * headers , char * headers_lc , char * * error_message TSRMLS_DC )
1999-04-08 05:05:13 +08:00
{
2003-09-09 06:36:59 +08:00
int res ;
1999-04-08 05:05:13 +08:00
char * p ;
2000-07-10 22:49:20 +08:00
char * tempMailTo , * token , * pos1 , * pos2 ;
2002-05-15 04:40:39 +08:00
char * server_response = NULL ;
2002-05-15 18:11:33 +08:00
char * stripped_header = NULL ;
2014-05-13 12:51:11 +08:00
zend_string * data_cln ;
1999-04-08 05:05:13 +08:00
2000-06-17 02:24:02 +08:00
/* check for NULL parameters */
1999-04-08 05:05:13 +08:00
if ( data = = NULL )
return ( BAD_MSG_CONTENTS ) ;
if ( mailTo = = NULL )
return ( BAD_MSG_DESTINATION ) ;
if ( RPath = = NULL )
return ( BAD_MSG_RPATH ) ;
2000-06-17 02:24:02 +08:00
/* simple checks for the mailto address */
/* have ampersand ? */
2002-05-15 04:40:39 +08:00
/* mfischer, 20020514: I commented this out because it really
seems bogus . Only a username for example may still be a
valid address at the destination system .
1999-04-08 05:05:13 +08:00
if ( strchr ( mailTo , ' @ ' ) = = NULL )
return ( BAD_MSG_DESTINATION ) ;
2002-05-15 04:40:39 +08:00
*/
1999-04-08 05:05:13 +08:00
2007-02-24 10:17:47 +08:00
snprintf ( Buffer , sizeof ( Buffer ) , " HELO %s \r \n " , LocalHost ) ;
1999-04-08 05:05:13 +08:00
2013-07-13 20:37:04 +08:00
/* in the beginning of the dialog */
2000-06-17 02:24:02 +08:00
/* attempt reconnect if the first Post fail */
1999-04-24 08:12:00 +08:00
if ( ( res = Post ( Buffer ) ) ! = SUCCESS ) {
1999-04-08 05:05:13 +08:00
MailConnect ( ) ;
2006-01-06 10:04:33 +08:00
if ( ( res = Post ( Buffer ) ) ! = SUCCESS ) {
1999-04-08 05:05:13 +08:00
return ( res ) ;
2006-01-06 10:04:33 +08:00
}
1999-04-08 05:05:13 +08:00
}
2002-05-15 04:40:39 +08:00
if ( ( res = Ack ( & server_response ) ) ! = SUCCESS ) {
SMTP_ERROR_RESPONSE ( server_response ) ;
1999-04-08 05:05:13 +08:00
return ( res ) ;
2002-05-15 04:40:39 +08:00
}
1999-04-08 05:05:13 +08:00
2006-01-06 10:04:33 +08:00
SMTP_SKIP_SPACE ( RPath ) ;
2009-08-19 02:58:33 +08:00
FormatEmailAddress ( Buffer , RPath , " MAIL FROM:<%s> \r \n " ) ;
2006-01-06 10:04:33 +08:00
if ( ( res = Post ( Buffer ) ) ! = SUCCESS ) {
2000-06-28 02:41:44 +08:00
return ( res ) ;
2006-01-06 10:04:33 +08:00
}
2002-05-15 04:40:39 +08:00
if ( ( res = Ack ( & server_response ) ) ! = SUCCESS ) {
SMTP_ERROR_RESPONSE ( server_response ) ;
2002-05-14 21:52:18 +08:00
return W32_SM_SENDMAIL_FROM_MALFORMED ;
2002-05-15 04:40:39 +08:00
}
1999-04-08 05:05:13 +08:00
2000-07-10 22:49:20 +08:00
tempMailTo = estrdup ( mailTo ) ;
/* Send mail to all rcpt's */
token = strtok ( tempMailTo , " , " ) ;
2006-01-06 10:04:33 +08:00
while ( token ! = NULL )
2000-07-10 22:49:20 +08:00
{
2006-01-06 10:04:33 +08:00
SMTP_SKIP_SPACE ( token ) ;
2009-08-19 02:58:33 +08:00
FormatEmailAddress ( Buffer , token , " RCPT TO:<%s> \r \n " ) ;
2002-06-06 01:08:38 +08:00
if ( ( res = Post ( Buffer ) ) ! = SUCCESS ) {
efree ( tempMailTo ) ;
2000-07-10 22:49:20 +08:00
return ( res ) ;
2002-06-06 01:08:38 +08:00
}
2002-05-15 04:40:39 +08:00
if ( ( res = Ack ( & server_response ) ) ! = SUCCESS ) {
SMTP_ERROR_RESPONSE ( server_response ) ;
2002-06-06 01:08:38 +08:00
efree ( tempMailTo ) ;
2000-07-10 22:49:20 +08:00
return ( res ) ;
2002-05-15 04:40:39 +08:00
}
2000-07-10 22:49:20 +08:00
token = strtok ( NULL , " , " ) ;
}
2002-05-15 18:11:33 +08:00
efree ( tempMailTo ) ;
2000-07-10 22:49:20 +08:00
2002-12-01 05:50:17 +08:00
if ( mailCc & & * mailCc ) {
tempMailTo = estrdup ( mailCc ) ;
/* Send mail to all rcpt's */
token = strtok ( tempMailTo , " , " ) ;
2006-01-06 10:04:33 +08:00
while ( token ! = NULL )
2002-12-01 05:50:17 +08:00
{
2006-01-06 10:04:33 +08:00
SMTP_SKIP_SPACE ( token ) ;
2009-08-19 02:58:33 +08:00
FormatEmailAddress ( Buffer , token , " RCPT TO:<%s> \r \n " ) ;
2002-12-01 05:50:17 +08:00
if ( ( res = Post ( Buffer ) ) ! = SUCCESS ) {
efree ( tempMailTo ) ;
return ( res ) ;
}
if ( ( res = Ack ( & server_response ) ) ! = SUCCESS ) {
SMTP_ERROR_RESPONSE ( server_response ) ;
efree ( tempMailTo ) ;
return ( res ) ;
}
token = strtok ( NULL , " , " ) ;
}
efree ( tempMailTo ) ;
}
2000-07-10 22:49:20 +08:00
/* Send mail to all Cc rcpt's */
2005-01-20 02:54:23 +08:00
else if ( headers & & ( pos1 = strstr ( headers_lc , " cc: " ) ) & & ( ( pos1 = = headers_lc ) | | ( * ( pos1 - 1 ) = = ' \n ' ) ) ) {
2002-05-18 00:16:27 +08:00
/* Real offset is memaddress from the original headers + difference of
* string found in the lowercase headrs + 3 characters to jump over
* the cc : */
pos1 = headers + ( pos1 - headers_lc ) + 3 ;
2002-05-14 21:52:18 +08:00
if ( NULL = = ( pos2 = strstr ( pos1 , " \r \n " ) ) ) {
tempMailTo = estrndup ( pos1 , strlen ( pos1 ) ) ;
} else {
2006-01-06 10:04:33 +08:00
tempMailTo = estrndup ( pos1 , pos2 - pos1 ) ;
2002-05-14 21:52:18 +08:00
}
1999-04-08 05:05:13 +08:00
2000-07-10 22:49:20 +08:00
token = strtok ( tempMailTo , " , " ) ;
2006-01-06 10:04:33 +08:00
while ( token ! = NULL )
2000-07-10 22:49:20 +08:00
{
2003-07-24 00:03:10 +08:00
SMTP_SKIP_SPACE ( token ) ;
2009-08-19 02:58:33 +08:00
FormatEmailAddress ( Buffer , token , " RCPT TO:<%s> \r \n " ) ;
2006-01-06 10:04:33 +08:00
if ( ( res = Post ( Buffer ) ) ! = SUCCESS ) {
efree ( tempMailTo ) ;
2000-07-10 22:49:20 +08:00
return ( res ) ;
2006-01-06 10:04:33 +08:00
}
2002-05-15 04:40:39 +08:00
if ( ( res = Ack ( & server_response ) ) ! = SUCCESS ) {
SMTP_ERROR_RESPONSE ( server_response ) ;
2006-01-06 10:04:33 +08:00
efree ( tempMailTo ) ;
2002-07-03 06:29:13 +08:00
return ( res ) ;
}
token = strtok ( NULL , " , " ) ;
}
efree ( tempMailTo ) ;
}
2002-12-01 05:50:17 +08:00
/* Send mail to all Bcc rcpt's
This is basically a rip of the Cc code above .
Just don ' t forget to remove the Bcc : from the header afterwards . */
if ( mailBcc & & * mailBcc ) {
tempMailTo = estrdup ( mailBcc ) ;
2002-07-03 06:29:13 +08:00
/* Send mail to all rcpt's */
token = strtok ( tempMailTo , " , " ) ;
2006-01-06 10:04:33 +08:00
while ( token ! = NULL )
2002-07-03 06:29:13 +08:00
{
2003-07-24 00:03:10 +08:00
SMTP_SKIP_SPACE ( token ) ;
2009-08-19 02:58:33 +08:00
FormatEmailAddress ( Buffer , token , " RCPT TO:<%s> \r \n " ) ;
2002-07-03 06:29:13 +08:00
if ( ( res = Post ( Buffer ) ) ! = SUCCESS ) {
efree ( tempMailTo ) ;
return ( res ) ;
}
if ( ( res = Ack ( & server_response ) ) ! = SUCCESS ) {
SMTP_ERROR_RESPONSE ( server_response ) ;
efree ( tempMailTo ) ;
2000-07-10 22:49:20 +08:00
return ( res ) ;
2002-05-15 04:40:39 +08:00
}
2000-07-10 22:49:20 +08:00
token = strtok ( NULL , " , " ) ;
}
efree ( tempMailTo ) ;
}
2002-12-01 05:50:17 +08:00
else if ( headers ) {
2002-05-18 00:16:27 +08:00
if ( pos1 = strstr ( headers_lc , " bcc: " ) ) {
/* Real offset is memaddress from the original headers + difference of
* string found in the lowercase headrs + 4 characters to jump over
* the bcc : */
pos1 = headers + ( pos1 - headers_lc ) + 4 ;
if ( NULL = = ( pos2 = strstr ( pos1 , " \r \n " ) ) ) {
tempMailTo = estrndup ( pos1 , strlen ( pos1 ) ) ;
/* Later, when we remove the Bcc: out of the
header we know it was the last thing . */
pos2 = pos1 ;
} else {
tempMailTo = estrndup ( pos1 , pos2 - pos1 ) ;
2002-05-15 18:11:33 +08:00
}
2002-05-18 00:16:27 +08:00
token = strtok ( tempMailTo , " , " ) ;
2006-01-06 10:04:33 +08:00
while ( token ! = NULL )
2002-05-18 00:16:27 +08:00
{
2003-07-24 00:03:10 +08:00
SMTP_SKIP_SPACE ( token ) ;
2009-08-19 02:58:33 +08:00
FormatEmailAddress ( Buffer , token , " RCPT TO:<%s> \r \n " ) ;
2002-05-18 00:16:27 +08:00
if ( ( res = Post ( Buffer ) ) ! = SUCCESS ) {
2006-01-06 10:04:33 +08:00
efree ( tempMailTo ) ;
2002-05-18 00:16:27 +08:00
return ( res ) ;
}
if ( ( res = Ack ( & server_response ) ) ! = SUCCESS ) {
SMTP_ERROR_RESPONSE ( server_response ) ;
2006-01-06 10:04:33 +08:00
efree ( tempMailTo ) ;
2002-05-18 00:16:27 +08:00
return ( res ) ;
}
token = strtok ( NULL , " , " ) ;
2002-05-15 18:11:33 +08:00
}
2002-05-18 00:16:27 +08:00
efree ( tempMailTo ) ;
2002-05-15 18:11:33 +08:00
2002-05-18 00:16:27 +08:00
/* Now that we've identified that we've a Bcc list,
remove it from the current header . */
if ( NULL = = ( stripped_header = ecalloc ( 1 , strlen ( headers ) ) ) ) {
return OUT_OF_MEMORY ;
}
/* headers = point to string start of header
pos1 = pointer IN headers where the Bcc starts
' 4 ' = Length of the characters ' bcc : '
Because we ' ve added + 4 above for parsing the Emails
we ' ve to substract them here . */
memcpy ( stripped_header , headers , pos1 - headers - 4 ) ;
if ( pos1 ! = pos2 ) {
/* if pos1 != pos2 , pos2 points to the rest of the headers.
Since pos1 ! = pos2 if " \r \n " was found , we know those characters
are there and so we jump over them ( else we would generate a new header
which would look like " \r \n \r \n " . */
memcpy ( stripped_header + ( pos1 - headers - 4 ) , pos2 + 2 , strlen ( pos2 ) - 2 ) ;
}
2002-12-07 06:56:57 +08:00
}
}
/* Simplify the code that we create a copy of stripped_header no matter if
we actually strip something or not . So we ' ve a single efree ( ) later . */
if ( headers & & ! stripped_header ) {
if ( NULL = = ( stripped_header = estrndup ( headers , strlen ( headers ) ) ) ) {
return OUT_OF_MEMORY ;
2002-05-15 18:11:33 +08:00
}
}
2002-07-03 07:44:06 +08:00
2002-05-15 18:11:33 +08:00
if ( ( res = Post ( " DATA \r \n " ) ) ! = SUCCESS ) {
2003-01-07 19:24:17 +08:00
if ( stripped_header ) {
efree ( stripped_header ) ;
}
1999-04-08 05:05:13 +08:00
return ( res ) ;
2002-05-15 18:11:33 +08:00
}
2002-05-15 04:40:39 +08:00
if ( ( res = Ack ( & server_response ) ) ! = SUCCESS ) {
SMTP_ERROR_RESPONSE ( server_response ) ;
2003-01-07 19:24:17 +08:00
if ( stripped_header ) {
efree ( stripped_header ) ;
}
1999-04-08 05:05:13 +08:00
return ( res ) ;
2002-05-15 04:40:39 +08:00
}
1999-04-08 05:05:13 +08:00
2000-06-17 02:24:02 +08:00
/* send message header */
2002-05-15 18:11:33 +08:00
if ( Subject = = NULL ) {
2005-08-08 06:06:29 +08:00
res = PostHeader ( RPath , " No Subject " , mailTo , stripped_header TSRMLS_CC ) ;
2002-05-15 18:11:33 +08:00
} else {
2005-08-08 06:06:29 +08:00
res = PostHeader ( RPath , Subject , mailTo , stripped_header TSRMLS_CC ) ;
2002-05-15 18:11:33 +08:00
}
2002-05-18 00:16:27 +08:00
if ( stripped_header ) {
efree ( stripped_header ) ;
}
2002-05-15 18:11:33 +08:00
if ( res ! = SUCCESS ) {
1999-04-08 05:05:13 +08:00
return ( res ) ;
2002-05-15 18:11:33 +08:00
}
1999-04-08 05:05:13 +08:00
2003-07-24 00:03:10 +08:00
/* Escape \n. sequences
* We use php_str_to_str ( ) and not php_str_replace_in_subject ( ) , since the latter
* uses ZVAL as it ' s parameters */
data_cln = php_str_to_str ( data , strlen ( data ) , PHP_WIN32_MAIL_DOT_PATTERN , sizeof ( PHP_WIN32_MAIL_DOT_PATTERN ) - 1 ,
2014-05-13 12:51:11 +08:00
PHP_WIN32_MAIL_DOT_REPLACE , sizeof ( PHP_WIN32_MAIL_DOT_REPLACE ) - 1 ) ;
2003-09-09 06:36:59 +08:00
if ( ! data_cln ) {
2014-05-13 12:51:11 +08:00
data_cln = STR_EMPTY_ALLOC ( ) ;
2003-09-09 06:36:59 +08:00
}
2003-07-24 00:03:10 +08:00
2000-06-17 02:24:02 +08:00
/* send message contents in 1024 chunks */
2003-09-09 06:36:59 +08:00
{
2014-05-13 12:51:11 +08:00
char c , * e2 , * e = data_cln - > val + data_cln - > len ;
p = data_cln - > val ;
2003-07-24 00:03:10 +08:00
2003-09-09 06:36:59 +08:00
while ( e - p > 1024 ) {
e2 = p + 1024 ;
c = * e2 ;
* e2 = ' \0 ' ;
if ( ( res = Post ( p ) ) ! = SUCCESS ) {
2014-08-26 01:24:55 +08:00
zend_string_free ( data_cln ) ;
2003-09-09 06:36:59 +08:00
return ( res ) ;
2003-07-24 00:03:10 +08:00
}
2003-09-09 06:36:59 +08:00
* e2 = c ;
p = e2 ;
2003-07-24 00:03:10 +08:00
}
2003-09-09 06:36:59 +08:00
if ( ( res = Post ( p ) ) ! = SUCCESS ) {
2014-08-26 01:24:55 +08:00
zend_string_free ( data_cln ) ;
2003-09-09 06:36:59 +08:00
return ( res ) ;
1999-04-08 05:05:13 +08:00
}
}
2014-08-26 01:24:55 +08:00
zend_string_free ( data_cln ) ;
2003-07-24 00:03:10 +08:00
2000-06-17 02:24:02 +08:00
/*send termination dot */
1999-04-08 05:05:13 +08:00
if ( ( res = Post ( " \r \n . \r \n " ) ) ! = SUCCESS )
return ( res ) ;
2002-05-15 04:40:39 +08:00
if ( ( res = Ack ( & server_response ) ) ! = SUCCESS ) {
SMTP_ERROR_RESPONSE ( server_response ) ;
1999-04-08 05:05:13 +08:00
return ( res ) ;
2002-05-15 04:40:39 +08:00
}
1999-04-08 05:05:13 +08:00
return ( SUCCESS ) ;
}
2005-08-08 06:06:29 +08:00
static int addToHeader ( char * * header_buffer , const char * specifier , char * string )
{
2002-06-03 06:10:25 +08:00
if ( NULL = = ( * header_buffer = erealloc ( * header_buffer , strlen ( * header_buffer ) + strlen ( specifier ) + strlen ( string ) + 1 ) ) ) {
return 0 ;
}
sprintf ( * header_buffer + strlen ( * header_buffer ) , specifier , string ) ;
return 1 ;
}
1999-04-08 05:05:13 +08:00
2000-06-17 02:24:02 +08:00
/*********************************************************************
1999-04-08 05:05:13 +08:00
// Name: PostHeader
// Input: 1) return path
2001-12-05 07:33:52 +08:00
// 2) Subject
// 3) destination address
// 4) headers
1999-04-08 05:05:13 +08:00
// Output: Error code or Success
// Description:
// Author/Date: jcar 20/9/96
// History:
2000-06-17 02:24:02 +08:00
//********************************************************************/
2005-08-08 06:06:29 +08:00
static int PostHeader ( char * RPath , char * Subject , char * mailTo , char * xheaders TSRMLS_DC )
1999-04-08 05:05:13 +08:00
{
2000-06-17 02:24:02 +08:00
/* Print message header according to RFC 822 */
/* Return-path, Received, Date, From, Subject, Sender, To, cc */
1999-04-08 05:05:13 +08:00
2005-08-08 06:06:29 +08:00
int res ;
2002-06-03 06:10:25 +08:00
char * header_buffer ;
2002-05-18 00:16:27 +08:00
char * headers_lc = NULL ;
size_t i ;
if ( xheaders ) {
if ( NULL = = ( headers_lc = estrdup ( xheaders ) ) ) {
return OUT_OF_MEMORY ;
}
for ( i = 0 ; i < strlen ( headers_lc ) ; i + + ) {
headers_lc [ i ] = tolower ( headers_lc [ i ] ) ;
}
}
1999-04-08 05:05:13 +08:00
2007-02-24 10:17:47 +08:00
header_buffer = ecalloc ( 1 , MAIL_BUFFER_SIZE ) ;
1999-04-08 05:05:13 +08:00
2005-08-08 06:06:29 +08:00
if ( ! xheaders | | ! strstr ( headers_lc , " date: " ) ) {
time_t tNow = time ( NULL ) ;
2014-05-13 12:51:11 +08:00
zend_string * dt = php_format_date ( " r " , 1 , tNow , 1 TSRMLS_CC ) ;
2005-08-08 06:06:29 +08:00
2014-05-13 12:51:11 +08:00
snprintf ( header_buffer , MAIL_BUFFER_SIZE , " Date: %s \r \n " , dt - > val ) ;
2014-08-26 01:24:55 +08:00
zend_string_free ( dt ) ;
1999-06-10 17:10:07 +08:00
}
2002-06-03 06:10:25 +08:00
if ( ! headers_lc | | ! strstr ( headers_lc , " from: " ) ) {
if ( ! addToHeader ( & header_buffer , " From: %s \r \n " , RPath ) ) {
goto PostHeader_outofmem ;
}
}
if ( ! addToHeader ( & header_buffer , " Subject: %s \r \n " , Subject ) ) {
goto PostHeader_outofmem ;
}
2002-06-03 07:39:59 +08:00
/* Only add the To: field from the $to parameter if isn't in the custom headers */
if ( ( headers_lc & & ( ! strstr ( headers_lc , " \r \n to: " ) & & ( strncmp ( headers_lc , " to: " , 3 ) ! = 0 ) ) ) | | ! headers_lc ) {
if ( ! addToHeader ( & header_buffer , " To: %s \r \n " , mailTo ) ) {
goto PostHeader_outofmem ;
}
1999-04-08 05:05:13 +08:00
}
2006-01-06 10:04:33 +08:00
if ( xheaders ) {
2002-07-03 07:44:06 +08:00
if ( ! addToHeader ( & header_buffer , " %s \r \n " , xheaders ) ) {
2002-06-03 06:10:25 +08:00
goto PostHeader_outofmem ;
}
1999-04-08 05:05:13 +08:00
}
2002-06-03 22:39:30 +08:00
if ( headers_lc ) {
efree ( headers_lc ) ;
}
2002-06-03 06:10:25 +08:00
if ( ( res = Post ( header_buffer ) ) ! = SUCCESS ) {
efree ( header_buffer ) ;
1999-04-08 05:05:13 +08:00
return ( res ) ;
2002-05-18 00:16:27 +08:00
}
2002-06-03 06:10:25 +08:00
efree ( header_buffer ) ;
1999-04-08 05:05:13 +08:00
2002-05-18 00:16:27 +08:00
if ( ( res = Post ( " \r \n " ) ) ! = SUCCESS ) {
1999-04-08 05:05:13 +08:00
return ( res ) ;
2002-05-18 00:16:27 +08:00
}
1999-04-08 05:05:13 +08:00
return ( SUCCESS ) ;
2002-06-03 06:10:25 +08:00
PostHeader_outofmem :
2002-06-03 22:39:30 +08:00
if ( headers_lc ) {
efree ( headers_lc ) ;
}
2002-06-03 06:10:25 +08:00
return OUT_OF_MEMORY ;
1999-04-08 05:05:13 +08:00
}
2000-06-17 02:24:02 +08:00
/*********************************************************************
1999-04-08 05:05:13 +08:00
// Name: MailConnect
// Input: None
// Output: None
// Description: Connect to the mail host and receive the welcome message.
// Author/Date: jcar 20/9/96
// History:
2000-06-17 02:24:02 +08:00
//********************************************************************/
2005-08-08 06:06:29 +08:00
static int MailConnect ( )
1999-04-08 05:05:13 +08:00
{
2009-06-30 19:39:15 +08:00
int res , namelen ;
2000-08-07 05:42:10 +08:00
short portnum ;
2009-06-30 19:39:15 +08:00
struct hostent * ent ;
IN_ADDR addr ;
# ifdef HAVE_IPV6
IN6_ADDR addr6 ;
# endif
1999-04-08 05:05:13 +08:00
2000-06-17 02:24:02 +08:00
/* Create Socket */
2009-06-30 19:39:15 +08:00
if ( ( sc = socket ( PF_INET , SOCK_STREAM , 0 ) ) = = INVALID_SOCKET ) {
1999-04-08 05:05:13 +08:00
return ( FAILED_TO_OBTAIN_SOCKET_HANDLE ) ;
2009-06-30 19:39:15 +08:00
}
1999-04-08 05:05:13 +08:00
2000-06-17 02:24:02 +08:00
/* Get our own host name */
2009-06-30 19:39:15 +08:00
if ( gethostname ( LocalHost , HOST_NAME_LEN ) ) {
return ( FAILED_TO_GET_HOSTNAME ) ;
}
ent = gethostbyname ( LocalHost ) ;
if ( ! ent ) {
1999-04-08 05:05:13 +08:00
return ( FAILED_TO_GET_HOSTNAME ) ;
2009-06-30 19:39:15 +08:00
}
2014-10-29 02:25:55 +08:00
namelen = ( int ) strlen ( ent - > h_name ) ;
2009-06-30 19:39:15 +08:00
# ifdef HAVE_IPV6
if ( inet_pton ( AF_INET , ent - > h_name , & addr ) = = 1 | | inet_pton ( AF_INET6 , ent - > h_name , & addr6 ) = = 1 )
# else
if ( inet_pton ( AF_INET , ent - > h_name , & addr ) = = 1 )
# endif
{
if ( namelen + 2 > = HOST_NAME_LEN ) {
return ( FAILED_TO_GET_HOSTNAME ) ;
}
strcpy ( LocalHost , " [ " ) ;
strcpy ( LocalHost + 1 , ent - > h_name ) ;
strcpy ( LocalHost + namelen + 1 , " ] " ) ;
} else {
if ( namelen > = HOST_NAME_LEN ) {
return ( FAILED_TO_GET_HOSTNAME ) ;
}
strcpy ( LocalHost , ent - > h_name ) ;
}
1999-04-08 05:05:13 +08:00
2000-06-17 02:24:02 +08:00
/* Resolve the servers IP */
/*
if ( ! isdigit ( MailHost [ 0 ] ) | | ! gethostbyname ( MailHost ) )
{
return ( FAILED_TO_RESOLVE_HOST ) ;
}
2006-01-06 10:04:33 +08:00
*/
1999-04-08 05:05:13 +08:00
2002-06-03 01:13:48 +08:00
portnum = ( short ) INI_INT ( " smtp_port " ) ;
2000-08-07 05:38:41 +08:00
if ( ! portnum ) {
2000-08-07 01:49:41 +08:00
portnum = 25 ;
2000-08-07 05:38:41 +08:00
}
2000-08-07 01:49:41 +08:00
2000-06-17 02:24:02 +08:00
/* Connect to server */
1999-04-24 08:12:00 +08:00
sock_in . sin_family = AF_INET ;
2000-08-07 01:49:41 +08:00
sock_in . sin_port = htons ( portnum ) ;
1999-04-24 08:12:00 +08:00
sock_in . sin_addr . S_un . S_addr = GetAddr ( MailHost ) ;
1999-04-08 05:05:13 +08:00
2009-06-30 19:39:15 +08:00
if ( connect ( sc , ( LPSOCKADDR ) & sock_in , sizeof ( sock_in ) ) ) {
1999-04-08 05:05:13 +08:00
return ( FAILED_TO_CONNECT ) ;
2009-06-30 19:39:15 +08:00
}
1999-04-08 05:05:13 +08:00
2000-06-17 02:24:02 +08:00
/* receive Server welcome message */
2002-05-15 04:40:39 +08:00
res = Ack ( NULL ) ;
1999-04-08 05:05:13 +08:00
return ( res ) ;
}
2000-06-17 02:24:02 +08:00
/*********************************************************************
1999-04-08 05:05:13 +08:00
// Name: Post
// Input:
// Output:
// Description:
// Author/Date: jcar 20/9/96
// History:
2000-06-17 02:24:02 +08:00
//********************************************************************/
2005-08-08 06:06:29 +08:00
static int Post ( LPCSTR msg )
1999-04-08 05:05:13 +08:00
{
2014-10-29 02:25:55 +08:00
int len = ( int ) strlen ( msg ) ;
1999-04-08 05:05:13 +08:00
int slen ;
int index = 0 ;
while ( len > 0 ) {
1999-04-24 08:12:00 +08:00
if ( ( slen = send ( sc , msg + index , len , 0 ) ) < 1 )
1999-04-08 05:05:13 +08:00
return ( FAILED_TO_SEND ) ;
len - = slen ;
index + = slen ;
}
return ( SUCCESS ) ;
}
2000-06-17 02:24:02 +08:00
/*********************************************************************
1999-04-08 05:05:13 +08:00
// Name: Ack
// Input:
// Output:
// Description:
// Get the response from the server. We only want to know if the
// last command was successful.
// Author/Date: jcar 20/9/96
// History:
2000-06-17 02:24:02 +08:00
//********************************************************************/
2005-08-08 06:06:29 +08:00
static int Ack ( char * * server_response )
1999-04-08 05:05:13 +08:00
{
2002-05-15 04:40:39 +08:00
static char buf [ MAIL_BUFFER_SIZE ] ;
1999-04-08 05:05:13 +08:00
int rlen ;
int Index = 0 ;
int Received = 0 ;
2006-01-06 10:04:33 +08:00
again :
1999-04-08 05:05:13 +08:00
2006-01-06 10:04:33 +08:00
if ( ( rlen = recv ( sc , buf + Index , ( ( MAIL_BUFFER_SIZE ) - 1 ) - Received , 0 ) ) < 1 ) {
1999-04-08 05:05:13 +08:00
return ( FAILED_TO_RECEIVE ) ;
2006-01-06 10:04:33 +08:00
}
1999-04-08 05:05:13 +08:00
Received + = rlen ;
buf [ Received ] = 0 ;
2000-06-17 02:24:02 +08:00
/*err_msg fprintf(stderr,"Received: (%d bytes) %s", rlen, buf + Index); */
1999-04-08 05:05:13 +08:00
2000-06-17 02:24:02 +08:00
/* Check for newline */
1999-04-08 05:05:13 +08:00
Index + = rlen ;
2000-09-05 08:26:15 +08:00
2003-08-12 02:03:24 +08:00
/* SMPT RFC says \r\n is the only valid line ending, who are we to argue ;)
* The response code must contain at least 5 characters ex . 220 \ r \ n */
if ( Received < 5 | | buf [ Received - 1 ] ! = ' \n ' | | buf [ Received - 2 ] ! = ' \r ' ) {
goto again ;
}
1999-04-08 05:05:13 +08:00
2002-05-15 04:40:39 +08:00
if ( buf [ 0 ] > ' 3 ' ) {
2002-06-03 00:25:06 +08:00
/* If we've a valid pointer, return the SMTP server response so the error message contains more information */
2002-05-15 04:40:39 +08:00
if ( server_response ) {
int dec = 0 ;
/* See if we have something like \r, \n, \r\n or \n\r at the end of the message and chop it off */
if ( Received > 2 ) {
if ( buf [ Received - 1 ] = = ' \n ' | | buf [ Received - 1 ] = = ' \r ' ) {
dec + + ;
if ( buf [ Received - 2 ] = = ' \r ' | | buf [ Received - 2 ] = = ' \n ' ) {
dec + + ;
}
}
}
* server_response = estrndup ( buf , Received - dec ) ;
}
1999-04-08 05:05:13 +08:00
return ( SMTP_SERVER_ERROR ) ;
2002-05-15 04:40:39 +08:00
}
1999-04-08 05:05:13 +08:00
return ( SUCCESS ) ;
}
2000-06-17 02:24:02 +08:00
/*********************************************************************
1999-04-08 05:05:13 +08:00
// Name: unsigned long GetAddr (LPSTR szHost)
// Input:
// Output:
// Description: Given a string, it will return an IP address.
// - first it tries to convert the string directly
// - if that fails, it tries o resolve it as a hostname
//
// WARNING: gethostbyname() is a blocking function
// Author/Date: jcar 20/9/96
// History:
2000-06-17 02:24:02 +08:00
//********************************************************************/
2005-08-08 06:06:29 +08:00
static unsigned long GetAddr ( LPSTR szHost )
1999-04-08 05:05:13 +08:00
{
LPHOSTENT lpstHost ;
u_long lAddr = INADDR_ANY ;
/* check that we have a string */
if ( * szHost ) {
/* check for a dotted-IP address string */
lAddr = inet_addr ( szHost ) ;
/* If not an address, then try to resolve it as a hostname */
if ( ( lAddr = = INADDR_NONE ) & & ( strcmp ( szHost , " 255.255.255.255 " ) ) ) {
lpstHost = gethostbyname ( szHost ) ;
if ( lpstHost ) { /* success */
lAddr = * ( ( u_long FAR * ) ( lpstHost - > h_addr ) ) ;
} else {
lAddr = INADDR_ANY ; /* failure */
}
}
}
return ( lAddr ) ;
2006-01-06 10:04:33 +08:00
} /* end GetAddr() */
2009-08-19 02:58:33 +08:00
/*********************************************************************
// Name: int FormatEmailAddress
// Input:
// Output:
// Description: Formats the email address to remove any content ouside
// of the angle brackets < > as per RFC 2821.
//
// Returns the invalidly formatted mail address if the < > are
// unbalanced (the SMTP server should reject it if it's out of spec.)
//
// Author/Date: garretts 08/18/2009
// History:
//********************************************************************/
2009-08-27 05:59:54 +08:00
static int FormatEmailAddress ( char * Buf , char * EmailAddress , char * FormatString ) {
2009-08-19 02:58:33 +08:00
char * tmpAddress1 , * tmpAddress2 ;
int result ;
if ( ( tmpAddress1 = strchr ( EmailAddress , ' < ' ) ) & & ( tmpAddress2 = strchr ( tmpAddress1 , ' > ' ) ) ) {
* tmpAddress2 = 0 ; // terminate the string temporarily.
2009-08-25 20:47:28 +08:00
result = snprintf ( Buf , MAIL_BUFFER_SIZE , FormatString , tmpAddress1 + 1 ) ;
2009-08-19 02:58:33 +08:00
* tmpAddress2 = ' > ' ; // put it back the way it was.
return result ;
}
2009-08-25 20:47:28 +08:00
return snprintf ( Buf , MAIL_BUFFER_SIZE , FormatString , EmailAddress ) ;
2009-08-19 02:58:33 +08:00
} /* end FormatEmailAddress() */