The CI Email send() function only returns true or false. Is there a way to get a more detailed reason as to why a sending failed? I'm using SMTP.
You can further inspect what happened by using the email debugger:
$r = $this->send(FALSE);
if (!$r)
$this->email->print_debugger()
;
From the Codeigniter Email Class Reference.
If you need the debugger output as a string, you can just catch the output with an output buffer:
$errors = array();
... # Loop
$r = $this->send(FALSE);
if (!$r) {
ob_start();
$this->email->print_debugger();
$error = ob_end_clean();
$errors[] = $error;
}
... # Loop end
Codeigniter in more recent versions requires an explicit FALSE for the $auto_clear parameter of the email->send() function in order to not clear the message and the debugging, effectively killing the debugger function if you fail to pass the FALSE.
The print_debugger() function will work but it appends the e-mail header and message at the bottom. If all you want is an array of the debug message (which include both success and error messages), you could consider extending the functionality of the Email class as follows:
<?php
class MY_Email extends CI_Email
{
public function clear_debugger_messages()
{
$this->_debug_msg = array();
}
public function get_debugger_messages()
{
return $this->_debug_msg;
}
}
You'd want to place this in a file named MY_Email.php in your ./application/libraries folder. CodeIgniter will automatically recognize the existence of this class and use it instead of it's default one.
When you want to get a list (array) of debug messages, you can then do this:
$this->email->get_debugger_messages();
If you're looping through messages and don't want to include debugger messages from previous attempts, you can do this:
foreach ($email_addresses as $email_address)
{
$this->email->to($email_address);
if (! $this->email->send())
{
echo 'Failed';
// Loop through the debugger messages.
foreach ($this->email->get_debugger_messages() as $debugger_message)
echo $debugger_message;
// Remove the debugger messages as they're not necessary for the next attempt.
$this->email->clear_debugger_messages();
}
else
echo 'Sent';
}
Reference: "Extending Native Libraries" section of https://www.codeigniter.com/user_guide/general/creating_libraries.html.
Codeigniter 3:
if ( $this->email->send() ) {
echo 'Your Email has successfully been sent.';
} else {
$errors = $this->email->print_debugger();
print_r($errors);
}
You could check your mail logs. If the mail errors out then you should have a record saying why in there.
I'm not sure where they will be located though it depends on your system.
Related
I'm working on a chat application using PubNub and PHP. The publishing of messages is working but I'm not sure how to read from the subscriber.
I ran the subscriber file in the command line and it is showing the messages as they are published but I'm not sure how to read from it or how to return, as per the doc the subscriber is a separate process.
use PubNub\PNConfiguration;
class MySubscribeCallback extends SubscribeCallback {
function status($pubnub, $status) {
if ($status->getCategory() === PNStatusCategory::PNUnexpectedDisconnectCategory) {
// This event happens when radio / connectivity is lost
} else if ($status->getCategory() === PNStatusCategory::PNConnectedCategory) {
} else if ($status->getCategory() === PNStatusCategory::PNDecryptionErrorCategory) {
// Handle message decryption error. Probably client configured to
// encrypt messages and on live data feed it received plain text.
}
}
function message($pubnub, $message) {
print_r($pubnub);
print_r($message);
}
function presence($pubnub, $presence) {
// handle incoming presence data
}
}
$subscribeCallback = new MySubscribeCallback();
$pubnub->addListener($subscribeCallback);
$pubnub->subscribe()
->channels(["Channel-1","Channel-2","Channel-3"])
->execute();
this is the subscriber code present on the PubNub Doc.
I'm calling this file using javascript.
I'd like to preface this by saying that I've read answers to similar questions, and haven't managed to find something that both does the job and does not slow the site down.
I have a site that displays messages based on users' choices and actions. The code might look something like this :
if (option 1) {
$message1 = "Message A";
}
else if (option 2){
$message1 = "Message B";
}
else {
$message1 = "Message C";
}
There are a hand full of these throughout the site. When i want to echo the messages somewhere within the html structure i have to write:
<?php
if (isset($message1)) {
echo $message1;
}
?>
I've written a simple function which does its job:
function message($msg){
if (isset($msg)) {
echo $msg;
}
}
The problem is that i get notices for undefined variables, which makes sense because the variable isn't defined before the user clicks a button. I would like to avoid turning off error reporting.
So, is adding # in front of the function the only way? The code would then look like:
<?php
#message($message1);
?>
If that is acceptable, then great. If not, I'm open to alternatives.
Based on your comment, your use-case seems to make sense. In that case I would have an array with all error messages, something like:
$messages = array();
...
$messages['registration-form']['error']['password-mismatch'] = 'Passwords do not match';
...
And when I validate the input and find mismatching passwords, I would do:
// at the top
$errors = array();
...
// passwords don't match
$errors['passwords-mismatch'] = $messages['registration-form']['error']['password-mismatch'];
And where I output the form below the passwords:
messages($errors, 'password-mismatch');
And finally the function would be something like:
function messages($errors, $error) {
if (isset($errors[$error])) {
// I would wrap it in a span to highlight the error
echo '<span class="error">' . $errors[$error] . '</span>';
}
}
You can pass the variable by reference, function message(&$msg){, no error will be raise.
From the documentation:
If you assign, pass, or return an undefined variable by reference, it will get created.
Try this php in built function:
error_reporting(0);
I have a function that sends an email when a form is submitted. This function contains the following if-statement:
if ($guestDetails)
{
$mailer->addRecipient($guestDetails->email);
$mailer->addCC( $config->get('emails_admin_email'));
$mailer->setSubject( $subject );
$mailer->setBody($template_layout);
$mailer->IsHTML($mode);
$mailer->setSender(array( $mailfrom, $fromname ));
$sent = $mailer->send();
}
Recently, this function has stopped working (i.e. the emails are no longer being sent). To investigate what is going on I have modified the code to log some of the variables as there was nothing being recorded in the PHP Error log. Here is how the if-statement looks now:
$testArr = array();
ClassName::_log_r("guestdetails", $guestDetails);
if ($guestDetails)
{
ClassName::_log_r("got into if", $testArr);
$mailer->addRecipient($guestDetails->email);
$mailer->addCC( $config->get('emails_admin_email'));
$mailer->setSubject( $subject );
$mailer->setBody($template_layout);
$mailer->IsHTML($mode);
$mailer->setSender(array( $mailfrom, $fromname ));
$sent = $mailer->send();
ClassName::_log_r("mailer", $mailer);
ClassName::_log_r("sent", $sent);
} else
ClassName::_log_r("got into else", $testArr);
The _log_r is just a function that writes to a text file the contents of the given variable. Once I added this "debug" code, the emails started being sent once again and the log correctly records "got into if".
Removing the afore mentioned debug code stops the emails from being sent once again.
I am puzzled at what could be possibly going on here. Has anyone ever came across anything like this?
Why are emails not being sent when the debug code is removed?
Please let me know if more information is needed. Thanks!
PS the code is written in PHP and the server is running PHP 5.3.10
The only likely answer that comes to mind is that, for whatever reason, $guestDetails is not defined anymore (e.g., it got renamed into $guestDetail somewhere else).
This also would need the _log_r function to redefine the argument if it does not exist.
If you check the mails being sent to the CC: only, they will arrive - an invalid $guestDetails will probably not stop the process from completing. Actually ONLY the emails to the admin will get generated.
Try something like
if (!defined($guestDetails))
ClassName::_log_r("mailer", "Not defined");
if (empty($guestDetails))
ClassName::_log_r("mailer", "empty");
and see whether some more detail can be worried out.
Instead of logging with _log_r, try to catch mail exceptions and check if you get better info on whats going on:
if ($guestDetails)
{
try
{
$mailer->addRecipient($guestDetails->email);
$mailer->addCC( $config->get('emails_admin_email'));
$mailer->setSubject( $subject );
$mailer->setBody($template_layout);
$mailer->IsHTML($mode);
$mailer->setSender(array( $mailfrom, $fromname ));
$sent = $mailer->send();
}
catch (phpmailerException $e)
{
echo $e->errorMessage(); //you could do a _log_r here..
}
catch (Exception $e)
{
echo $e->getMessage(); //or here..
}
}
else
{
echo "guestDetails empty!"; //or here..
}
What is the standard way to return errors to the user from a function? (email invalid, max characters exeeded, etc.)
function register($name, $email) {
if(!$name) {
$registration_errors = 'name empty,';
}
if(!email) {
$registration_errors = $errors . 'email empty,';
}
if($registration_errors) {
return $registration_errors;
}
else {
register stuff........
return true;
}
}
now the problem is that it always returns true so you cant do something like:
if(register()) {blah blah blah} else { put errors under inputs}
So what would be the standard method of doing this?
use something like this
function register
{
..
else
{
return array('error' => $errorwhichyoufound);
}
....
}
$result = register();
if((array_key_exists('error', $result)))
{
}
else
{
}
This way you can even check for individual errors.
<?php
// in your register function:
$registration_errors = array();
if (!$name) {
$registration_errors['name'] = 'Name is required.';
}
// etc.
?>
<!-- in your phtml: -->
<?php if (array_key_exists('name', $registration_errors) echo $registration_errors['name'];?>
<label for="name">Name</label>
<input id="name" name="name" type="text" value="<?php echo $name; ?>" />
There are all sorts of ways to do this, and you might even consider some of them "standard". You could return an array containing the error code (as the answers above), you could store the error as an object property (requiring you to call "register" as an object method), you could store the error in a global variable, or put the error in a registered location. You could pass in a variable reference and set the variable value to the error. You could reverse the return logic, so a string would be false and a zero would be a true value. You could raise an error. You could throw an exception.
The real problem here is that the "register" function is supposed to perform some function and you are asking it to sanitize the input just in case something funny is going on. So if you really need to sanitize $name and $email, why not do that validation before the call to register? You are going to need some kind of error path regardless, and perhaps several different error messages depending on the situation. When you are finally ready to call register, it should succeed or fail for its own reasons, and not because the business rules require a non-empty email address.
I have an HTML form that takes inputted data and sends it via the mail() function. I also have some validation techniques that validate the inputs, and I created an array variable $errors to log all of the errors; for example,
if the name was left empty, $errors[]="Name empty";
If the email was left empty, $errors[]="email empty";
and so on..
I was able to report the errors using the following technique:
print '<div id="formfeedback"><h3>Error!</h3><p>The following error(s) has occurred:<br />';
foreach ($errors as $msg) { //prints each error
print " - $msg<br />\n";
} // end of foreach
However, what I want is the following. I want the page to be redirected back to the original form that was used to input the information (I know the exact link location, so i can use a header() or even a <meta=http-equiv=refresh> to bring me back to the form page.
Also, on the form, I want to be able to post the errors above the form in some div (call it div=errors)
Would I be able to do the following?
<div id="errors">
<?php
print 'The following error(s) has occurred:<br />';
foreach ($_REQUEST[$errors] as $msg) { //prints each error
print " - $msg<br />\n";
} // end of foreach
?>
</div>
Thanks a lot!
Amit
I agree with #Fosco. I want to explain a little bit more-
There may be two cases-
1. You are doing raw php
2. You are coding on any php framework like CI or your own.
and this will help to identify error field and change style to make better user response. Also last input data remain as it was.
You are doing raw php
In this case you can receive the input data in same file/page.
I will do a common example later.
You are coding on any php framework like CI or your own.
In this case you load a view file to show the form page and you can pass data to view page/file when you load it.
For both of above case you can do some coding like-
/*
your input validation and verification goes here. where $error is generated too
In addition add some error status in above section,
you can do it in your $error array too. Also you store received data into $data here. index of $data should be similar as (corresponding) HTML input name.
You can do it like below
*/
$error_stat = array();
//if the input field name is "email" and email input data raises any error then
$error_stat['email'] = true;
// same for name
$error_stat['name'] = true;
// and so on
// now decide whether you will back to the form page or send the email and do other tasks
if(count($error_stat)<= 0){
// send email
// do aditional tasks
}
else{
// load the form again if its aframework or the form is in seperate file
// off course send $error,$data and $error_stat to the form page/file
}
// now here is a code segment of form page
<?php if(isset($error) && count($error)>0):?>
<div id="error-msg">
<?php
//display errors here
?>
</div>
<?php endif;?>
<form .... >
<input type="text" name="email" class="<?php echo (isset($error_stat['email'])?'error':'else'); ?>" value="<?php echo $data['email'];?>" />\
<!-- and so on ... -->
The simplest way to do this is to:
// Start the session
session_start();
// Store the errors in the session
$_SESSION['errors'] = $errors;
// Redirect to correct page
header('HTTP/1.1 303 See Other');
header('Location: http://original/page');
exit;
Then, on the form page:
// Start the session
session_start();
// extract the errors
$errors = isset($_SESSION['errors']) ? $_SESSION['errors'] : array();
// Display the form with errors
foreach ($errors as $msg) ... ;
Typically I would have the same page process the input and the submission. If the data was valid, the mail would be sent and the page would notify them of that (or redirect them elsewhere)... if the data was not valid, then the form would appear again and the errors could be displayed, without any fancy redirection.
make sure your session is started at the top of your application
include this basic class
class FormErrors
{
var $handler;
function __construct($fname)
{
$this->handler &= isset($_SESSION[$fname]) $_SESSION[$fname] : ($_SESSION[$fname] = array());
}
public function add($name, $value)
{
$this->handler[$name] = $value;
}
public function remove($name)
{
unset($this->handler[$name]);
}
public function getErrors()
{
return $this->handler;
}
}
so when your processing the errors you can go
if(isset($_POST))
{
$FormErrors = new FormErrors("registration");
if(strlen($_POST['username']) == 0)
{
$FormErrors->add('Username','Please enter a valid username');
}
//And for the rest of your checks
}
then within side your html do
foreach($FormErrors ->getErrors() as $name => $error)
{
echo sprintf("<p title=\"%s\">%s</p>",$name,$error);
}
Should work, and if you want to remove all known errors do
$FormErrors = new FormErrors("registration");
unset($FormErrors->handler,$FormErrors);