Jump to content

Sending emails over SMTP with fsockopen


whastings

Recommended Posts

I am still new to php, but have a fair amount of experience in other languages. Anyway I decided to start working on a CMS for my own site, and I will be using Amazons SES service to be sending emails. I have this function written to send an email to the user when they register so they can activate their account. But it would be great if I could get passed asking the SMTP server 'EHLO' and not getting a 421 timed out error code.

function smtp_parse($socket, $message, $response)
{
	global $mailSettings;
	if($message !== null) fputs($socket, $message . $mailSettings['newLine']);
	
	echo('Message => ' . $message . $mailSettings['newLine'] . '<br />');
	$server_response = '';
	while(substr($server_response, 3, 1) != ' ')
	{
		if(!($server_response = fgets($socket, 256))) return false;
	}
	
	echo('Response => ' . $server_response . '<br /><br />');
	if($response == substr($server_response, 0, 3)) return true;
	else return false;
}

function smtp_mail($to, $to_name, $subject, $body)
{
	global $mailSettings;
	if(!($socket = fsockopen($mailSettings['host'], $mailSettings['port'], $errno, $errstr, $mailSettings['timeout'])))
	{
		return false;
	}
	
	if(!smtp_parse($socket, null, '220')) return false;
        //it times out here!
	if(smtp_parse($socket, 'EHLO ' . $mailSettings['host'], '250'))
	{
                //Never makes it to here
		smtp_parse($socket, 'AUTH LOGING', '334');
		smtp_parse($socket, base64_encode($mailSettings['user']), '334');
		smtp_parse($socket, $mailSettings['pass'], '334');
                smtp_parse($socket, 'MAIL FROM: my name <' . $mailSettings['return'] . '>', '250');
                smtp_parse($socket, 'RCPT TO: ' . $to_name . ' <' . $to . '>', '250');
                smtp_parse($socket, 'DATA', '354');
		
		$headers = "MIME-Version: 1.0" . $mailSettings['newLine'];
		$headers .= "Connect-Type: text/html; charset=iso-8859-1";
		$headers .= "To: " . $to_name . " <" . $to . ">" . $mailSettings['newLine'];
		$headers .= "From: my name <" . $mailSettings['return'] . ">" . $mailSettings['newLine'];
		$headers .= "Subject: " . $subject . $mailSettings['newLine'];
		$body = strtr($body, array('\r\n' . '.' => '\r\n' . '..'));
		
		smtp_parse($socket, $headers, '250');
		smtp_parse($socket, $body, '250');
		smtp_parse($socket, '.', '250');
		smtp_parse($socket, 'QUIT', null);
		fclose($socket);
		return true;
	}
	return false;
}
$mailSettings = array('host' => 'email-smtp.us-east-1.amazonaws.com',
						'port' => '25',
						'timeout' => '2',
						'identity' => 'email-smtp.amazonaws.com',
						'newLine' => '\r\n',
						'user' => '...',
						'pass' => '...',
						'return' => 'noreply@domain');

The debug response I am getting from my test email I am trying to send is

 

Message => \r\n
Response => 220 email-smtp.amazonaws.com ESMTP SimpleEmailService-625029891

Message => EHLO email-smtp.us-east-1.amazonaws.com\r\n
Response => 421 Timeout waiting for data from client.

Mail sent un-succesfuly!

 

I am probably doing something wrong, I don't know. I am trying to avoid using classes like PHPMailer, SwiftMailer, ... because I would like to learn how to do it myself.

Any suggestions, pointers, and help would be great. But as I said I can't get past the EHLO to the SMTP server, as it times out afterwards.

Link to comment
https://forums.phpfreaks.com/topic/286248-sending-emails-over-smtp-with-fsockopen/
Share on other sites

Yea, the script works fine to me.

So, a few recommendations before to continue with this php testing script.

Open up a telnet terminal from your local machine, test if the port 25 is open, and try to get the server greetings using " "EHLO" word.

telnet servername.domainname.com 25
EHLO servername.domainname.com
220 srvername.domainname.com ESMTP Postfix
EHLO servername.domainname.com
250-servername.domainname.com
250-PIPELINING
250-SIZE 10240000
250-VRFY
250-ETRN
250-ENHANCEDSTATUSCODES
250-8BITMIME
250 DSN

 

Yea, the script works fine to me.

So, a few recommendations before to continue with this php testing script.

Open up a telnet terminal from your local machine, test if the port 25 is open, and try to get the server greetings using " "EHLO" word.

telnet servername.domainname.com 25
EHLO servername.domainname.com
220 srvername.domainname.com ESMTP Postfix
EHLO servername.domainname.com
250-servername.domainname.com
250-PIPELINING
250-SIZE 10240000
250-VRFY
250-ETRN
250-ENHANCEDSTATUSCODES
250-8BITMIME
250 DSN

 

I opened up a telnet window to get to the EHLO screen and it worked.

 

220 email-smtp.amazonaws.com ESMTP SimpleEmailService-625029891

EHLO email-smtp.us-east-1.amazonaws.com

250-email-smtp.amazonaws.com

250-8BITMIME

250-SIZE 10485760

250-STARTTLS

250-AUTH PLAIN LOGIN

250 Ok

 

 

 

I am getting the EHLO response. Still not sure why it times out :x

I have no idea how about "amazon" are configured their mail servers.

 

Alright, well thanks for at-least confirming my code does in-fact work. I will just have to keep tinkering until I figure out whats wrong. I also noticed I did not have the php_openssl.dll enabled within my php.ini file, and once I edited it I managed to get a crypto error result which I fixed which sent me back to the time-out response. I may just not have a type of authentication or module needed turned enabled/compiled in my version of php. Which would not make much sense as I am already using Amazons SES service on a open source forum software. I even compared my code against theirs and don't see anything that should effect my result. I have also uploaded the files to that same web-server to see if its just my local version of php or apache as I run nginx and php on my box.

 

Anyway, thanks again! If you do think of anything or for me to try I would be hopelessly grateful!

 

'newLine' => '\r\n',

 

You have the \r\n inside single-quotes so it'll be treated literally rather than as a new-line character as intended. So when you send your message you are sending literally slash-r-slash-n and not a new line. The SMTP server is waiting for that new line before it parses the message and sends a response.

You have the \r\n inside single-quotes so it'll be treated literally rather than as a new-line character as intended. So when you send your message you are sending literally slash-r-slash-n and not a new line. The SMTP server is waiting for that new line before it parses the message and sends a response.

 

I did not realize that single and double quotes meant different things. Wow, thanks! That did the trick!

 

You have the \r\n inside single-quotes so it'll be treated literally rather than as a new-line character as intended.

 

Completely missing this. :happy-04:

When he wrote the "ELHO" works by telnet but not with php script my suggest was about mail server configuration.

A good observation @kick.

Archived

This topic is now archived and is closed to further replies.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.