php mail error handling when no smtp server - php

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

Related

Bad Message Number IMAP

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?

Using https when calling waitFor method setting up openstack nova server

I have the following PHP script (this is just the bottom half):
use Guzzle\Http\Exception\BadResponseException;
$server = $compute->server();
try {
$response = $server->create(array(
'name' => 'My server',
'image' => $centos,
'flavor' => $twoGbFlavor
));
} catch (BadResponseException $e) {
// No! Something failed. Let's find out:
printf("Request: %s\n\nResponse: %s", $e->getRequest(), $e->getResponse());
}
use OpenCloud\Compute\Constants\ServerState;
$callback = function($server) {
if (!empty($server->error)) {
var_dump($server->error);
exit;
} else {
echo sprintf(
"Waiting on %s/%-12s %4s%%",
$server->name(),
$server->status(),
isset($server->progress) ? $server->progress : 0
);
}
};
$server->waitFor(ServerState::ACTIVE, 600, $callback);
When I run it I receive the following error:
PHP Fatal error: Uncaught exception 'Guzzle\Http\Exception\CurlException' with message '[curl] 52: Empty reply from server [url] http://api.openstack.ecloud.co.uk:8774/v2/b7db5fe13c044b6e95bf5b766ae49393/servers/f5bf8951-f662-4940-904c-023b98b724c0' in /var/www/html/nutshell/openstack/vendor/guzzle/guzzle/src/Guzzle/Http/Curl/CurlMulti.php:359
I have narrowed it down to a problem with the waitFor method using http instead https. However I am unable to work out how to get this method to use https or if there is a setting I can change to force all calls over https?
In addition I have tried running these commands using curl on the command line, outside of the script, and can confirm the https one works. So I just need to work out how to get the script call to use https.
Also, note the $server->create call above works fine and I would have just expected the waitFor to work in the same fashion (i.e. over https).
Any help would be much appreciated.
You created server with https, got response with server data. Server data contains self url and that url is most probably http.
"waitFor" is calling openstack for server data with that url. You can see this here:
https://github.com/rackspace/php-opencloud/blob/working/lib/OpenCloud/Common/Resource/BaseResource.php (line 148)

How to find error code/reason when stream_socket_accept() fails

I have a stream socket server written in PHP.
To see how many connections it can handle at a time,I wrote a simulator in C to create 1000 different clients to connect to the server.
stream_socket_accept was returning false a few times.
I need to find out the reason for this failure.
I tried socket_last_error() and socket_strerror() to get the error codes, but they returned 'Success'. These functions don't seem to be working on stream-sockets. Is there any way/ method to find out the actual error codes
My code:
$socket = #stream_socket_accept($this->master, "-1", $clientIp);
$ip = str_getcsv($clientIp, ":");
//socket accept error
if($socket === FALSE)
{
$this->logservice->log($this->module_name, "ERROR", "cannot accept the device connection");
***// Need to find error code here ***
}
I am able to see PHP level error messages in my logs now. # operator before stream_socket_accept was suppressing the error messages. (# symbol in php )

how to check if a mail server exists or not?

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.

PHP fatal error: Uncaught exception 'Exception' with message

I have a PHP script that connects to an api and posts information to their systems, but when its trying to connect it throws a fatal error:
Fatal error: Uncaught exception 'Exception' with message 'Problem with
'http://apitestserver.co.uk:9000/Service.svc/Items' in
/var/www/html/e/connect_test.php:17 Stack trace: #0
/var/www/html/e/connect_test.php(39):
do_http_request('http://apitest....', 'hello') #1 {main} thrown in
/var/www/html/e/connect_test.php on line 17
If I send it to a PHP script which just grabs the IP then it works, but if I send it to the API it doesn't. My PHP script creates XML and then forwards to the server. I was getting errors so I just created the following smaller script purely to test the connection:
function do_http_request($url, $data, $method = 'POST',
$optional_headers = 'Content-Type: application/atom+xml') {
$params = array(
'http' => array(
'method' => $method,
'content' => $data
)
);
if ($optional_headers !== null) {
$params['http']['header'] = $optional_headers;
}
$ctx = stream_context_create($params);
$fp = fopen($url, 'rb', false, $ctx);
if (!$fp) {
throw new Exception("Problem with $url");
}
$response = #stream_get_contents($fp);
if ($response === false) {
throw new Exception("Problem reading data from $url");
}
$metaData = stream_get_meta_data($fp);
fclose($fp);
if(!preg_match('~^HTTP.*([0-9]{3})~',
$metaData['wrapper_data'][0], $matches)){
throw new Exception('MALFORED RESPONSE - COULD NOT UNDERSTAND HTTP CODE');
}
if (substr($matches[1], 0, 1) != '2') {
throw new Exception('SERVER REPORTED HTTP ERROR ' . $matches[1]);
}
return $response;
}
$data = 'hello';
$paul =
do_http_request('http://apitestserver.co.uk:9000/Service.svc/Items',$data);
echo $paul;
If I change the URL to a simple script on another one of our servers which just grabs the IP of the incoming connection and returns it:
$ip=$_SERVER['REMOTE_ADDR'];
echo 'IP equals = ' . $ip;
Then it works fine with no errors.
Update -
with errors on it throws the following warning, probably because the script is not sending the correct info to the API
Warning: fopen(http://apitestserver.co.uk:9000/Service.svc/Items)
[function.fopen]: failed to open stream: HTTP request failed! HTTP/1.1
500 Data at the root level is invalid. Line 1, position 1.
Also note that I can access the api server fine using fiddler to send manually created items across, its just when this script tries to connect and send data there is an issue. I wrote another quick script which connects and prints out the default response (an rss feed of submitted items)
When I run the 'main' connector script it throws the following two errors
Warning: fopen() [function.fopen]: php_network_getaddresses:
getaddrinfo failed: Name or service not known in
/var/www/html/e/sequence.php on line 65
Warning: fopen(http://apitestserver.co.uk:9000/Service.svc/Items)
[function.fopen]: failed to open stream: Operation now in progress
in /var/www/html/e/sequence.php on line 65
I would suggest using curl instead of fopen(). curl is both more flexible, and more secure. Many servers disable allow_url_fopen, curl also fails more gracefully when there are problems on the remote server.
I just tested the URL in my browser and got a connection error.
Maybe the problem is with their server (or you have the wrong URL)?
Edit:
Looks like ther server is throwing a 500 error - maybe because the data you're posting is invalid.
You could use a packet sniffer and check the exact data you're sending to the server (or use cURL as suggested by #acrosman)
apitestserver.co.uk doesn't respond to ping and the url is inaccessable. The API-server doesn't seem to be up.
or You can change the headers:
$optional_headers = 'Content-Type: application/json')
First error message suggests problems with apitestserver - it returns error code 500, which states for "Internal server error".
Second one informs that PHP can't resolve host name into IP address - I'd look into DNS configuration and/or hosts file.
Apparently 'fopen' function does not return proper stream. There can be many possibilities when that happens, but according to PHP manual, fopen function on fail should present E_WARNING message with proper commentary. It is possible that you have errors of that class silenced - call error_reporting(E_ALL) at the beginning of your script and look for some relevant error messages.

Categories