[BUGFIX] Browser hanging when testing e-mail connections

Swift Mailer is a fantastic library for sending email with php. Discuss this library or ask any questions about it here.

Moderators: Chris Corbyn, General Moderators

chazter6
Forum Newbie
Posts: 9
Joined: Thu Apr 12, 2007 1:38 pm

[BUGFIX] Browser hanging when testing e-mail connections

Post by chazter6 »

I have uploaded my script to my isp and I am using their sendmail function.

When I use this code for my file testEmail1.php:

Code: Select all

require_once ("swift/lib/Swift.php");
require_once ("swift/lib/Swift/Connection/Sendmail.php");

$swift =& new Swift(new Swift_Connection_NativeMail());

//Create the message
$message =& new Swift_Message("My subject Native", "My body");
 
//Now check if Swift actually sends it
if ($swift->send($message, "Address@Todomain.com", "Address@Fromdomain.com")) echo "Sent";
else echo "Failed";
..the browser will return with my page saying it was Sent. I do receive this e-mail in my test recepient.

Now when I use this code for my file testEmail2.php

Code: Select all

require_once ("swift/lib/Swift.php");
require_once ("swift/lib/Swift/Connection/Sendmail.php");

//Start Swift
$swift =& new Swift(new Swift_Connection_Sendmail(SWIFT_SENDMAIL_AUTO_DETECT));

//Create the message
$message =& new Swift_Message("My subject", "My body");
 
//Now check if Swift actually sends it
if ($swift->send($message, "im_chaz@rocketmail.com", "webmaster@isceca.com")) echo "Sent";
else echo "Failed";
...Both browsers FireFox and I.E. hangs, like it is trying to load the page. I dont get and indication that its been sent per my echo statement, BUT when I check my test e-mail account, I do receive the test e-mails (Successful). Though, my browser just keeps hanging. I have used the connection timeout setting per

http://www.swiftmailer.org/wikidocs/v3/ ... s/sendmail

..and my test script testEmail2.php is still reacts the same. Any ideas? The browsers does not timeout it continues to act like its loading the page or awaiting a response somehow and I have to manually stop the page.

Thanks.
User avatar
Chris Corbyn
Breakbeat Nuttzer
Posts: 13098
Joined: Wed Mar 24, 2004 7:57 am
Location: Melbourne, Australia

Post by Chris Corbyn »

You're the second person to tell me of this issue I cannot reproduce (it's the check for the executable). Can I ask if your MTA is postfix? If you don't know, you can check by running this command on the server:

Code: Select all

/usr/sbin/sendmail -bs
QUIT
That wil print a line starting with 220. If that line has "postfix" in it then you use postfix which is the same as the other bug-reporter and helps me to narrow this down :)

The ad-hoc fix (I haven't found an alternative bit of code that doesn't have other drawbacks) is this:

Open Sendmail.php and change the function start() to comment out the following:

Code: Select all

//    $test = popen($this->getCommand() . " 2>&1", "r");
//    $read = fread($test, 4);
//    fclose($test);
//    if ((strpos($this->getFlags(), "t") !== false && !empty($read))
//      && (substr($read, 0, 4) != "220 "))
//    {
//      throw new Swift_Connection_Exception(
//        "Sendmail cannot be started.  The command given [" . $this->getCommand() . "] does not appear to be valid.");
//    }
That code is superfluosu anyway if you already know the binary is there.

I am looking into another approach though. I had a simple is_executable() before but a problem was brought to light with this approach.
chazter6
Forum Newbie
Posts: 9
Joined: Thu Apr 12, 2007 1:38 pm

Post by chazter6 »

d11wtq wrote:You're the second person to tell me of this issue I cannot reproduce (it's the check for the executable). Can I ask if your MTA is postfix? If you don't know, you can check by running this command on the server:

Code: Select all

/usr/sbin/sendmail -bs
QUIT
That wil print a line starting with 220. If that line has "postfix" in it then you use postfix which is the same as the other bug-reporter and helps me to narrow this down :)
I dont have command line access to the ISP server but I did call them and they indicated they were using QMAIL as the MTA.
d11wtq wrote: The ad-hoc fix (I haven't found an alternative bit of code that doesn't have other drawbacks) is this:

Open Sendmail.php and change the function start() to comment out the following:

Code: Select all

//    $test = popen($this->getCommand() . " 2>&1", "r");
//    $read = fread($test, 4);
//    fclose($test);
//    if ((strpos($this->getFlags(), "t") !== false && !empty($read))
//      && (substr($read, 0, 4) != "220 "))
//    {
//      throw new Swift_Connection_Exception(
//        "Sendmail cannot be started.  The command given [" . $this->getCommand() . "] does not appear to be valid.");
//    }
That code is superfluosu anyway if you already know the binary is there.

I am looking into another approach though. I had a simple is_executable() before but a problem was brought to light with this approach.
My sendmail.php file has this...It looks a bit different. Is this the same? I am using your version for php4.

Code: Select all

$test = popen($this->getCommand() . " 2>&1", "r");
    $read = fread($test, 4);
    fclose($test);
    if ((strpos($this->getFlags(), "t") !== false && !empty($read))
      && (substr($read, 0, 4) != "220 "))
    {
      Swift_Errors::trigger(new Swift_Connection_Exception(
        "Sendmail cannot be started.  The command given [" . $this->getCommand() . "] does not appear to be valid."));
      return;
    }
UPDATE: I went ahead and commented the php code I had in my sendmail.php out and still go the same result. The browser just hangs.
User avatar
Chris Corbyn
Breakbeat Nuttzer
Posts: 13098
Joined: Wed Mar 24, 2004 7:57 am
Location: Melbourne, Australia

Post by Chris Corbyn »

What happens if you change this:

Code: Select all

$swift =& new Swift(new Swift_Connection_Sendmail(SWIFT_SENDMAIL_AUTO_DETECT));
To this:

Code: Select all

$swift =& new Swift(new Swift_Connection_Sendmail());
If you can post a phpinfo() showing the value of sendmail_path that would be HUGELY useful :)
chazter6
Forum Newbie
Posts: 9
Joined: Thu Apr 12, 2007 1:38 pm

Post by chazter6 »

d11wtq wrote:What happens if you change this:

Code: Select all

$swift =& new Swift(new Swift_Connection_Sendmail(SWIFT_SENDMAIL_AUTO_DETECT));
To this:

Code: Select all

$swift =& new Swift(new Swift_Connection_Sendmail());
If you can post a phpinfo() showing the value of sendmail_path that would be HUGELY useful :)
Sorry, I was out on a lunch...I changed to what you suggested but still the same problem. I am able to receive my test e-mail, but the browser still hangs.

I am going to PM you my link for the PHP Info.

Thanks.
stonedyak
Forum Newbie
Posts: 6
Joined: Thu Apr 19, 2007 10:37 am
Location: Shropshire, UK

Post by stonedyak »

I am having the same problem with the sendmail connection hanging. Commenting out that bit of code did work for me, so I tried testing the popen code on its own:

Code: Select all

$test = popen("/usr/sbin/sendmail -bs 2>&1", "r");
echo "opened connection\n";
$read = fread($test, 4); // this never returns
fclose($test);
echo $read;
The 'hang' occurs on the fread call. If I replace the command with "/bin/echo hello 2>&1", it works perfectly. If I run ps aux | grep sendmail while that script is hanging, I get:

Code: Select all

paul    51960  1.0  0.5  3436  2400  pv  S+    5:02PM   0:00.02 sendmail: server paul@localhost cmd read (sendmail)
paul    51959  0.0  0.2  1632  1048  pv  S+    5:02PM   0:00.00 sh -c /usr/libexec/sendmail/sendmail -bs 2>&1
Running sendmail on the commandline:

Code: Select all

[paul@ra][~] $ /usr/sbin/sendmail -bs 2>&1
220 ra.example.net ESMTP Sendmail 8.13.6/8.13.6/Submit; Thu, 19 Apr 2007 16:53:24 +0100 (BST)
QUIT
221 2.0.0 ra.example.net closing connection
sendmail_path in php.ini is /usr/sbin/sendmail -t -i. I'm running on FreeBSD 6.1
stonedyak
Forum Newbie
Posts: 6
Joined: Thu Apr 19, 2007 10:37 am
Location: Shropshire, UK

Post by stonedyak »

Actually, my previous post is incorrect. I assumed the hang was happening on the fread - actually it was happening on fclose. However, if I remove the fread, and just close the connection without reading anything then it works ok.
User avatar
Chris Corbyn
Breakbeat Nuttzer
Posts: 13098
Joined: Wed Mar 24, 2004 7:57 am
Location: Melbourne, Australia

Post by Chris Corbyn »

stonedyak wrote:Actually, my previous post is incorrect. I assumed the hang was happening on the fread - actually it was happening on fclose. However, if I remove the fread, and just close the connection without reading anything then it works ok.
That's useful to me, thank you :) I`m reluctant to go back to the obvious is_executable() check because some servers were reporitng FALSE even when they could successuflly start the process. Maybe some fseek()/fflush() trickery or something will help fix this.
stonedyak
Forum Newbie
Posts: 6
Joined: Thu Apr 19, 2007 10:37 am
Location: Shropshire, UK

Post by stonedyak »

No luck with fflush before or after the fread. Using fseek results in a warning that the 'stream does not support seeking'.

Do you have any other suggestions?
User avatar
Chris Corbyn
Breakbeat Nuttzer
Posts: 13098
Joined: Wed Mar 24, 2004 7:57 am
Location: Melbourne, Australia

Post by Chris Corbyn »

I'll have to have a snoop around the stream functions. Maybe a simple unset() will work. I believe unsetting a resource closes it.
stonedyak
Forum Newbie
Posts: 6
Joined: Thu Apr 19, 2007 10:37 am
Location: Shropshire, UK

Post by stonedyak »

unset() hangs, and so does exit().
stonedyak
Forum Newbie
Posts: 6
Joined: Thu Apr 19, 2007 10:37 am
Location: Shropshire, UK

Post by stonedyak »

Silly question, but why is the popen needed at all? Couldn't you just read from the proc_open pipe and throw an error if you don't get anything?
User avatar
Chris Corbyn
Breakbeat Nuttzer
Posts: 13098
Joined: Wed Mar 24, 2004 7:57 am
Location: Melbourne, Australia

Post by Chris Corbyn »

stonedyak wrote:Silly question, but why is the popen needed at all? Couldn't you just read from the proc_open pipe and throw an error if you don't get anything?
Not a silly question at all. proc_open() hangs even beyond the 30 second time limit if you try reading from a non-existing process. Reason: it's tryng to read the bash shell. proc_open() *always* returns a process because it uses bash (or sh, or DOS) to launch the process. It sucks.
User avatar
Chris Corbyn
Breakbeat Nuttzer
Posts: 13098
Joined: Wed Mar 24, 2004 7:57 am
Location: Melbourne, Australia

Post by Chris Corbyn »

Here's a couple of threads I've had here regarding proc_open in the past if it helps with any background info:

viewtopic.php?t=63602&highlight=procopen
viewtopic.php?t=64654&highlight=procopen
User avatar
Chris Corbyn
Breakbeat Nuttzer
Posts: 13098
Joined: Wed Mar 24, 2004 7:57 am
Location: Melbourne, Australia

Post by Chris Corbyn »

I think I have an inexpensive solution to this and my testing on my server setting all kinds of restrictive permissions (i.e. nothing but execute, no read or write) and using symlinks etc still works.

Simple:

Code: Select all

if (!@stat($this->getPath()))
{
  //No use
}
The @ is needed though since it throws a warning without it. Worth a shot :)
Post Reply