I am a php beginner and I am working on a mail parser. For that, I am going through PHP's IMAP functions which I wrote inside a mailParser class.
function __construct(){
$this->stream = imap_open($this->server,$this->username,$this->password) or
die('Cannot connect to Gmail'.imap_last_error());
}
When I ran this:
function getInboxHeaders(){
imap_headers($this->stream);
$tot_msg = imap_num_msg($this->stream);
for($count=$tot_msg;$count>-1;$count--){
$header = imap_header($this->stream,$count);
print_r($header);
}
}
inorder to get the headers of the messages on my Inbox, I was notified of the warning "Bad message number". Why do I get such a warning upon running this function?
Related
I make a php page to send email. I will give this page to multiple users, but I have no control of the server they will use. And some of them should have no SMTP server. So I try to handle this error.
For example, on my own computer, if I deactivate my SMTP server, I receive a "PHP Warning: mail(): Failed to connect to mailserver at ..." error message.
My code :
try
{
$okmail=mail($to,$Subject,$texte,$headers);
}
catch (Exception $ex)
{
...
}
But this code doesn't throw an exception, it only write the error message (like an "echo(...)" statement).
I use this code in a xmlhttprequest page and use an xml type response. But the original page receive the error message before the xml text :
PHP Warning: mail(): Failed to connect to mailserver at ... \n1Email not send
How can I handle this "no SMTP" error ?
Thanks!
If I understand the problem correctly, the following directive will hide the warnings.
ini_set('display_errors', 0);
Instead of "try/catch" you can use the following approach.
set_error_handler("warningHandler", E_USER_WARNING);
// Trigger some warning here for testing purposes only (this is just an example).
trigger_error('This here is the message from some warning ...', E_USER_WARNING);
// If you need DNS Resource Records associated with a hostname.
// $result = dns_get_record($_SERVER['HTTP_HOST']);
// Restores the previous error handler function.
restore_error_handler();
// This is your custom warning handler.
function warningHandler($errno, $errstr) {
// Do what you want here ...
echo $errno, ' ::: ', $errstr;
}
Thanks for your answers, but nothing works :(
I find a solution by cleaning the output buffer by using ob_start(null,0,PHP_OUTPUT_HANDLER_CLEANABLE) and ob_clean() just after the mail() function.
I don't understand why the mail function writes an error into the output buffer
I am doing a script to send a string via URL link to an SMS gateway and get the response from them.
They will respond with a code and text for the answer, either '200 = SUCCESS' or an error-code: '-100 = UNKNOWN ERROR' , '-101 = MISSING PARAMETER' , etc.
In my back-end code, I would like to know how to keep looping, waiting for the return message from the SMS Gateway with an error-code and resend my string to the SMS gateway until success or confirmation?
$link = "http://www.smsgateway.com/send.php?phoneno=".$phonenumber."&message=".urlencode($smsMessage);
Next, I use cURL to send this link and get the response:
$returned_content = using_cURL_function_to_get_response($link);
Now, my $returned_content will show:
Success Code: 200 = SUCCESS
Failure Code: -100 = UNKNOWN ERROR
Failure Code: -101 = MISSING PARAMETER
and many more -1xx failure / error-codes
Then, I want to perform a loop to check the $returned_content, if it is a failure / error-code then send again the string via cURL to the SMS gateway.
if ($returned_content = 'ANY FAILURE / ERROR-CODE') {
//redo cURL
$link = "http://www.smsgateway.com/send.php?phoneno=".$phonenumber."&message=".urlencode($smsMessage);
$returned_content = using_cURL_function_to_get_response($link);
// Check the $returned_content
} else {
// inform me the '200 = SUCCESS' via email
mail($myEmail, $successfulSubjectt, $returned_content, $msgHeaders);
}
I'm not sure about this looping part, anyone could help?
I guess what you're trying to do is this:
$link = "http://www.smsgateway.com/send.php?phoneno=".$phonenumber."&message=".urlencode($smsMessage);
while ($returned_content != '200 = SUCCESS')
{
$returned_content = using_cURL_function_to_get_response($link);
}
mail($myEmail, $successfulSubjectt, $returned_content, $msgHeaders);
But it's not a good idea. Suppose you never do get a success? You will have an infinite loop. You should really rethink what you're trying to do.
So when you try to send an SMS and you get an error, you want to retry sending? How would that work?
Also, not sure, but the target server might interpret this as a DoS attack.
I think you should rethink your approach. If your goal is enabling some users to send SMS, then how about presenting them with a message saying that there was an error delivering their SMS and they should try later?
I'm using the PHP Stomp client to send a stomp message.
I would like to leave a persistent connection open, in the background, and send messages occasionally.
However, I can't find a way to handle connection errors if they happen after opening the connection (on send()).
For example, when running:
<?php
$stomp = new Stomp('tcp://localhost:61613');
sleep(5); // Connection goes down in the meantime
$result = $stomp->send('/topic/test', 'TEST');
print "send " . ($result ? "successful\n": "failed\n");
?>
Output: send successful
Even if the connection goes down while in sleep(), send() always returns true.
The docs weren't very helpful, Stomp::error() and stomp_connect_error() also don't help much as they return false.
As a temporary solution, I'm reconnecting before every send().
Is there a better way to catch connection errors?
Found the answer in the specification of the stomp protocol itself:
Any client frame other than CONNECT MAY specify a receipt header with an arbitrary value. This will cause the server to acknowledge receipt of the frame with a RECEIPT frame which contains the value of this header as the value of the receipt-id header in the RECEIPT frame.
So setting a "receipt" header makes the request synchronous, so the connection to the server must be alive.
So the code:
$result = $stomp->send('/topic/test', 'TEST');
print "send " . ($result ? "successful\n": "failed\n");
$result = $stomp->send('/topic/test', 'TEST', array('receipt' => 'message-123'));
print "send " . ($result ? "successful\n": "failed\n");
Gives output:
send successful
send failed
It doesn't seem like the best solution for this case, but it works for me.
If anyone knows a better way I'll be happy to hear it.
Update:
Eventually I switched to Stomp-PHP (a pure PHP client) instead of the Pecl stomp client, which handles it much better.
my PHP page currently doesnot have a mail server, instead of throwing an error, is it possible to catch this error and print it out to the user?
this is what I have so far, it just gives an error.
<?php
$foo = mail('test#test.com', 'subject', 'message');
if ( $foo == false )
{
echo "no mail server";
}
?>
thanks!
You could open a port to the mail server in question using fsockopen('servername/ipaddres', 25); If it returns content, it means the port is open and that you could ASSUME that there is a mail server.
$errno = 0;
$errstr = '';
$fp = fsockopen("localhost", 25, $errno, $errstr, 5);
if (!$fp) {
echo "No mail server responded on this server on port 25, validate your configuration";
}
This is by all means very experimental, you need to involve yourself in more work but it should get you started :)
mail() could fail for other reasons than just a non-existant mail server. I think the best you can do is fail gracefully and show the user the message you got, and even that has limitations.
In PHP 5.1 and above, you could catch the error in the following way:
error_reporting(0); // Don't display errors
$success = mail(....);
if (!$success)
{
echo "Mailing failed: Error message: ".error_get_last();
}
if you need to support older versions than that, I think you'll have no option than showing the raw error message from mail() - you could theoretically suppress it, but that will not show the user what exactly went wrong.
I'm working on a project where I am verifying information from a user with a SOAP web service. I currently am taking care of errors assuming that I'm receiving responses from the web service, but also need to handle the edge cases of a service timeout or unavailability.
In the case of a timeout or service unavailability, I need to pretend that the request was successful (that the web service approved the info), but I'm not clear on what exceptions are thrown.
Some pseudo-code:
// $client is PHP's SoapClient class
try {
$response = $client->SomeSoapRequest();
}
catch(SoapFault $e){
// handle issues returned by the web service
}
catch(Exception $e){
// handle PHP issues with the request
}
What I can't seem to find is:
Are timeouts a SoapFault? If so, what is the best way to distinguish between a timeout error and web service issues (like a type error, etc.)? I found one page that mentioned an error where the message was something to the effect of "Error loading headers", but didn't mention if this was a Soap fault.
How is a service unavailability potentially going to happen? A PHP exception seems like it would make sense (a SoapFault would be returned from the web service where unavailability would be a socket issue or similar)?
Is there an existing service (e.g. example) that I can test a timeout against? Most timeout related discussions seem to be related to preventing timeouts by extending the default timeout setting, which isn't ideal in this situation.
1) In case of timeout, PHP throws a SoapFault exception with faultcode="HTTP" and faultstring="Error Fetching http headers".
2) In my opinion, the best way to distinguish between a timeout error and web service issues is by looking at the faultcode and faultstring members of the SoapFault class.
In particular, the faultcode element is intended for use by software to provide an algorithmic mechanism for identifying the fault.
As you can also read in a comment of the PHP manual, there is no method to read the faultcode property, so you have to access it directly (eg. $e->faultcode), because the getCode() method does not work.
The SOAP 1.1 Spec defines four possible values for the faultcode field:
VersionMismatch: The processing party found an invalid namespace for the SOAP Envelope element
MustUnderstand: An immediate child element of the SOAP Header element that was either not understood or not obeyed by the processing party contained a SOAP mustUnderstand attribute with a value of "1"
Client: The Client class of errors indicate that the message was incorrectly formed or did not contain the appropriate information in order to succeed. For example, the message could lack the proper authentication or payment information. It is generally an indication that the message should not be resent without change.
Server: The Server class of errors indicate that the message could not be processed for reasons not directly attributable to the contents of the message itself but rather to the processing of the message. For example, processing could include communicating with an upstream processor, which didn't respond. The message may succeed at a later point in time.
In addition to those codes, PHP uses the HTTP code for identifying the errors happening at the protocol level (eg.: socket errors); for example, if you search for add_soap_fault in the ext/soap/php_http.c source code you can see when some of these kind of faults are generated.
By searching for the add_soap_fault and soap_server_fault functions in the PHP SOAP extension source files, I've built the following list of PHP SoapFault exceptions:
HTTP
----
Unable to parse URL
Unknown protocol. Only http and https are allowed.
SSL support is not available in this build
Could not connect to host
Failed Sending HTTP SOAP request
Failed to create stream??
Error Fetching http headers
Error Fetching http body: No Content-Length: connection closed or chunked data
Redirection limit reached: aborting
Didn't recieve an xml document
Unknown Content-Encoding
Can't uncompress compressed response
Error build soap request
VersionMismatch
---------------
Wrong Version
Client
------
A SOAP 1.2 envelope can contain only Header and Body
A SOAP Body element cannot have non Namespace qualified attributes
A SOAP Envelope element cannot have non Namespace qualified attributes
A SOAP Header element cannot have non Namespace qualified attributes
Bad Request
Body must be present in a SOAP envelope
Can't find response data
DTD are not supported by SOAP
encodingStyle cannot be specified on the Body
encodingStyle cannot be specified on the Envelope
encodingStyle cannot be specified on the Header
Error cannot find parameter
Error could not find "location" property
Error finding "uri" property
looks like we got "Body" with several functions call
looks like we got "Body" without function call
looks like we got no XML document
looks like we got XML without "Envelope" element
Missing parameter
mustUnderstand value is not boolean
SoapClient::__doRequest() failed
SoapClient::__doRequest() returned non string value
Unknown Data Encoding Style
Unknown Error
DataEncodingUnknown
MustUnderstand
--------------
Header not understood
Server
------
Couldn't find WSDL
DTD are not supported by SOAP
Unknown SOAP version
WSDL generation is not supported yet
3) To simulate the timeout condition, try with the following code:
soapclient.php
<?php
ini_set('default_socket_timeout', 10);
$client = new SoapClient(null,
array(
'location' => "http://localhost/soapserver.php",
'uri' => "http://localhost/soapserver.php",
'trace' => 1
)
);
try {
echo $return = $client->__soapCall("add",array(41, 51));
} catch (SoapFault $e) {
echo "<pre>SoapFault: ".print_r($e, true)."</pre>\n";
//echo "<pre>faultcode: '".$e->faultcode."'</pre>";
//echo "<pre>faultstring: '".$e->getMessage()."'</pre>";
}
?>
soapserver.php
<?php
function add($a, $b) {
return $a + $b;
}
sleep(20);
$soap = new SoapServer(null, array('uri' => 'http://localhost/soapserver.php'));
$soap->addFunction("add");
$soap->handle();
?>
Notice the sleep call in the SoapServer.php script with a time (20) longest than the time (10) specified for the default_socket_timeout parameter in the SoapClient.php script.
If you want to simulate a service unavailability, you could for example change the location protocol from http to https in the soapclient.php script, assuming that your web server is not configured for SSL; by doing this, PHP should throw a "Could not connect to host" SoapFault.
Looks like default_socket_timeout is not taken into account when making SOAP calls over HTTPS:
Bug #48524 - Timeout setting is not considered on SOAP+HTTPS calls.
Bug open at the time of writing. As a comment on the blog post Robert Ludwick referenced in a deleted answer Timing Out PHP Soap Calls (21 Oct 2009; by Published by Robert F. Ludwick) points out, the workaround the post discusses (overriding SoapClient::__doRequest() with a curl request) works around this bug also.
archived copy of <http://www.darqbyte.com/2009/10/21/timing-out-php-soap-calls/>
Another related bug is:
Bug #41631 - default_socket_timeout does not work with SSL
The code mentioned in the blog post has undergone some changes and can be found in it's latest form with support of HTTP authentication here on Github:
SoapClientTimeout.class.php
In any case, the workaround shouldn't be needed any longer as this problem has been fixed in the PHP SOAPClient extension.
To deal with timeouts in the service
$client = new SoapClient($wsdl, array("connection_timeout"=>10));
// SET SOCKET TIMEOUT
if(defined('RESPONSE_TIMEOUT') && RESPONSE_TIMEOUT != '') {
ini_set('default_socket_timeout', RESPONSE_TIMEOUT);
}
From my experience, if $e->getMessage is "Error Fetching http headers", you are dealing with a network timeout.
If $e->getMessage is something like "Cannot connect to host", the service you are trying to reach is down.
Then there is "Looks like we got no XML document", which is more cryptic an can mean different things.
I used two factors to get my SoapClient extention to throw a nice exception. The message and the time the request took to return. I think the error message "Error Fetching http headers" can also occure in some other cases, therefore the time check.
The following code should be about right
class SoapClientWithTimeout extends SoapClient {
public function __soapCall ($params, ---) {
$time_start = microtime(true);
try {
$result = parent::__soapCall ($params, ---);
}
catch (Exception $e) {
$time_request = (microtime(true)-$time_start);
if(
$e->getMessage() == 'Error Fetching http headers' &&
ini_get('default_socket_timeout') < $time_request
) {
throw new SoapTimeoutException(
'Soap request most likly timed out.'.
' It took '.$time_request.
' and the limit is '.ini_get('default_socket_timeout')
);
}
// E: Not a timeout, let's rethrow the original exception
throw $e;
}
// All good, no exception from the service or PHP
return $result;
}
}
class SoapTimeoutException extends Exception {}
I then use SoapClientWithTimeout
$client = new SoapClientWithTimeout();
try {
$response = $client->SomeSoapRequest();
var_dump($response);
}
catch(SoapTimeoutException $e){
echo 'We experienced a timeout! '. $e->getMessage();
}
catch(Exception $e) {
echo 'Exception: '.$e->getMessage();
}
To debug your service timing out. Add the following line before calling the service
ini_set('default_socket_timeout', 1);
Simply setting the default_socket_timeout globally via the ini may not do what you want. This would affect SOAP requests, but would also affect other outgoing connections, including DB connections. Instead, override SoapClient's __doRequest() method to make the HTTP connection yourself. You can then set your own timeout on the socket, detect it, and throw exceptions that you can trap and handle.
class SoapClientWithTimeout extends SoapClient {
public function __construct ($wsdl, $options = null) {
if (!$options) $options = [];
$this->_connectionTimeout =
#$options['connection_timeout']
?: ini_get ('default_socket_timeout');
$this->_socketTimeout =
#$options['socket_timeout']
?: ini_get ('default_socket_timeout');
unset ($options['socket_timeout']);
parent::__construct($wsdl, $options);
}
/**
* Override parent __doRequest to add a timeout.
*/
public function __doRequest (
$request, $location, $action, $version, $one_way = 0
) {
// Extract host, port, and scheme.
$url_parts = parse_url ($location);
$host = $url_parts['host'];
$port =
#$url_parts['port']
?: ($url_parts['scheme'] == 'https' ? 443 : 80);
$length = strlen ($request);
// Form the HTTP SOAP request.
$http_req = "POST $location HTTP/1.0\r\n";
$http_req .= "Host: $host\r\n";
$http_req .= "SoapAction: $action\r\n";
$http_req .= "Content-Type: text/xml; charset=utf-8\r\n";
$http_req .= "Content-Length: $length\r\n";
$http_req .= "\r\n";
$http_req .= $request;
// Need to tell fsockopen to use SSL when requested.
if ($url_parts['scheme'] == 'https')
$host = 'ssl://'.$host;
// Open the connection.
$socket = #fsockopen (
$host, $port, $errno, $errstr, $this->_connectionTimeout
);
if (!$socket)
throw new SoapFault (
'Client',
"Failed to connect to SOAP server ($location): $errstr"
);
// Send the request.
stream_set_timeout ($socket, $this->_socketTimeout);
fwrite ($socket, $http_req);
// Read the response.
$http_response = stream_get_contents ($socket);
// Close the socket and throw an exception if we timed out.
$info = stream_get_meta_data ($socket);
fclose ($socket);
if ($info['timed_out'])
throw new SoapFault (
'Client',
"HTTP timeout contacting $location"
);
// Extract the XML from the HTTP response and return it.
$response = preg_replace (
'/
\A # Start of string
.*? # Match any number of characters (as few as possible)
^ # Start of line
\r # Carriage Return
$ # End of line
/smx',
'', $http_response
);
return $response;
}
}
Guess I'm little late, but in case someone is still looking for solution to timeouts in php soap client - here's what's worked for me:
archived copy of <http://www.darqbyte.com/2009/10/21/timing-out-php-soap-calls/>
Basicly replacing PHP SoapClient with cURL with set timeout. Just keep in mind, sometimes WS expects action specified in HTTP header. Original solution posted on that website doesn't include that (check comments).
just use the "stream_context" to set the timeout setting also for WSDL loading (you need to set the SoapClient $options['connection_timeout'] before):
class SoapClient2 extends SoapClient
{
public function __construct($wsdl, $options=null)
{
if(isset($options['connection_timeout']))
{
$s_options = array(
'http' => array(
'timeout' => $options['connection_timeout']
)
);
$options['stream_context'] = stream_context_create($s_options);
}
parent::__construct($wsdl, $options);
}
}