commit 1cddd59c4ed2341f87cf58d9b67d45c82ffd99d0
Author: Warren Baker <warren@decoy.co.za>
Date:   Mon Sep 16 15:13:29 2013 +0200

    Split SSL/TLS into separate checkboxes so that plaintext connections can be made secured by using STARTTLS. Support for SMTPS connections should probably be done away with in future. Fixes #3180

diff --git a/etc/inc/notices.inc b/etc/inc/notices.inc
index ff45054361..c7ae7db788 100644
--- a/etc/inc/notices.inc
+++ b/etc/inc/notices.inc
@@ -310,6 +310,7 @@ function send_smtp_message($message, $subject = "(no subject)") {
 
 	$smtp->direct_delivery = 0;
 	$smtp->ssl = ($config['notifications']['smtp']['ssl'] == "checked") ? 1 : 0;
+	$smtp->tls = ($config['notifications']['smtp']['tls'] == "checked") ? 1 : 0;
 	$smtp->debug = 0;
 	$smtp->html_debug = 0;
 	$smtp->localhost=$config['system']['hostname'].".".$config['system']['domain'];
diff --git a/etc/inc/smtp.inc b/etc/inc/smtp.inc
index d884c867bd..ec8a7c9d5a 100644
--- a/etc/inc/smtp.inc
+++ b/etc/inc/smtp.inc
@@ -20,6 +20,7 @@ class smtp_class
 	var $host_name="";
 	var $host_port=25;
 	var $ssl=0;
+	var $tls=0;
 	var $localhost="";
 	var $timeout=0;
 	var $data_timeout=0;
@@ -213,7 +214,7 @@ class smtp_class
 
 	Function ConnectToHost($domain, $port, $resolve_message)
 	{
-		if($this->ssl)
+		if($this->ssl || $this->tls)
 		{
 			$version=explode(".",function_exists("phpversion") ? phpversion() : "3.0.7");
 			$php_version=intval($version[0])*1000000+intval($version[1])*1000+intval($version[2]);
@@ -461,62 +462,20 @@ class smtp_class
 			socket_set_timeout($this->connection,$timeout,0);
 		if($this->debug)
 			$this->OutputDebug(sprintf(gettext("Connected to SMTP server \"%s\"."), $domain));
-		if(!strcmp($localhost=$this->localhost,"")
-		&& !strcmp($localhost=getenv("SERVER_NAME"),"")
-		&& !strcmp($localhost=getenv("HOST"),"")
-		&& !strcmp($localhost=getenv("HOSTNAME"),"")
-		&& !strcmp($localhost=exec("/bin/hostname"),""))
-			$localhost="localhost";
-		$success=0;
 		if($this->VerifyResultLines("220",$responses)>0)
 		{
-			$fallback=1;
-			if($this->esmtp
-			|| strlen($this->user))
-			{
-				if($this->PutLine("EHLO $localhost"))
-				{
-					if(($success_code=$this->VerifyResultLines("250",$responses))>0)
-					{
-						$this->esmtp_host=$this->Tokenize($responses[0]," ");
-						for($response=1;$response<count($responses);$response++)
-						{
-							$extension=strtoupper($this->Tokenize($responses[$response]," "));
-							$this->esmtp_extensions[$extension]=$this->Tokenize("");
-						}
-						$success=1;
-						$fallback=0;
-					}
-					else
-					{
-						if($success_code==0)
-						{
-							$code=$this->Tokenize($this->error," -");
-							switch($code)
-							{
-								case "421":
-									$fallback=0;
-									break;
-							}
-						}
-					}
-				}
-				else
-					$fallback=0;
-			}
-			if($fallback)
-			{
-				if($this->PutLine("HELO $localhost")
-				&& $this->VerifyResultLines("250",$responses)>0)
-					$success=1;
-			}
+			// Send our HELLO
+			$success = $this->hello($this->hostname());
+			if ($this->tls)
+				$success = $this->startTLS();
+
 			if($success
 			&& strlen($this->user)
 			&& strlen($this->pop3_auth_host)==0)
 			{
 				if(!IsSet($this->esmtp_extensions["AUTH"]))
 				{
-					$this->error=gettext("server does not require authentication");
+					$this->error = gettext("server does not require authentication");
 					$success=0;
 				}
 				else
@@ -599,6 +558,64 @@ class smtp_class
 		return($success);
 	}
 
+	Function hostname() {
+		if(!strcmp($localhost=$this->localhost,"")
+		&& !strcmp($localhost=getenv("SERVER_NAME"),"")
+		&& !strcmp($localhost=getenv("HOST"),"")
+		&& !strcmp($localhost=getenv("HOSTNAME"),"")
+		&& !strcmp($localhost=exec("/bin/hostname"),""))
+			$localhost="localhost";
+
+		return $localhost;
+	}
+
+	Function hello()
+	{
+		$success = 0;
+		$fallback = 1;
+		if ($this->esmtp || strlen($this->user)) {
+			if ($this->PutLine("EHLO ".$this->hostname())) {
+				if (($success_code = $this->VerifyResultLines("250",$responses)) > 0) {
+					$this->esmtp_host = $this->Tokenize($responses[0]," ");
+					for($response=1;$response<count($responses);$response++) {
+						$extension = strtoupper($this->Tokenize($responses[$response]," "));
+						$this->esmtp_extensions[$extension]=$this->Tokenize("");
+					}
+					$success = 1;
+					$fallback = 0;
+				} else {
+					if ($success_code == 0) {
+						$code = $this->Tokenize($this->error," -");
+						switch($code) {
+							case "421":
+								$fallback=0;
+								break;
+						}
+					}
+				}
+			} else
+				$fallback=0;
+		}
+
+		if ($fallback) {
+			if ($this->PutLine("HELO $localhost") && $this->VerifyResultLines("250",$responses)>0)
+				$success=1;
+		}
+		return $success;
+	}
+
+	Function startTLS() {
+		if ($this->PutLine("STARTTLS") && $this->VerifyResultLines("220",$responses)>0) {
+			if (!stream_socket_enable_crypto($this->connection,true,STREAM_CRYPTO_METHOD_TLS_CLIENT)) {
+				return false;
+			} else {
+				// Resend HELO since session has been reset
+				return $this->hello($this->hostname);
+			}
+		} else
+			return false;
+	}
+
 	Function MailFrom($sender)
 	{
 		if($this->direct_delivery)
diff --git a/usr/local/www/system_advanced_notifications.php b/usr/local/www/system_advanced_notifications.php
index 48de7fd4d6..3b6d311157 100644
--- a/usr/local/www/system_advanced_notifications.php
+++ b/usr/local/www/system_advanced_notifications.php
@@ -66,6 +66,8 @@ if($config['notifications']['smtp']['port'])
 	$pconfig['smtpport'] = $config['notifications']['smtp']['port'];
 if($config['notifications']['smtp']['ssl'])
 	$pconfig['smtpssl'] = $config['notifications']['smtp']['ssl'];
+if($config['notifications']['smtp']['tls'])
+	$pconfig['smtptls'] = $config['notifications']['smtp']['tls'];
 if($config['notifications']['smtp']['notifyemailaddress']) 
 	$pconfig['smtpnotifyemailaddress'] = $config['notifications']['smtp']['notifyemailaddress'];
 if($config['notifications']['smtp']['username']) 
@@ -113,6 +115,7 @@ if ($_POST) {
 		$config['notifications']['smtp']['ipaddress'] = $_POST['smtpipaddress'];
 		$config['notifications']['smtp']['port'] = $_POST['smtpport'];
 		$config['notifications']['smtp']['ssl'] = isset($_POST['smtpssl']) ? 'checked' : 'unchecked';
+		$config['notifications']['smtp']['tls'] = isset($_POST['smtptls']) ? (isset($_POST['smtpssl']) ? 'unchecked' : 'checked') : 'unchecked';
 		$config['notifications']['smtp']['notifyemailaddress'] = $_POST['smtpnotifyemailaddress'];
 		$config['notifications']['smtp']['username'] = $_POST['smtpusername'];
 		$config['notifications']['smtp']['password'] = $_POST['smtppassword'];
@@ -258,9 +261,15 @@ include("head.inc");
 						<tr>
 							<td width="22%" valign="top" class="vncell"><?=gettext("SMTP Port of E-Mail server"); ?></td>
 							<td width="78%" class="vtable">
-								<input name='smtpport' value='<?php echo $pconfig['smtpport']; ?>' />
-								<input type='checkbox' name='smtpssl' <?php echo $pconfig['smtpssl']; ?> />Enable SSL/TLS Authentication<br/>
-								<?=gettext("This is the port of the SMTP E-Mail server, typically 25, 587 (submission) or 465 (smtps, tick ssl/tls checkbox)"); ?>
+								<input name='smtpport' value='<?php echo $pconfig['smtpport']; ?>' /><br/>
+								<?=gettext("This is the port of the SMTP E-Mail server, typically 25, 587 (submission) or 465 (smtps)"); ?>
+							</td>
+						</tr>
+						<tr>
+							<td width="22%" valign="top" class="vncell"><?=gettext("Secure SMTP Connection"); ?></td>
+							<td width="78%" class="vtable">
+								<input type='checkbox' id='smtpssl' name='smtpssl' <?php echo $pconfig['smtpssl']; ?> />Enable SMTP over SSL/TLS<br/>
+								<input type='checkbox' id='smtptls' name='smtptls' <?php echo $pconfig['smtptls']; ?> />Enable STARTTLS<br/>
 							</td>
 						</tr>
 						<tr>
@@ -333,6 +342,21 @@ include("head.inc");
 			</td>
 		</tr>
 	</table>
+<script type="text/javascript">
+	jQuery(document).ready(function() {
+		if (jQuery('#smtpssl').is(':checked')) {
+			jQuery('#smtptls').prop('disabled', true);
+		} else if  (jQuery('#smtptls').is(':checked')) {
+			jQuery('#smtpssl').prop('disabled', true);
+		}
+	});
+	jQuery('#smtpssl').change( function() {
+		jQuery('#smtptls').prop('disabled', this.checked);
+	});
+	jQuery('#smtptls').change( function() {
+		jQuery('#smtpssl').prop('disabled', this.checked);
+	});
+</script>
 <?php include("fend.inc"); ?>
 </body>
 </html>
