Jump to content

Sending emails over SMTP with fsockopen


whastings
Go to solution Solved by 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.

Edited by whastings
Link to comment
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

Link to comment
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

 

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

Edited by whastings
Link to comment
Share on other sites

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!

Link to comment
Share on other sites

 

'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.

Edited by kicken
Link to comment
Share on other sites

  • Solution

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!

Link to comment
Share on other sites

 

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.

Link to comment
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • 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.