I have been working on a class in PHP to send out mail and I decided to use the Zend framework. This class sends out mail using a user's SMTP configuration. As of right now I am checking a user's SMTP configuration by using the supplied user credentials, and sending out a "dummy" email to a "dummy" email address, and catching the ZendException
class that may be thrown on error. This is a horrible method, because of many reasons:
The following is an example of what I am doing right now to test if a SMTP configuration is valid:
public function validSMTP () {
// Get the user's SMTP configuration
$config = $this->getConfiguration ();
// Create a new Zend transport SMTP object
$transport = new Zend_Mail_Transport_Smtp ( $config ["hostname"], [
"auth" => "login",
"ssl" => $config ["protocol"],
"port" => $config ["port"],
"username" => $config ["from"],
"password" => $config ["password"]
]);
// Create a new message and send it to dummy email
$mail = new Zend_Mail ("UTF-8");
$mail->setBodyText ( "null" );
$mail->setFrom ( $config ["from"] );
$mail->addTo ( "dev@null.com" );
$mail->setSubject ( "Test" );
// Attempt to send the email
try {
// Send the email out
$mail->send ( $transport );
// If all is well, return true
return true;
}
// Catch all Zend exceptions
catch ( Zend_Exception $exception ) {
// Invalid configuration
return false;
}
}
So my question is: Is there a better way of doing this? Does Zend_Mail have a built in feature like this? I have looked all over and couldn't find anything build-in into Zend_Mail. Thank you in advance to whoever answers!
I decided to check manually, I will post the end result below so it may help someone in the future. Thanks to @Barmar for helping me search through the documentation and coming to the result that the Zend_Mail framework doesn't support such a feature. The below methods only work for SSL unfortunately since TLS involves encrypting after the EHLO command (and much more). If the configuration is valid, then it returns true, otherwise it returns the reason it is invalid in string form.
public function validSMTP () {
// Initialize client configuration, for this example
$config = [
"hostname" => "smtp.gmail.com",
"port" => 465,
"protocol" => "ssl",
"username" => "USERNAME",
"password" => "PASSWORD",
];
// Add the connection url based on protocol
$config ["url"] = $config ["protocol"] . "://" . $config ["hostname"];
// Open a new socket connection to the SMTP mail server
if ( !( $socket = fsockopen ( $config ["url"], $config ["port"], $en, $es, 15 ) ) ) {
// Could not establish connection to host
return "Connection failed, check hostname/port?";
}
// Make sure that the protocol is correct
if ( $this->status_match($socket, '220') === false ) {
// Probably a wrong protocol (SSL/TLS)
return "Connection failed, check protocol?";
}
// Send hello message to server
fwrite ( $socket, "EHLO " . $config ["hostname"] ."\r\n" );
if ( $this->status_match ( $socket, "250" ) === false ) {
// If Hello fails, say config is invalid
return "Invalid SMTP configuration";
}
// Request to login
fwrite ( $socket, "AUTH LOGIN\r\n" );
if ( $this->status_match ( $socket, "334" ) === false ) {
return "Invalid SMTP configuration";
}
// Send the username
fwrite ( $socket, base64_encode ( $config [ "username" ] ) . "\r\n" );
if ( $this->status_match ( $socket, "334" ) === false ) {
// If failed, warn that invalid username password was passed
return "Invalid username/password combination.";
}
// Send the password
fwrite ( $socket, base64_encode ( $config [ "password" ] ) . "\r\n" );
if ( $this->status_match ( $socket, "235" ) === false ) {
// If failed, warn that invalid username password was passed
return "Invalid username/password combination.";
}
// Close the socket connections
fclose ( $socket );
// Return true, if everything above passed
return true;
}
private function status_match ( $socket, $expected ) {
// Initialize the response string
$response = '';
// Get response until nothing but code is visible
while ( substr ( $response, 3, 1) != ' ' ) {
// Receive 250 bytes
if ( !( $response = fgets ( $socket, 256 ) ) ) {
// Break if nothing else to read
break;
}
}
// If the status code is not what was expected
if ( !( substr ( $response, 0, 3 ) == $expected ) ) {
// Return false
return false;
}
// Otherwise return true
return true;
}
I came up with this by using the following example: http://schoudhury.com/blog/articles/send-email-using-gmail-from-php-with-fsockopen/