Skip to content

Commit d7b3f6a

Browse files
SMTP: STARTTLS failed (code: 220, response: 2.0.0 Ready to start TLS) (#74)
* SMTP: STARTTLS failed (code: 220, response: 2.0.0 Ready to start TLS) #68 * SMTP: STARTTLS failed (code: 220, response: 2.0.0 Ready to start TLS) #68 * SMTP: STARTTLS failed (code: 220, response: 2.0.0 Ready to start TLS) #68 Issue with non-blocking streams on establishing STARTTLS encryption * SMTP: STARTTLS failed (code: 220, response: 2.0.0 Ready to start TLS) #68 Beware of infinite loop * SMTP: STARTTLS failed (code: 220, response: 2.0.0 Ready to start TLS) #68 do it in a for loop * SMTP: STARTTLS failed (code: 220, response: 2.0.0 Ready to start TLS) #68 more details in STARTTLS failed errormessage * SMTP: STARTTLS failed (code: 220, response: 2.0.0 Ready to start TLS) #68 keep backwards-compatibility to PHP5.4 by creating a method for array_filter parameter <mode> change detailied error-message from combining string to sprintf() function change usleep timing according to attempts adding error_handler on every attempt * SMTP: STARTTLS failed (code: 220, response: 2.0.0 Ready to start TLS) #68 changed new method name * Update Net/SMTP.php Co-authored-by: Jon Parise <jon@indelible.org> * Update Net/SMTP.php Co-authored-by: Jon Parise <jon@indelible.org> * Update Net/SMTP.php --------- Co-authored-by: Jon Parise <jon@indelible.org>
1 parent cfd963d commit d7b3f6a

File tree

1 file changed

+85
-10
lines changed

1 file changed

+85
-10
lines changed

Net/SMTP.php

+85-10
Original file line numberDiff line numberDiff line change
@@ -426,7 +426,7 @@ public function command($command, $valid)
426426
*/
427427
public function getResponse()
428428
{
429-
return array($this->code, join("\n", $this->arguments));
429+
return array($this->code, implode("\n", $this->arguments));
430430
}
431431

432432
/**
@@ -623,23 +623,77 @@ public function starttls()
623623
/* STREAM_CRYPTO_METHOD_TLS_ANY_CLIENT constant does not exist
624624
* and STREAM_CRYPTO_METHOD_SSLv23_CLIENT constant is
625625
* inconsistent across PHP versions. */
626-
$crypto_method = STREAM_CRYPTO_METHOD_TLS_CLIENT
627-
| @STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT
628-
| @STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT;
626+
$crypto_method = STREAM_CRYPTO_METHOD_TLS_CLIENT;
627+
628+
if (defined('STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT')) {
629+
$crypto_method |= @STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT;
630+
}
631+
632+
if (defined('STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT')) {
633+
$crypto_method |= @STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT;
634+
}
635+
636+
if (defined('STREAM_CRYPTO_METHOD_TLSv1_3_CLIENT')) {
637+
$crypto_method |= @STREAM_CRYPTO_METHOD_TLSv1_3_CLIENT;
638+
}
629639
}
630-
if (PEAR::isError($result = $this->socket->enableCrypto(true, $crypto_method))) {
631-
return $result;
632-
} elseif ($result !== true) {
633-
return PEAR::raiseError('STARTTLS failed');
640+
641+
for ($attempts = 1; $attempts < 15; $attempts++) {
642+
if(PEAR::isError(
643+
$result = $this->socket->enableCrypto(
644+
true, $crypto_method)
645+
)
646+
) {
647+
return $result;
648+
}
649+
if ($this->socket->isBlocking() !== true) {
650+
usleep($attempts);
651+
}
652+
if ($result !== 0) {
653+
break;
654+
}
634655
}
635-
656+
657+
if ($result !== true) {
658+
$last_error = error_get_last();
659+
$crypto_types_arr = $this->getDefinedConstantsKeyFilter(
660+
'STREAM_CRYPTO_METHOD_'
661+
);
662+
$error_types_arr = $this->getDefinedConstantsKeyFilter(
663+
'E_'
664+
);
665+
666+
$resultErrorString = "STARTTLS failed ";
667+
//{enableCrypto: false;
668+
$resultErrorString .= "{enableCrypto: %s; ";
669+
//crypto_method: STREAM_CRYPTO_METHOD_TLS_CLIENT (3);
670+
$resultErrorString .= "crypto_method: %s (%s); ";
671+
//attempts: 1;
672+
$resultErrorString .= "attempts: %d; ";
673+
//E_ERROR (1): ErrorMessage}
674+
$resultErrorString .= "%s (%s): %s}";
675+
676+
return PEAR::raiseError(
677+
sprintf(
678+
$resultErrorString,
679+
var_export($result, true),
680+
array_search($crypto_method, $crypto_types_arr),
681+
var_export($crypto_method, true),
682+
$attempts,
683+
array_search($last_error['type'], $error_types_arr),
684+
$last_error['type'],
685+
$last_error['message']
686+
)
687+
);
688+
}
689+
636690
/* Send EHLO again to recieve the AUTH string from the
637691
* SMTP server. */
638692
$this->negotiate();
639693
} else {
640694
return false;
641695
}
642-
696+
643697
return true;
644698
}
645699

@@ -1475,4 +1529,25 @@ public function identifySender()
14751529
{
14761530
return true;
14771531
}
1532+
1533+
/**
1534+
* Backwards-compatibility method.
1535+
* array_filter alternative in PHP5.4 for using
1536+
* key filter because array_filter mode parameter
1537+
* is only available since PHP5.6.
1538+
*
1539+
* @param string $filter The string to filter
1540+
* @return array Filtered constants array.
1541+
*/
1542+
private function getDefinedConstantsKeyFilter($filter) {
1543+
$constants_filtered = array();
1544+
$filter_length = strlen($filter);
1545+
$constants = get_defined_constants();
1546+
foreach ($constants as $key=>$value){
1547+
if (substr($key, 0, $filter_length) == $filter) {
1548+
$constants_filtered[$key] = $value;
1549+
}
1550+
}
1551+
return $constants_filtered;
1552+
}
14781553
}

0 commit comments

Comments
 (0)