Saturday, January 13, 2007 12:26:11
C:\Ezpublish\ezpublish-3.8.6\lib\ezutils\classes\ezsmtp.phpC:\Ezpublish\ezpublish39\lib\ezutils\classes\ezsmtp.php
11<?php
22/***************************************
33** Filename.......: class.smtp.inc
44** Project........: SMTP Class
55** Version........: 1.0.5
66** Last Modified..: 21 December 2001
77***************************************/
88 
99    define('SMTP_STATUS_NOT_CONNECTED', 1, TRUE);
1010    define('SMTP_STATUS_CONNECTED', 2, TRUE);
1111 
12    class smtp{12    class smtp
 13    {
1314 
1415        var $authenticated;
1516        var $connection;
1617        var $recipients;
1718        var $CcRecipients;
1819        var $BccRecipients;
1920        var $headers;
2021        var $timeout;
2122        var $errors;
2223        var $status;
2324        var $body;
2425        var $from;
2526        var $host;
2627        var $port;
2728        var $helo;
2829        var $auth;
2930        var $user;
3031        var $pass;
3132 
3233        /***************************************
3334        ** Constructor function. Arguments:
3435        ** $params - An assoc array of parameters:
3536        **
3637        ** host - The hostname of the smtp server Default: localhost
3738        ** port - The port the smtp server runs on Default: 25
3839        ** helo - What to send as the HELO command Default: localhost
3940        ** (typically the hostname of the
4041        ** machine this script runs on)
4142        ** auth - Whether to use basic authentication Default: FALSE
4243        ** user - Username for authentication Default: <blank>
4344        ** pass - Password for authentication Default: <blank>
4445        ** timeout - The timeout in seconds for the call Default: 5
4546        ** to fsockopen()
4647        ***************************************/
4748 
48        function smtp($params = array()){49        function smtp( $params = array() )
49 50        {
5051            if(!defined('CRLF'))
5152                define('CRLF', "\r\n", TRUE);
5253 
5354            $this->authenticated = FALSE;
5455            $this->timeout = 5;
5556            $this->status = SMTP_STATUS_NOT_CONNECTED;
5657            $this->host = 'localhost';
5758            $this->port = 25;
5859            $this->helo = 'localhost';
5960            $this->auth = FALSE;
6061            $this->user = '';
6162            $this->pass = '';
6263            $this->errors = array();
6364 
64            foreach($params as $key => $value){65            foreach ( $params as $key => $value )
 66            {
6567                $this->$key = $value;
6668            }
6769        }
6870 
6971        /***************************************
7072        ** Connect function. This will, when called
7173        ** statically, create a new smtp object,
7274        ** call the connect function (ie this function)
7375        ** and return it. When not called statically,
7476        ** it will connect to the server and send
7577        ** the HELO command.
7678        ***************************************/
7779 
78        function connect($params = array()){80        function connect($params = array())
79 81        {
80            if(!isset($this->status)){82            if ( !isset( $this->status ) )
 83            {
8184                $obj = new smtp($params);
82                if($obj->connect()){85                if( $obj->connect() )
 86                {
8387                    $obj->status = SMTP_STATUS_CONNECTED;
8488                }
85  
8689                return $obj;
87 90            }
88            }else{91            else
 92            {
8993                $this->connection = fsockopen($this->host, $this->port, $errno, $errstr, $this->timeout);
90                if(function_exists('socket_set_timeout')){94                if ( function_exists( 'socket_set_timeout' ) )
 95                {
9196                    @socket_set_timeout($this->connection, 5, 0);
9297                }
9398 
9499                $greeting = $this->get_data();
95                if(is_resource($this->connection)){100                if ( is_resource( $this->connection ) )
 101                {
96102                    return $this->auth ? $this->ehlo() : $this->helo();
97                }else{103                }
 104                else
 105                {
98106                    $this->errors[] = 'Failed to connect to server: '.$errstr;
99107                    return FALSE;
100108                }
101109            }
102110        }
103111 
104112        /***************************************
105113        ** Function which handles sending the mail.
106114        ** Arguments:
107115        ** $params - Optional assoc array of parameters.
108116        ** Can contain:
109117        ** recipients - Indexed array of recipients
110118        ** from - The from address. (used in MAIL FROM:),
111119        ** this will be the return path
112120        ** headers - Indexed array of headers, one header per array entry
113121        ** body - The body of the email
114122        ** It can also contain any of the parameters from the connect()
115123        ** function
116124        ***************************************/
117125 
118        function send($params = array()){126        function send( $params = array() )
119 127        {
120            foreach($params as $key => $value){128            foreach ( $params as $key => $value )
 129            {
121130                $this->set($key, $value);
122131            }
123132 
124            if($this->is_connected()){133            if ( $this->is_connected() )
125 134            {
126135                // Do we auth or not? Note the distinction between the auth variable and auth() function
127                if($this->auth AND !$this->authenticated){136                if ( $this->auth AND !$this->authenticated )
 137                {
128138                    if(!$this->auth())
129139                        return FALSE;
130140                }
131141                $this->mail($this->from);
132142                if(is_array($this->recipients))
133143                    foreach($this->recipients as $value)
134144                        $this->rcpt($value);
135145                else
136146                    $this->rcpt($this->recipients);
137147 
138148                if(is_array($this->CcRecipients))
139149                    foreach($this->CcRecipients as $value)
140150                        $this->rcpt($value);
141151                else
142152                    $this->rcpt($this->CcRecipients);
143153 
144154                if(is_array($this->BccRecipients))
145155                    foreach($this->BccRecipients as $value)
146156                        $this->rcpt($value);
147157                else
148158                    $this->rcpt($this->BccRecipients);
149159 
150160                if(!$this->data())
151161                    return FALSE;
152162 
153163                // Transparency
154164                $headers = str_replace(CRLF.'.', CRLF.'..', trim(implode(CRLF, $this->headers)));
155165                $body = str_replace(CRLF.'.', CRLF.'..', $this->body);
156166                $body = $body[0] == '.' ? '.'.$body : $body;
157167 
158168                $this->send_data($headers);
159169                $this->send_data('');
160170                $this->send_data($body);
161171                $this->send_data('.');
162172 
163173                $result = (substr(trim($this->get_data()), 0, 3) === '250');
164                //$this->rset(); 
165174                return $result;
166            }else{175            }
 176            else
 177            {
167178                $this->errors[] = 'Not connected!';
168179                return FALSE;
169180            }
170181        }
171182 
172183        /***************************************
173184        ** Function to implement HELO cmd
174185        ***************************************/
175186 
176        function helo(){187        function helo()
 188        {
 189            $error = $this->get_data();
177            if(is_resource($this->connection)190            if ( is_resource( $this->connection ) and
178                    AND $this->send_data('HELO '.$this->helo)191                 $this->send_data( 'HELO ' . $this->helo ) and
179                    AND substr(trim($error = $this->get_data()), 0, 3) === '250' ){192                 substr( trim( $error ), 0, 3 ) === '250' )
180 193            {
181194                return TRUE;
182 195            }
183            }else{196            else
 197            {
184198                $this->errors[] = 'HELO command failed, output: ' . trim(substr(trim($error),3));
185199                return FALSE;
186200            }
187201        }
188202 
189203        /***************************************
190204        ** Function to implement EHLO cmd
191205        ***************************************/
192206 
193        function ehlo(){207        function ehlo()
 208        {
 209            $error = $this->get_data();
194            if(is_resource($this->connection)210            if ( is_resource( $this->connection ) and
195                    AND $this->send_data('EHLO '.$this->helo)211                 $this->send_data( 'EHLO ' . $this->helo ) and
196                    AND substr(trim($error = $this->get_data()), 0, 3) === '250' ){212                 substr( trim( ), 0, 3 ) === '250' )
197 213            {
198214                return TRUE;
199 215            }
200            }else{216            else
 217            {
201218                $this->errors[] = 'EHLO command failed, output: ' . trim(substr(trim($error),3));
202219                return FALSE;
203220            }
204221        }
205222 
206223        /***************************************
207224        ** Function to implement RSET cmd
208225        ***************************************/
209226 
210        function rset(){227        function rset()
 228        {
 229            $error = $this->get_data();
211            if(is_resource($this->connection)230            if ( is_resource( $this->connection ) and
212                    AND $this->send_data('RSET')231                 $this->send_data( 'RSET' ) and
213                    AND substr(trim($error = $this->get_data()), 0, 3) === '250' ){232                 substr( trim( $error ), 0, 3 ) === '250' )
214 233            {
215234                return TRUE;
216 235            }
217            }else{236            else
 237            {
218238                $this->errors[] = 'RSET command failed, output: ' . trim(substr(trim($error),3));
219239                return FALSE;
220240            }
221241        }
222242 
223243        /***************************************
224244        ** Function to implement QUIT cmd
225245        ***************************************/
226246 
227        function quit(){247        function quit()
 248        {
 249            $error = $this->get_data();
228            if(is_resource($this->connection)250            if ( is_resource( $this->connection ) and
229                    AND $this->send_data('QUIT')251                 $this->send_data( 'QUIT' ) and
230                    AND substr(trim($error = $this->get_data()), 0, 3) === '221' ){252                 substr( trim( $error ), 0, 3 ) === '221' )
231 253            {
232254                fclose($this->connection);
233255                $this->status = SMTP_STATUS_NOT_CONNECTED;
234256                return TRUE;
235 257            }
236            }else{258            else
 259            {
237260                $this->errors[] = 'QUIT command failed, output: ' . trim(substr(trim($error),3));
238261                return FALSE;
239262            }
240263        }
241264 
242265        /***************************************
243266        ** Function to implement AUTH cmd
244267        ***************************************/
245268 
246        function auth(){269        function auth()
247            if(is_resource($this->connection)270        {
248                    AND $this->send_data('AUTH LOGIN')271            $error = $this->get_data();
249                    AND substr(trim($error = $this->get_data()), 0, 3) === '334'272            if ( is_resource( $this->connection ) and
250                    AND $this->send_data(base64_encode($this->user)) // Send username273                 $this->send_data( 'AUTH LOGIN' ) and
251                    AND substr(trim($error = $this->get_data()),0,3) === '334'274                 substr( trim( $error ), 0, 3) === '334' and
252                    AND $this->send_data(base64_encode($this->pass))  // Send password275                 $this->send_data( base64_encode( $this->user ) ) and // Send username
253                    AND substr(trim($error = $this->get_data()),0,3) === '235' ){276                 substr( trim( $error ), 0, 3 ) === '334' and
254 277                 $this->send_data( base64_encode( $this->pass ) ) and // Send password
 278                 substr( trim( $error ), 0, 3 ) === '235' )
 279            {
255280                $this->authenticated = TRUE;
256281                return TRUE;
257 282            }
258            }else{283            else
 284            {
259285                $this->errors[] = 'AUTH command failed: ' . trim(substr(trim($error),3));
260286                return FALSE;
261287            }
262288        }
263289 
264290        /***************************************
265291        ** Function that handles the MAIL FROM: cmd
266292        ***************************************/
267293 
268294        function mail($from)
269295        {
270296            if ( !preg_match( "/<.+>/", $from ) )
271297                $from = '<' . $from .'>';
272            if($this->is_connected()298            if ( $this->is_connected() and
273                AND $this->send_data('MAIL FROM:'.$from.'')299                 $this->send_data( 'MAIL FROM:' . $from . '' ) and
274                AND substr(trim($this->get_data()), 0, 3) === '250' )300                 substr( trim( $this->get_data() ), 0, 3 ) === '250' )
275301            {
276302                return TRUE;
277 303            }
278            }else304            else
279305            {
280306                return FALSE;
281307            }
282308        }
283309 
284310        /***************************************
285311        ** Function that handles the RCPT TO: cmd
286312        ***************************************/
287313 
288314        function rcpt($to)
289315        {
290316            if ( !preg_match( "/<.+>/", $to ) )
291317                $to = '<' . $to .'>';
 318 
 319            $error = $this->get_data();
292            if($this->is_connected()320            if ( $this->is_connected() and
293                AND $this->send_data('RCPT TO:'.$to.'' )321                 $this->send_data( 'RCPT TO:' . $to . '' ) and
294                AND substr(trim($error = $this->get_data()), 0, 3) === '250' )322                 substr( trim( $error ), 0, 3 ) === '250' )
295323            {
296324                return TRUE;
297 325            }
298            }else326            else
299327            {
300328                $this->errors[] = trim(substr(trim($error), 3 ) );
301329                return FALSE;
302330            }
303331        }
304332 
305333        /***************************************
306334        ** Function that sends the DATA cmd
307335        ***************************************/
308336 
309        function data(){337        function data()
310 338        {
 339            $error = $this->get_data();
311            if($this->is_connected()340            if( $this->is_connected() and
312                AND $this->send_data('DATA')341                $this->send_data( 'DATA' ) and
313                AND substr(trim($error = $this->get_data()), 0, 3) === '354' ){342                substr( trim( $error ), 0, 3 ) === '354' )
 343            {
314344                return TRUE;
315 345            }
316            }else{346            else
 347            {
317348                $this->errors[] = trim(substr(trim($error), 3));
318349                return FALSE;
319350            }
320351        }
321352 
322353        /***************************************
323354        ** Function to determine if this object
324355        ** is connected to the server or not.
325356        ***************************************/
326357 
327        function is_connected(){358        function is_connected()
328 359        {
329360            return (is_resource($this->connection) AND ($this->status === SMTP_STATUS_CONNECTED));
330361        }
331362 
332363        /***************************************
333364        ** Function to send a bit of data
334365        ***************************************/
335366 
336        function send_data($data){367        function send_data( $data )
 368        {
337            if(is_resource($this->connection)){369            if ( is_resource( $this->connection ) )
 370            {
338371                return fwrite($this->connection, $data.CRLF, strlen($data)+2);
339 372            }
340            }else373            else
341374                return FALSE;
342375        }
343376 
344377        /***************************************
345378        ** Function to get data.
346379        ***************************************/
347380 
348        function &get_data(){381        function get_data()
349 382        {
350383            $return = '';
351384            $line = '';
352385            $loops = 0;
353386 
354            if(is_resource($this->connection)){387            if ( is_resource( $this->connection ) )
 388            {
355                while((strpos($return, CRLF) === FALSE OR substr($line,3,1) !== ' ') AND $loops < 100){389                while ( ( strpos( $return, CRLF ) === FALSE OR substr( $line, 3, 1 ) !== ' ' ) AND $loops < 100 )
 390                {
356391                    $line = fgets($this->connection, 512);
357392                    $return .= $line;
358393                    $loops++;
359394                }
360395                return $return;
361 396            }
362            }else397            else
363398                return FALSE;
364399        }
365400 
366401        /***************************************
367402        ** Sets a variable
368403        ***************************************/
369404 
370        function set($var, $value){405        function set( $var, $value )
371 406        {
372407            $this->$var = $value;
373408            return TRUE;
374409        }
375410 
376411    } // End of class
377412?>
378413