Forums / Install & configuration / Is SSL supported for SMTP?

Is SSL supported for SMTP?

Author Message

Greg McAvoy-Jensen

Tuesday 30 October 2007 11:10:12 pm

Is there a way to specify SSL communication if one's SMTP server requires an encrypted connection? Thanks!

Granite Horizon, Certified Developer of eZ Publish Web Solutions
Provider of the SaaS Solution Granite Horizon In The Cloud | http://granitehorizon.com/cloud
http://granitehorizon.com | +1 916 647 6350 | California USA | @granitegreg
Blog: http://granitehorizon.com/blog

Mauricio Sánchez

Friday 14 November 2008 2:26:02 pm

I made some tweaks on the smtp class to add support for SSL SMTP connection

Here is the new code for lib/ezutils/classes/ezsmtp.php


<?php
/***************************************
** Filename.......: class.smtp.inc
** Project........: SMTP Class
** Version........: 1.0.5
** Last Modified..: 21 December 2001
***************************************/

    class smtp
    {
        const STATUS_NOT_CONNECTED = 1;
        const STATUS_CONNECTED = 2;
        const CRLF = "\r\n";

        public $authenticated;
        public $connection;
        public $recipients;
        public $CcRecipients;
        public $BccRecipients;
        public $headers;
        public $timeout;
        public $errors;
        public $status;
        public $body;
        public $from;
        public $host;
        public $port;
        public $helo;
        public $auth;
        public $user;
        public $pass;

        /***************************************
        ** Constructor function. Arguments:
        ** $params - An assoc array of parameters:
        **
        **   host    - The hostname of the smtp server        Default: localhost
        **   port    - The port the smtp server runs on        Default: 25
        **   helo    - What to send as the HELO command        Default: localhost
        **             (typically the hostname of the
        **             machine this script runs on)
        **   auth    - Whether to use basic authentication    Default: FALSE
        **   user    - Username for authentication            Default: <blank>
        **   pass    - Password for authentication            Default: <blank>
        **   timeout - The timeout in seconds for the call    Default: 5
        **             to fsockopen()
        ***************************************/

        function smtp( $params = array() )
        {
            $this->authenticated = FALSE;
            $this->timeout       = 5;
            $this->status        = smtp::STATUS_NOT_CONNECTED;
            $this->host          = 'localhost';
            $this->port          = 25;
            $this->helo          = 'localhost';
            $this->auth          = FALSE;
            $this->user          = '';
            $this->pass          = '';
            $this->errors        = array();

            foreach ( $params as $key => $value )
            {
                $this->$key = $value;
            }
        }

        /***************************************
        ** Connect function.
        ** It will connect to the server and send
        ** the HELO command.
        ***************************************/

        function connect($params = array())
        {
            $this->connection = fsockopen( $this->host, $this->port, $errno, $errstr, $this->timeout );
            if ( function_exists( 'socket_set_timeout' ) )
            {
                @socket_set_timeout( $this->connection, 5, 0 );
            }

            $greeting = $this->get_data();
            if ( is_resource( $this->connection ) )
            {
                $result = $this->auth ? $this->ehlo() : $this->helo();
                if ( $result )
                {
                    $this->status = smtp::STATUS_CONNECTED;
                }
                return $result;
            }
            else
            {
                $this->errors[] = 'Failed to connect to server: ' . $errstr;
                return FALSE;
            }
        }

        /***************************************
        ** Function which handles sending the mail.
        ** Arguments:
        ** $params    - Optional assoc array of parameters.
        **            Can contain:
        **              recipients - Indexed array of recipients
        **              from       - The from address. (used in MAIL FROM:),
        **                           this will be the return path
        **              headers    - Indexed array of headers, one header per array entry
        **              body       - The body of the email
        **            It can also contain any of the parameters from the connect()
        **            function
        ***************************************/

        function send( $params = array() )
        {
            foreach ( $params as $key => $value )
            {
                $this->set( $key, $value );
            }

            if ( $this->is_connected() )
            {
                // Do we auth or not? Note the distinction between the auth variable and auth() function
                if ( $this->auth AND !$this->authenticated )
                {
                    if ( !$this->auth() )
                        return FALSE;
                }
                $this->mail( $this->from );
                if ( is_array( $this->recipients ) )
                    foreach ( $this->recipients as $value )
                        $this->rcpt( $value );
                else
                    $this->rcpt( $this->recipients );

                if ( is_array( $this->CcRecipients ) )
                    foreach( $this->CcRecipients as $value )
                        $this->rcpt( $value );
                else
                    $this->rcpt( $this->CcRecipients );

                if ( is_array( $this->BccRecipients ) )
                    foreach ( $this->BccRecipients as $value )
                        $this->rcpt( $value );
                else
                    $this->rcpt( $this->BccRecipients );

                if ( !$this->data() )
                    return FALSE;

                // Transparency
                $headers = str_replace( smtp::CRLF.'.', smtp::CRLF.'..', trim( implode( smtp::CRLF, $this->headers ) ) );
                $body    = str_replace( smtp::CRLF.'.', smtp::CRLF.'..', $this->body );
                $body    = $body[0] == '.' ? '.'.$body : $body;


		// Modify by Mauricio Sánchez - Aplyca Tecnología (24-07-08) 
		//Dealing with SMTP line length limitation (Avoid truncated mails)
                $body = wordwrap($body, 76, "\r\n");
                //End Modify                

                $this->send_data( $headers );
                $this->send_data( '' );
                $this->send_data( $body );
                $this->send_data( '.' );

                $result = ( substr( trim( $this->get_data() ), 0, 3) === '250' );
                return $result;
            }
            else
            {
                $this->errors[] = 'Not connected!';
                return FALSE;
            }
        }

        /***************************************
        ** Function to implement HELO cmd
        ***************************************/

        function helo()
        {
            return( $this->send_cmd( 'HELO ' . $this->helo, '250' ) );
        }


        /***************************************
        ** Function to implement EHLO cmd
        ***************************************/

        function ehlo()
        {
            /* return the result of the EHLO command */
            return ( $this->send_cmd( 'EHLO ' . $this->helo, '250' ) );
        }

        /***************************************
        ** Function to implement RSET cmd
        ***************************************/

        function rset()
        {
            /* return the result of the RSET command */
            return ( $this->send_cmd( 'RSET', '250' ) );
        }

        /***************************************
        ** Function to implement QUIT cmd
        ***************************************/

        function quit()
        {
            /* if QUIT OK */
            if ( $this->send_cmd( 'QUIT', '221' ) )
            {
                /* unset the connection flag and return TRUE */
                $this->status = smtp::STATUS_NOT_CONNECTED;
                return TRUE;
            }
            /* in other case return FALSE */
            return FALSE;
        }

        /***************************************
        ** Function to implement AUTH cmd
        ***************************************/

        function auth()
        {
            /* if the connection is made */
			// Modify by Mauricio Sánchez - Aplyca Tecnología (24-07-08) 
			//Add SMTP secure (SSL) support
			if ( $this->send_cmd( 'STARTTLS', '220' ) )
			{
			    if(!stream_socket_enable_crypto($this->connection, true, STREAM_CRYPTO_METHOD_TLS_CLIENT)) 
				{
					return false;
				}
			//End Modify
	            if ( $this->send_cmd('AUTH LOGIN', '334' ) )
	            {
	                /* if sending username ok */
	                if ( $this->send_cmd( base64_encode( $this->user ), '334' ) )
	                {
	                    /* if sending password ok */
	                    if ( $this->send_cmd( base64_encode( $this->pass ), '235' ) )
	                    {
	                        /* set the authenticated  flag and return TRUE */
	                        $this->authenticated = TRUE;
	                         return TRUE;
	                    }
	                }
	            }
			// Modify by Mauricio Sánchez - Aplyca Tecnología (24-07-08)
			//Add SMTP secure (SSL) support	
			}	
			//End Modify
            /* in other case return FALSE */
            return FALSE;
        }

        /***************************************
        ** Function that handles the MAIL FROM: cmd
        ***************************************/

        function mail( $from )
        {
            /* normalize the from field */
            if ( !preg_match( "/<.+>/", $from ) )
                $from = '<' . $from .'>';

            /* return the result of the MAIL FROM command */
            return ( $this->send_cmd('MAIL FROM:' . $from . '', '250' ) );
        }

        /***************************************
        ** Function that handles the RCPT TO: cmd
        ***************************************/

        function rcpt( $to )
        {
            /* normalize the to field */
            if ( !preg_match( "/<.+>/", $to ) )
                $to = '<' . $to .'>';

            /* return the result of the RCPT TO command */
            return ( $this->send_cmd( 'RCPT TO:' . $to . '', '250' ) );
        }


        /***************************************
        ** Function that sends the DATA cmd
        ***************************************/

        function data()
        {
            /* return the result of the RCPT TO command */
            return ( $this->send_cmd('DATA', '354' ) );
        }

        /***************************************
        ** Function to determine if this object
        ** is connected to the server or not.
        ***************************************/

        function is_connected()
        {
            return ( is_resource( $this->connection ) AND ( $this->status === smtp::STATUS_CONNECTED ) );
        }

        /***************************************
        ** Function to send a bit of data
        ***************************************/

        function send_data( $data )
        {
            if ( is_resource( $this->connection ) )
            {
                return fwrite( $this->connection, $data.smtp::CRLF, strlen( $data ) + 2 );
            }
            else
                return FALSE;
        }

        /***************************************
        ** Function to get data.
        ***************************************/

        function get_data()
        {
            $return = '';
            $line   = '';
            $loops  = 0;

            if ( is_resource( $this->connection ) )
            {
                while ( ( strpos( $return, smtp::CRLF ) === FALSE OR substr( $line, 3, 1 ) !== ' ' ) AND $loops < 100 )
                {
                    $line    = fgets( $this->connection, 512 );
                    $return .= $line;
                    $loops++;
                }
                return $return;
            }
            else
                return FALSE;
        }

        /***************************************
        ** Sets a variable
        ***************************************/

        function set( $var, $value )
        {
            $this->$var = $value;
            return TRUE;
        }

        /********************************************************
        ** Function to simply send a command to the smtp socket
        *********************************************************/
        function send_cmd( $msg, $answer )
        {
            /* if the connection is made */
            if ( $error = is_resource( $this->connection ) )
            {
                /* if sending DATA ok */
                if ( $error = $this->send_data( $msg ) )
                {
                    /* Wait for server answer */
                    $error = $this->get_data();

                    /* return TRUE if the server answered the expected tag */
                    if( substr( trim( $error ), 0, 3 ) === $answer )
                    {
                        return TRUE;
                    }
                }
            }
            /* else return FALSE and set an error */
            $this->errors[] = $msg . ' command failed, output: ' . $error;
            return FALSE;
        }

    } // End of class
?>



Heath

Sunday 16 November 2008 4:08:15 pm

Wow, it looks like you spent some time preparing that code for use with eZ Publish!

You could consider submitting a patch / feature request through the official channels specifically through the mailing list to have your fix included in eZ Publish.

<i>http://ez.no/ezpublish/contributing#bugfixing
http://ez.no/ezpublish/contributing
http://ez.no/developer/developer_information</i>

This process has succeeded in getting new features in eZ Publish for others,
http://www.google.com/search?q=site%3Ahttp%3A%2F%2Flists.ez.no%2Fpipermail%2Fsdk-public%2F+Brookins+Consulting

Cheers,
Heath

Brookins Consulting | http://brookinsconsulting.com/
Certified | http://auth.ez.no/certification/verify/380350
Solutions | http://projects.ez.no/users/community/brookins_consulting
eZpedia community documentation project | http://ezpedia.org

Piotrek Karaś

Sunday 07 December 2008 12:14:56 am

Also, if you need that for custom extensions rather than entire eZ Publish installation, consider Mail Component:
http://ezcomponents.org/docs/tutorials/Mail

--
Company: mediaSELF Sp. z o.o., http://www.mediaself.pl
eZ references: http://ez.no/partners/worldwide_partners/mediaself
eZ certified developer: http://ez.no/certification/verify/272585
eZ blog: http://ez.ryba.eu

Stijn van Esveld

Monday 26 October 2009 1:25:53 pm

Sorry to kick this old topic, but I'm trying to use GMail as SMTP server. I've copied Sanchez code to ezsmtp.php but i can't get the email notification system to work.

In site.ini.append.php i've put the following settings:

[MailSettings]
Transport=smtp
TransportServer=smtp.gmail.com
TransportPort=465
TransportUser=********@gmail.com
TransportPassword=*******
AdminEmail=********@gmail.com
EmailSender=********@gmail.com

I'm getting the following error in the logs:
Unable to connect to SMTP server smtp.gmail.com

I'm running ezpublish version 4.1.1. Is there anyone who got gmail to work with ezpublish or can help with the right settings?

Teru H.

Friday 04 December 2009 7:14:06 pm

http://ez.no/jp/developer/forum/install_configuration/sending_mail_via_gmail_or_google_apps_smtp may help. i haven't tried for gmail but tried for my email account on a rental server.

i haven't succeeded yet, and wonder if there are simpler ways. looking at ezcomponents, for example, it looks like ssl is already supported...

eZ debug

Timing: Jan 18 2025 03:07:42
Script start
Timing: Jan 18 2025 03:07:42
Module start 'content'
Timing: Jan 18 2025 03:07:43
Module end 'content'
Timing: Jan 18 2025 03:07:43
Script end

Main resources:

Total runtime0.7293 sec
Peak memory usage4,096.0000 KB
Database Queries211

Timing points:

CheckpointStart (sec)Duration (sec)Memory at start (KB)Memory used (KB)
Script start 0.00000.0053 589.5078180.8281
Module start 'content' 0.00530.6302 770.3359780.9375
Module end 'content' 0.63540.0938 1,551.2734352.4609
Script end 0.7292  1,903.7344 

Time accumulators:

 Accumulator Duration (sec) Duration (%) Count Average (sec)
Ini load
Load cache0.00350.4787210.0002
Check MTime0.00130.1776210.0001
Mysql Total
Database connection0.00060.080310.0006
Mysqli_queries0.661790.74132110.0031
Looping result0.00180.25282090.0000
Template Total0.710097.420.3550
Template load0.00160.225520.0008
Template processing0.708397.127920.3542
Template load and register function0.00010.013210.0001
states
state_id_array0.00090.127810.0009
state_identifier_array0.00070.099020.0004
Override
Cache load0.00140.1970410.0000
Sytem overhead
Fetch class attribute can translate value0.00090.121670.0001
Fetch class attribute name0.00100.138390.0001
XML
Image XML parsing0.00200.276170.0003
class_abstraction
Instantiating content class attribute0.00000.001990.0000
General
dbfile0.00310.4200430.0001
String conversion0.00000.000630.0000
Note: percentages do not add up to 100% because some accumulators overlap

CSS/JS files loaded with "ezjscPacker" during request:

CacheTypePacklevelSourceFiles
CSS0extension/community/design/community/stylesheets/ext/jquery.autocomplete.css
extension/community_design/design/suncana/stylesheets/scrollbars.css
extension/community_design/design/suncana/stylesheets/tabs.css
extension/community_design/design/suncana/stylesheets/roadmap.css
extension/community_design/design/suncana/stylesheets/content.css
extension/community_design/design/suncana/stylesheets/star-rating.css
extension/community_design/design/suncana/stylesheets/syntax_and_custom_tags.css
extension/community_design/design/suncana/stylesheets/buttons.css
extension/community_design/design/suncana/stylesheets/tweetbox.css
extension/community_design/design/suncana/stylesheets/jquery.fancybox-1.3.4.css
extension/bcsmoothgallery/design/standard/stylesheets/magnific-popup.css
extension/sevenx/design/simple/stylesheets/star_rating.css
extension/sevenx/design/simple/stylesheets/libs/fontawesome/css/all.min.css
extension/sevenx/design/simple/stylesheets/main.v02.css
extension/sevenx/design/simple/stylesheets/main.v02.res.css
JS0extension/ezjscore/design/standard/lib/yui/3.17.2/build/yui/yui-min.js
extension/ezjscore/design/standard/javascript/jquery-3.7.0.min.js
extension/community_design/design/suncana/javascript/jquery.ui.core.min.js
extension/community_design/design/suncana/javascript/jquery.ui.widget.min.js
extension/community_design/design/suncana/javascript/jquery.easing.1.3.js
extension/community_design/design/suncana/javascript/jquery.ui.tabs.js
extension/community_design/design/suncana/javascript/jquery.hoverIntent.min.js
extension/community_design/design/suncana/javascript/jquery.popmenu.js
extension/community_design/design/suncana/javascript/jScrollPane.js
extension/community_design/design/suncana/javascript/jquery.mousewheel.js
extension/community_design/design/suncana/javascript/jquery.cycle.all.js
extension/sevenx/design/simple/javascript/jquery.scrollTo.js
extension/community_design/design/suncana/javascript/jquery.cookie.js
extension/community_design/design/suncana/javascript/ezstarrating_jquery.js
extension/community_design/design/suncana/javascript/jquery.initboxes.js
extension/community_design/design/suncana/javascript/app.js
extension/community_design/design/suncana/javascript/twitterwidget.js
extension/community_design/design/suncana/javascript/community.js
extension/community_design/design/suncana/javascript/roadmap.js
extension/community_design/design/suncana/javascript/ez.js
extension/community_design/design/suncana/javascript/ezshareevents.js
extension/sevenx/design/simple/javascript/main.js

Templates used to render the page:

UsageRequested templateTemplateTemplate loadedEditOverride
1node/view/full.tplfull/forum_topic.tplextension/sevenx/design/simple/override/templates/full/forum_topic.tplEdit templateOverride template
3content/datatype/view/ezimage.tpl<No override>extension/sevenx/design/simple/templates/content/datatype/view/ezimage.tplEdit templateOverride template
6content/datatype/view/ezxmltext.tpl<No override>extension/community_design/design/suncana/templates/content/datatype/view/ezxmltext.tplEdit templateOverride template
11content/datatype/view/ezxmltags/paragraph.tpl<No override>extension/ezwebin/design/ezwebin/templates/content/datatype/view/ezxmltags/paragraph.tplEdit templateOverride template
1content/datatype/view/ezxmltags/literal.tpl<No override>extension/community/design/standard/templates/content/datatype/view/ezxmltags/literal.tplEdit templateOverride template
6content/datatype/view/ezxmltags/line.tpl<No override>design/standard/templates/content/datatype/view/ezxmltags/line.tplEdit templateOverride template
1pagelayout.tpl<No override>extension/sevenx/design/simple/templates/pagelayout.tplEdit templateOverride template
 Number of times templates used: 29
 Number of unique templates used: 7

Time used to render debug report: 0.0001 secs