PHPMailer exception error - php

I've written my own Code Igniter model for sending emails. All was fine until recently when I started to get this error:
Fatal error: Cannot redeclare class phpmailerException in /home/mysite/public_html/subdir/application/libraries/phpmailer/class.phpmailer.php on line 2319
I'm using:
CodeIgniter 2
PHPMailer 5.1
I've tried the following to resolve it:
Added "$mail->SMTPDebug = 0" to turn off errors.
Added: "$mail->MailerDebug = false;"
Modified the PHPMailer to only show errors when SMTPDebug is turned on.
Looked for and removed any echo statements
Added try / catch blocks Tried adding / removing: $mail = new PHPMailer(true);
Here is my controller method (company/contact) which calls my model (message_model):
function contact()
{
//Do settings.
$this->options->task='email';
$this->options->change = 'sent';
$this->options->form_validation='';
$this->options->page_title='Contact Us';
//Import library
include_once('application/libraries/recaptcha/recaptchalib.php');//Include recaptcha library.
//Keys for recaptcha, stored in mainconfig file.
$this->options->publickey = $this->config->item('recaptcha_public');
$this->options->privatekey = $this->config->item('recaptcha_private');
//Form validation
$this->form_validation->set_error_delimiters('<div class="error">', '</div>');
$this->form_validation->set_rules('name_field','Name of problem','trim|required|min_length[3]|max_length[100]');
$this->form_validation->set_rules('desc_field','Description','trim|required|min_length[10]|max_length[2000]');
$this->form_validation->set_rules('email_field','Your email address','trim|required|valid_email');
$this->form_validation->set_rules('recaptcha_response_field','captcha field','trim|required|callback__check_recaptcha');
//If valid.
if( $this->form_validation->run() )
{
//Set email contents.
$message="This is a message from the contact form on ".$this->config->item('site_name')."<br /><br />";
$message.=convert_nl($this->input->post('desc_field'));
$message.="<br /><br />Reply to this person by clicking this link: ".$this->input->post('name_field')."<br /><br />";
$options = array('host'=>$this->config->item('email_host'),//mail.fixilink.com
'username'=>$this->config->item('email_username'),
'password'=>$this->config->item('email_password'),
'from_name'=>$this->input->post('name_field'),
'to'=>array($this->config->item('email_to')=>$this->config->item('email_to') ),
'cc'=>$this->config->item('email_cc'),
'full_name'=>$this->input->post('name_field'),
'subject'=>'Email from '.$this->config->item('site_name').' visitor: '.$this->input->post('name_field'),
'message'=>$message,
'word_wrap'=>50,
'format'=>$this->config->item('email_format'),
'phpmailer_folder'=>$this->config->item('phpmailer_folder')
);
//Send email using own email class and phpmailer.
$result = $this->message_model->send_email($options);
//Second email to sender
//Set email contents.
$message="Thank you for your enquiry, we aim to get a reply to you within 2 working days. In the meantime, please do follow us on www.facebook.com/autismworksuk";
$options = array('host'=>$this->config->item('email_host'),//mail.fixilink.com
'username'=>$this->config->item('email_username'),
'password'=>$this->config->item('email_password'),
'from_name'=>$this->input->post('name_field'),
'to'=>$this->input->post('email_field'),
'full_name'=>$this->input->post('name_field'),
'subject'=>'Email from '.$this->config->item('site_name'),
'message'=>$message,
'word_wrap'=>50,
'format'=>$this->config->item('email_format'),
'phpmailer_folder'=>$this->config->item('phpmailer_folder')
);
//Send email using own email class and phpmailer.
$result = $this->message_model->send_email($options);
//Set result.
if($result==-1)
$this->session->set_flashdata('result', ucfirst($this->options->task).' was not '.$this->options->change.' because of a database error.');
elseif($result==0)
$this->session->set_flashdata('result', 'No changes were made.');
else
$this->session->set_flashdata('result', ucfirst($this->options->task).' was '.$this->options->change.' successfully.');
//Redirect to completed controller.
redirect('completed');
}
//Validation failed or first time through loop.
$this->load->view('company/contact_view.php',$this->options);
}
Here is my model's method to send the emails. It used to work but without any changes I can think of now I get an exception error:
function send_email($options=array())
{
if(!$this->_required(array('host','username','password','from_name','to','full_name','subject','message'),$options))//check the required options of email and pass aggainst provided $options.
return false;
$options = $this->_default(array('word_wrap'=>50,'format'=>'html','charset'=>'utf-8'),$options);
try
{
if(isset($options['phpmailer_folder']))
require($options['phpmailer_folder']."/class.phpmailer.php");
else
require("application/libraries/phpmailer/class.phpmailer.php");//Typical CI 2.1 folder.
$mail = new PHPMailer();
$mail->MailerDebug = false;
//Set main fields.
$mail->SetLanguage("en", 'phpmailer/language/');
$mail->IsSMTP();// set mailer to use SMTP
$mail->SMTPDebug = 0;
$mail->Host = $options['host'];
$mail->SMTPAuth = TRUE; // turn on SMTP authentication
$mail->Username = $options['username'];
$mail->Password = $options['password'];
$mail->FromName = $options['from_name'];//WHo is the email from.
$mail->WordWrap = $options['word_wrap'];// Set word wrap to 50 characters default.
$mail->Subject = $options['subject'];
$mail->Body = $options['message'];
$mail->CharSet = $options['charset'];
//From is the username on the server, not sender email.
if(isset($options['from']))
$mail->From = $options['from'];
else
$mail->From = $mail->Username; //Default From email same as smtp user
//Add reply to.
if(isset($options['reply_to']))
$mail->AddReplyTo($options['reply_to'], $options['from']);
if(isset($options['sender']))
$mail->Sender = $options['sender'];
//Add recipients / to field (required)
if(is_array($options['to']))
{
foreach($options['to'] as $to =>$fn)
$mail->AddAddress($to, $fn);
}
else
{
$mail->AddAddress($options['to']); //Email address where you wish to receive/collect those emails.
}
//Add cc to list if exists. Must be an array
if(isset($options['cc']))
{
if(is_array($options['cc']))
{
foreach($options['cc'] as $to =>$fn)
$mail->AddCC($to, $fn);
}
else
{
log_message('debug', '---->CC field must be an array for use with Message_Model.');
}
}
//Add bcc to list if exists. Must be an array
if(isset($options['bcc']))
{
if(is_array($options['bcc']))
{
foreach($options['bcc'] as $to =>$fn)
$mail->AddBCC($to, $fn);
}
else
{
log_message('debug', '---->BCC field must be an array for use with Message_Model.');
}
}
//Alternative text-only body.
if(isset($options['alt_body']))
$mail->AltBody=$options['alt_body'];
else
$mail->AltBody = htmlspecialchars_decode( strip_tags( $options['message'] ),ENT_QUOTES );//Strip out all html and other chars and convert to plain text.
//Plain/html format.
if(isset($options['format']))
{
if($options['format']=='html')
$mail->IsHTML(true); // set email format to HTML
}
//Send email and set result.
$return['message']='';
if(!$mail->Send())
{
$return['message'].= "Message could not be sent.<br />\n";
$return['message'].= "Mailer Error: " . $mail->ErrorInfo."\n";
$return['result'] = 0;
}
else
{
$return['message'].= "Message has been sent successfully.\n";
$return['result'] = 1;
}
}
catch (phpmailerException $e)
{
log_message('error', '---->PHPMailer error: '.$e->errorMessage() );
}
catch (Exception $e)
{
log_message('error', '---->PHPMailer error: '.$e->errorMessage() );
}
return $return;
}

if (!class_exists("phpmailer")) {
require_once('PHPMailer_5.2.2/class.phpmailer.php');
}
This Code will clear this issue 100%..

Basically one of two things is happening:
You are "including" your PHP code twice somewhere, causing the 2nd time to generate the redeclaration error
You are using "phpmailerException" somewhere else, besides your model. Have you tried to do a "find all" in your IDE for ALL calls to "phpmailerException" - perhaps you used this name in another area for another exception?

require_once("class.phpmailer.php") is better.
Mukesh is right that require_once will solve Sift Exchanges answer #1. However, there is not need to check if the class exists as require_once does that.

Related

Send bulk message using php mailer with ajax

I need assistance with sending bulk email.
This is this scanario.
A dropdown contains the categories of emails to be fetched. The selected (value) is then passed through a function that obtains all the emails per the selected value from db. And the emails passed to the mailer's addAddress method.
The sql query works fine but my headers show only the selected value from the network session and not all the returned emails. I am including both php codes and the ajax codes and also the response headers.
PHP block
$accountid = $_POST['accountid'];
$selectedstatus = $_POST['bulkrecipients']; //From dropdown
$emailtype = $_POST['emailtype'];
$subject = sanitize_text($_POST['bulksubject']);
$message = sanitize_text($_POST['bulkmessage']);
//Pass recipientemails to function and extract individual emails.
$getemails = getAllEmailsFromStatus($selectedstatus , $_SESSION['username']);
$name = 'Tester';
$mail = new PHPMailer;
$mail->isSMTP();
$mail->SMTPKeepAlive = true;
$mail->Host = 'smtp.gmail.com';
$mail->SMTPAuth = true;
$mail->Username = "";
$mail->Password = '';
$mail->Port = 465;
$mail->SMTPSecure = "ssl";
$mail->isHTML(true);
$mail->setFrom('testproject222', $name);
$mail->Subject = ("$subject");
$mail->Body = $message;
foreach ($getemails as $row) {
try {
$mail->addAddress($row['email']);
} catch (Exception $ex) {
echo 'Invalid address skipped: ' . htmlspecialchars($row['email']) . '<br>';
continue;
}
try {
if ($mail->send()) {
$status = "success";
$response = "Email is sent";
//Save the contact details to db.
saveAllEmployerEmails($accountid , $subject, emailtype, $message );
} else {
$status = "failed";
$response = 'Something is wrong ' . $mail->ErrorInfo;
}
exit(json_encode(array("status" => $status, "response" => $response)));
} catch (Exception $ex) {
echo 'Mailer Error (' . htmlspecialchars($row['email']) . ') ' . $mail->ErrorInfo . '<br>';
$mail->getSMTPInstance()->reset();
}
$mail->clearAddresses();
$mail->clearAttachments();
}
Ajax
function sendBulk() {
var url = "./inc/emailjobs.php";
var accountid = $("#accountid");
var emailtype = $("#emailtype");
var recipientemails = $("#bulkrecipients");
var bulksubject = $("#bulksubject");
var bulkmessage = $('#' + 'bulkmessage').html( tinymce.get('bulkmessage').getContent() );
if (isNotEmpty(recipientemails) /*&& isNotEmptyTextArea("bulkmessage")*/) {
$.ajax({
url: url,
method: 'POST',
cache: false,
dataType: 'json',
beforeSend: function () {
$('#bulksendbtn').text("Sending...");
},
data: {
accountid: accountid.val(),
emailtype: emailtype.val(),
bulksubject: bulksubject.val(),
bulkrecipients: recipientemails.val(),
bulkmessage: bulkmessage.val()
}
, success: function (response) {
$('#bulkemailForm')[0].reset();
$('.bulksendmessage').text("Emails Sent.");
$('#bulksendbtn').text("Sent");
},
});
}
}
Response Form header data
accountid: 2
emailtype: bulk
bulksubject: Test
bulkrecipients: shortlisted
bulkmessage: <p>Testing... </p>
Instead of the 'shortlisted' for bulkrecipients, I expect the email addresses. I was hoping to see 2 returned emails. The 'shortlisted' is supposed to be used to obtain the emails for that category (shortlisted).
Your code looks generally correct, but this is confusing:
$mail->setFrom('Test', $name);
//$mail->From = ("$email");
$email isn't defined, and Test is not a valid from address. I have a suspicion you're trying to use an arbitrary user-submitted email address as the from address. That will not work with Gmail because Gmail does not allow setting arbitrary from addresses; it will only let you send as the account owner (what you put in Username), or aliases that you preset in gmail settings. If you try to use anything else, it will simply ignore it and use your account address instead. Is this what you meant by "only the selected value from the network session"?
It's entirely reasonable for gmail to do this since almost by definition anything other than your account address is likely to be forgery, and nobody likes that.
If you want to send email where replies will go to a user-submitted address, use your own address in the from address, and use the user-submitted address as a reply-to. See the contact form example provided with PHPMailer for how to do that.

PHPmailer dynamic data to multiple mails?

I am coding on a system where the admin should be able to click a button and send a mail to all users. When i click the a href and redirect with type = 2 it sends the mail to all accounts but the content which is supposed to be dynamic just returns the email of the last user in the array.
<?php
include "core/init.php";
error_reporting(E_ALL);
date_default_timezone_set('Etc/UTC');
require 'phpmailer/PHPMailerAutoload.php';
$mail = new PHPMailer;
$mail->isSMTP();
$mail->SMTPDebug = 0;
$mail->Debugoutput = 'html';
$mail->Host = 'smtprotocl';
$mail->Port = 587;
$mail->SMTPSecure = 'tls';
$mail->SMTPAuth = true;
$mail->Username = "mymail#mail.dk";
$mail->Password = "password";
$mail->CharSet = 'UTF-8';
$mail->setFrom('mymail#mail.dk', 'nameofmailholder');
if ($_GET["type"]) {
if ($_GET["type"] == 2){
$confirmede = 0;
$getVendorc = $db->prepare("SELECT * FROM db");
$getVendorc->execute();
$vresultc = $getVendorc->get_result();
$getVendorc->store_result();
while ($rowing = $vresultc->fetch_assoc()) {
$removeSpace = explode(" ", decrypt($rowing["email"]));
$Uemail = implode("+", $removeSpace);
$mail->addReplyTo($Uemail);
$mail->addAddress($Uemail);
}
$mail->isHTML(true);
$mail->Subject = 'welcome';
$mail->Body = '<button >Bekræft email</button>';
} else {
urlLocation("index");
}
}
$mail->AltBody = 'aa';
if($mail->send()) {
urlLocation("../../index");
}?>
Either create the email (using PHPMailer functions) and send it INSIDE the loop (which is what you should do), or do the following if you want to send one email to all recipients at once (without revealing emails to anyone, because it's BCC). I don't recommend this, but I suppose it could work.
$mail->addAddress("fake#address.com");
$mail->addBCC($email1, $email2, $email3, $email4);
That should work for sending the same email to multiple recipients, in one email without revealing all of the emails to everyone.
Personally, I use wuMail... It makes using PHPMailer a lot easier, especially with SMTP. Here's my setup, with login details changed obviously... I'll explain how it works below, but you would need to download wuMail (link at bottom) so that the files (for PHPMailer) are referenced correctly by config.php & wuMail.php... The code blocks below are references, but can't be used standalone without the rest of the wuMail download.
The first thing that happens is that we set the system defaults... These are used in case certain email parameters are not supplied to wuMail(). This is a fail safe, in case you want a default to address in case part of the system attempts to use wuMail() without supplying to address.. This would let you discover those types of bugs quickly.
The following is the code in config.php... You require config.php in any file that you want to use wuMail() function in (to send mail). Config will set the settings in advance & then bring in the wuMail.php file itself. So don't include the wuMail.php file, just config.php!
<?php
/*
NOTE: These settings have been prepared by
WUBUR.COM / WUBUR LLC / BILLY LOWERY / WILL PASSMORE
*/
# DO NOT REMOVE:
$wuMail_Config = new stdClass();
//SENDER CONFIG SETTINGS - YOU CAN CHANGE THESE:
// ----> Note: This current configuration has a form sending to the same address each time
// ----> This could obviously be adapted to allow for emails being sent elsewhere
$wuMail_Config->SiteName = 'Wubur.com';
//SERVER CONFIG SETTINGS - YOU CAN CHANGE THESE:
$wuMail_Config->isSMTP = true; // Set mailer to use SMTP (TRUE / FALSE)
$wuMail_Config->Host = 'smtp.gmail.com'; // Specify main and backup SMTP servers
$wuMail_Config->SMTPAuth = true; // Enable SMTP authentication (TRUE / FALSE)
$wuMail_Config->AuthType = 'LOGIN'; // Authentification type... ex: PLAIN, LOGIN
$wuMail_Config->Username = 'USERNAME#gmail.com'; // Only blank for GoDaddy's servers
$wuMail_Config->Password = 'PASSWORD'; // Only blank for GoDaddy's servers
$wuMail_Config->SMTPSecure = 'ssl'; // ('tls', 'ssl' or false)
$wuMail_Config->Port = 465; // TCP port to connect to
$wuMail_Config->Exceptions = true; // true/false, if Exceptions enabled
$wuMail_Config->SMTPDebug = 0; // Enable verbose debug output ~~ must be 0 in production environment
//MESSAGE CONFIG SETTINGS - YOU CAN CHANGE THESE:
$wuMail_Config->DefaultToAddress = 'to#email.com';
$wuMail_Config->DefaultToName = 'To Name';
$wuMail_Config->DefaultCC = false; // no default CC
$wuMail_Config->DefaultBCC = false; // no default BCC
$wuMail_Config->DefaultFromAddress = 'from#email.com';
$wuMail_Config->DefaultFromName = 'From Name';
$wuMail_Config->DefaultReplyAddress = 'replyaddress#email.com';
$wuMail_Config->DefaultReplyName = 'Reply Name';
$wuMail_Config->DefaultSubject = 'Default Subject';
# MESSAGE / HTML VERSION CONFIG SETTINGS - YOU CAN CHANGE THESE. BE CAREFUL:
$wuMail_Config->DefaultMessage = 'Default Message (Message Not Supplied)';
$wuMail_Config->ForceHTML = true; // (recommended: true)
// If set to TRUE, and no HTML version of message is supplied to wuMail function, use the HTML template below...Otherwise use HTML supplied to wuMail function if it is supplied.
// If set to FALSE, and no HTML version of message is supplied to wuMail function, simply display a non-HTML message to recipient. If HTML version is supplied, HTML version will be used instead of template
# DefaultHTML: Simply use {!messageInsert!} to insert the regular non-HTML message into the template. {!siteNameInsert!} will insert the config site name.
$wuMail_Config->DefaultHTML = '
<div>
<center><img style="width:350px; height:auto; margin-bottom:25px;" src="site.com/logo.png" alt="Site Name" /></center>
<div style="width:100%; color:white; background-color:#c02026; font-weight:500; padding:10px;">Important Information</div>
<div style="width:100%; padding:25px; color:black; background-color:#f2f2f2;">
{!messageInsert!}
</div>
</div>
';
# NOTE: The 'HTML' key in the options data array for wuMail can be a template with {!messageInsert!} or {!siteNameInsert!} as variables!
// PHPMailer Path Settings:
$wuMail_Path = ""; // path from root dir for site access
// DO NOT REMOVE:
require $wuMail_Path . "wuMail.php";
?>
The URL & logo image in the template should obviously be updated... This is the default template if someone supplies an email message without the HTML version. This is so every email can use HTML templates when allowed, even if developers don't properly use one in the first place :) System settings for the win!
Next we have wuMail.php itself...
<?php
/*
NOTE: These settings have been prepared by
WUBUR.COM / WUBUR LLC / BILLY LOWERY / WILL PASSMORE
*/
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception;
require $wuMail_Path . 'src/Exception.php';
require $wuMail_Path . 'src/PHPMailer.php';
require $wuMail_Path . 'src/SMTP.php';
function wuMail($data, $multi = false){
global $wuMail_Config;
if(!is_array($data)){
$useDefaults = true;
} else {
$useDefaults = false;
}
$mailSettings = array(
"TOADDRESS" => $wuMail_Config->DefaultToAddress,
"TONAME" => $wuMail_Config->DefaultToName,
"CC" => $wuMail_Config->DefaultCC,
"BCC" => $wuMail_Config->DefaultBCC,
"SUBJECT" => $wuMail_Config->DefaultSubject,
"MESSAGE" => $wuMail_Config->DefaultMessage,
"HTML" => $wuMail_Config->DefaultHTML,
"FROMADDRESS" => $wuMail_Config->DefaultFromAddress,
"FROMNAME" => $wuMail_Config->DefaultFromName,
"REPLYADDRESS" => $wuMail_Config->DefaultReplyAddress,
"REPLYNAME" => $wuMail_Config->DefaultReplyName
);
# NOTES: THE FOLLOWING CAN BE ARRAYS: ToAddress, ToName (arr key must match ToAddress arr), CC, BCC
# IN FUTURE, YOU CAN LINE UP EMAILS TO SEND SEPARATELY BY SIMPLY MAKING MULTIDIMENSIONAL ARRAY OF DATA, AND SETTING PARAM 2 (MULTI) EQUAL TO TRUE IN WUMAIL
if($useDefaults !== true){
$submittedOpts = array();
foreach($data as $submittedOption => $submittedValue){
$submittedOptionUPPER = strtoupper($submittedOption);
$submittedOpts[] = $submittedOptionUPPER;
if(isset($mailSettings[$submittedOptionUPPER])){
$mailSettings[$submittedOptionUPPER] = $data[$submittedOption];
} else {
echo "ERROR: SUBMITTED MAIL OPTION NOT ACCEPTED";
}
}
if(($mailSettings['TOADDRESS'] !== $wuMail_Config->DefaultToAddress) && !in_array('TONAME', $submittedOpts)){ # To address supplied, but no to name supplied
# do not use a toName...
$mailSettings['TONAME'] = false;
}
if(($mailSettings['FROMADDRESS'] !== $wuMail_Config->DefaultFromAddress) && !in_array('FROMNAME', $submittedOpts)){ # From address supplied, but no fromname supplied
$mailSettings['FROMNAME'] = false;
# do not use fromname below, because the supplied from address differs from the default in settings
}
if(($mailSettings['REPLYADDRESS'] !== $wuMail_Config->DefaultFromAddress) && !in_array('REPLYNAME', $submittedOpts)){ # Reply address supplied, but no replyname supplied
$mailSettings['REPLYNAME'] = false;
# do not use replyname below, because the supplied reply address differs from the default in settings
}
} # useDefaults !== true
$mail = new PHPMailer($wuMail_Config->Exceptions);
try {
//Server Settings (from PHPMailer/config.php) - Change in config.php file, not here!
$mail->SMTPDebug = $wuMail_Config->SMTPDebug;
if($wuMail_Config->isSMTP === true){ $mail->isSMTP(); }
$mail->Host = $wuMail_Config->Host;
$mail->SMTPAuth = $wuMail_Config->SMTPAuth;
$mail->AuthType = $wuMail_Config->AuthType;
$mail->Username = $wuMail_Config->Username;
$mail->Password = $wuMail_Config->Password;
$mail->SMTPSecure = $wuMail_Config->SMTPSecure;
$mail->Port = $wuMail_Config->Port;
//Recipients
if($mailSettings['FROMNAME'] !== false){
$mail->setFrom($mailSettings['FROMADDRESS'], $mailSettings['FROMNAME']);
} else {
$mail->setFrom($mailSettings['FROMADDRESS']);
}
if($mailSettings['TONAME'] !== false){
$mail->addAddress($mailSettings['TOADDRESS'], $mailSettings['TONAME']);
} else {
$mail->addAddress($mailSettings['TOADDRESS']);
}
if($mailSettings['REPLYNAME'] !== false){
$mail->addReplyTo($mailSettings['REPLYADDRESS'], $mailSettings['REPLYNAME']);
} else {
$mail->addReplyTo($mailSettings['REPLYADDRESS']);
}
if($mailSettings['REPLYNAME'] !== false){
$mail->addReplyTo($mailSettings['REPLYADDRESS'], $mailSettings['REPLYNAME']);
} else {
$mail->addReplyTo($mailSettings['REPLYADDRESS']);
}
if($mailSettings['CC'] !== false){
$mail->addCC($mailSettings['CC']);
}
if($mailSettings['BCC'] !== false){
$mail->addCC($mailSettings['BCC']);
}
//Attachments
#$mail->addAttachment('/var/tmp/file.tar.gz'); // Add attachments
#$mail->addAttachment('/tmp/image.jpg', 'new.jpg'); // Optional name
if($wuMail_Config->ForceHTML !== true && !in_array("HTML", $submittedOpts)){ # ForceHTML is not enforced, and HTML not submitted.... Use plain text message:
$mailSettings['HTML'] = $mailSettings['MESSAGE'];
$mail->isHTML(false);
} else if($wuMail_Config->ForceHTML === true && !in_array("HTML", $submittedOpts)){ # ForceHTML is true, and wuMail received no HTML template to use: ... use default:
$templateVarFind = array("{!messageInsert!}", "{!siteNameInsert!}");
$templateVars = array($mailSettings['MESSAGE'], $wuMail_Config->SiteName);
$mailSettings['HTML'] = str_replace($templateVarFind, $templateVars, $mailSettings['HTML']); // insert variables into default wuMail HTML template
$mail->isHTML(true);
} else {
$mail->isHTML(true);
}
$mail->Subject = $mailSettings['SUBJECT'];
if($mailSettings['HTML'] == $mailSettings['MESSAGE']){
$mail->Body = $mailSettings['MESSAGE'];
} else {
$mail->Body = $mailSettings['HTML'];
$mail->AltBody = $mailSettings['MESSAGE'];
}
$mail->send();
return true;
} catch (Exception $e) {
return 'Message could not be sent. Mailer Error: ' . $mail->ErrorInfo;
}
} // wuMail end
?>
Finally, after all of this is setup in config.php and wuMail.php, we can begin to use the wuMail() function
require_once "wuMail/config.php";
$mailData = array(
"TOADDRESS" => "userToSendTo#email.com",
"TONAME" => "First Name",
"SUBJECT" => "Registration",
"MESSAGE" => "Hello this is a message",
"HTML" => "Hello this is a <strong>message</strong>",
"FROMADDRESS" => "from#website.com",
"FROMNAME" => "Admin Mail",
"REPLYADDRESS" => "donotreply#email.com"
);
if(wuMail($mailData) === true){
// mail sent
} else {
// mail not successful, change SMTPDebug to = 4 in config.php to bug test
}
As you can see, not all parameters have to be supplied...In the $mailData array you can supply:
$mailSettings = array(
"TOADDRESS" => $wuMail_Config->DefaultToAddress,
"TONAME" => $wuMail_Config->DefaultToName,
"CC" => $wuMail_Config->DefaultCC,
"BCC" => $wuMail_Config->DefaultBCC,
"SUBJECT" => $wuMail_Config->DefaultSubject,
"MESSAGE" => $wuMail_Config->DefaultMessage,
"HTML" => $wuMail_Config->DefaultHTML,
"FROMADDRESS" => $wuMail_Config->DefaultFromAddress,
"FROMNAME" => $wuMail_Config->DefaultFromName,
"REPLYADDRESS" => $wuMail_Config->DefaultReplyAddress,
"REPLYNAME" => $wuMail_Config->DefaultReplyName
);
As you can see, there are quite a few custom parameters you can enter into wuMail($data) when you want to send mail. If you leave any out, it defaults to the settings in config.php for that specific setting! The reply address/name & to address/name & from name/address all are dynamic so that if you supply a custom address (but no name), it will not mismatch the custom email with the default name. It will simply send it with that information as blank.
You can download wuMail if you want it at:
http://nerdi.org/stackoverflow/wuMail.zip
wuMail comes with PHPMailer packaged in and is 100% free... obviously :)

PHPMailer Fallback Validation

i'm needing some help with this PHPmailer config code to provide simple form validation in case for any reason the Jquery validation fails or if Javascript is disabled.
the SUCCESS part of this does work!
meaning, the form submission sends both emails as expected, & shows "Email sent!" to the submitter.
the ERROR part of this does not work!
meaning, if any field is left empty, the form submission does not send any emails, and does not show anything but a blank page to the submitter.
EDIT: correction - i just did another round of testing & discovered that the 1st Catch is catching if the Email field is empty. but that's it. i would rather the 2nd catch catch that, along with the other required fields. that must be something built-in to PHPMailer. /edit.
1) i want to have the custom error message in the 2nd catch display to the submitter if the form fields that i want to be required are empty. In this example, I'd like to require the "name" & "email" fields (more in real form) but not the "message" field.
somebody suggested i use the function validateEmpty code you see below the catches, but i can't get it to work. do i have it in the wrong placement within the script or doing something else wrong with it?
2) it looks to me like this function validateEmpty part is just for the "name" field, do i have to duplicate it for the "email" & any other required fields? or is there a better way to just add which form fields i want as "required" to this one function piece?
3) it's also been suggested that i log any error messages using use error_log(). how do i do that? is that what produces the text file of error messages i've seen elsewhere in the ftp directory?
4) someone also suggested using an $error & $success flag. what is that & how do i do it if it's different than doing what i've got going on here?
5) lastly, i can easily test the 2nd Catch by just submitting the form with empty fields. i'm not sure how i can test the 1st Catch; is that possible or even worth doing?
<?php
if (isset($_POST['submit'])) {
date_default_timezone_set('US/Central');
require 'PHPMailer-5.2.26/PHPMailerAutoload.php';
function sendemail(
$SK_emailTo,
$SK_emailSubject,
$SK_emailBody
) {
$mail = new PHPMailer(true);
$mail->setFrom('myEmail#gmail.com', 'My Name');
$mail->addReplyTo($_POST['email'], $_POST['name']);
$mail->addAddress($SK_emailTo);
$mail->Subject = $SK_emailSubject;
$mail->Body = $SK_emailBody;
$mail->isHTML(true);
$mail->isSMTP();
$mail->Host = 'smtp.gmail.com';
$mail->SMTPAuth = true;
$mail->SMTPSecure = 'tls';
$mail->Port = 587;
$mail->Username = 'myEmail#gmail.com';
$mail->Password = 'myPwd';
return $mail->send();
} //end function sendemail
$name = $_POST['name'];
$email = $_POST['email'];
$message = $_POST['message'];
try {
sendemail(
'myEmail#address.com',
'First email subject',
'Form results to me...
<br><br>'.$message
);
sendemail(
$email,
'Second email subject',
'Confirmation email to person who submitted the form...
<br><br>'.$message
);
echo 'Email sent!';
} //end try
catch (phpmailerException $e) { //catches PHPMailer errors
echo 'There is a problem; the message did NOT send. Please go back and check that you have filled in all the required fields and there are no typos in your email address.';
echo $e->errorMessage();
}
catch (Exception $e) { //catches validation errors
echo 'There is a problem; the message did NOT send. Please either go back and try again or contact us at email#address.com';
echo $e->getMessage();
}
function validateEmpty($string, $name = 'name') {
$string = trim($string);
if ($string == '') {
throw new Exception(sprintf('%s is empty.', $name));
}
}
} //end if submit
?>
thank you for your time & expertise!
PS: yes, this is a duplication of another post that i think got so confusing people stopped helping on it... Form to Email PHP Validation fallback using PHPMailer

Form to Email PHP Validation fallback using PHPMailer

i have a basic contact form on a website. i need to send the form results to 2 email addresses... 1) me, & 2) a confirmation to the person who submitted the form. the form results sent to the submitter has a different message in it.
i plan to add jQuery validation & Ajax but first i want to get the PHP to work. so i don't think i need a lot of PHP validation, just a basic - if critical fields are empty, then error message, as a fallback.
i'm using PHPMailer but unfortunately their documentation is sorely lacking for someone of my lack-of-php skills. but after much google'ing, i've been able to piece together something that mostly works. here is my code utilizing a small form (more fields to come later).
this DOES send the form to both email addresses - great!
the part i'm having trouble with is the validation & error/success messages.
if i just use the return $mail->send(); at the end of the function sendemail section, it sends fine. but if i try to submit the form without anything in the fields, nothing happens. so i tried adding this if(!$mail->send()) {...else...} piece i found somewhere, and it also works with valid form info, but not if empty.
so, what should i use instead of this? or would it be something different to the end if/else part?
<?php
if (isset($_POST['submit'])) {
date_default_timezone_set('US/Central');
require 'PHPMailer-5.2.26/PHPMailerAutoload.php';
function sendemail(
$SK_emailTo,
$SK_emailSubject,
$SK_emailBody
) {
$mail = new PHPMailer;
$mail->setFrom('myEmail#gmail.com', 'My Name');
$mail->addReplyTo($_POST['email'], $_POST['name']);
$mail->addAddress($SK_emailTo);
$mail->Subject = $SK_emailSubject;
$mail->Body = $SK_emailBody;
$mail->isHTML(true);
$mail->isSMTP();
$mail->Host = 'smtp.gmail.com';
$mail->SMTPAuth = true;
$mail->SMTPSecure = 'tls';
$mail->Port = 587;
$mail->Username = 'myEmail#gmail.com';
$mail->Password = 'myPwd';
//return $mail->send(); //this works by itself, without IF/ELSE, but doesn't return error if empty form fields
if(!$mail->send()) {
return 'There is a problem' . $mail->ErrorInfo;
}else{
return 'ok'; // this works but i don't know why
}
} //end function sendemail
// form fields to variables
$name = $_POST['name'];
$email = $_POST['email'];
$message = $_POST['message'];
// from function sendmail to ASSIGN VALUES to...
/* $SK_emailTo,
SK_emailSubject,
$SK_emailBody */
if (sendemail(
'myEmail#address.com',
'First email subject',
'Form results to me...
<br><br>'.$message
)) {
sendemail(
$email,
'Second email subject',
'Confirmation email to person who submitted the form...
<br><br>'.$message
);
$msg = 'Email sent!';
} else {
$msg = 'Email failed!' . $mail->ErrorInfo;
}
} //end if submit
?>
as a sidenote, why does the return 'ok'; work? what does the 'ok' part attach to?
thanks!
//////////////////////// EDIT: NEW INFO BUT STILL NOT SOLVED ////////////////////////
based on the suggestions & edits by Mauro below (and in that posts comments), here is where i'm at now...
<?php
if (isset($_POST['submit'])) {
date_default_timezone_set('US/Central');
require 'PHPMailer-5.2.26/PHPMailerAutoload.php';
function sendemail(
$SK_emailTo,
$SK_emailSubject,
$SK_emailBody
) {
$mail = new PHPMailer(true);
$mail->setFrom('myEmail#gmail.com', 'My Name');
$mail->addReplyTo($_POST['email'], $_POST['name']);
$mail->addAddress($SK_emailTo);
$mail->Subject = $SK_emailSubject;
$mail->Body = $SK_emailBody;
$mail->isHTML(true);
$mail->isSMTP();
$mail->Host = 'smtp.gmail.com';
$mail->SMTPAuth = true;
$mail->SMTPSecure = 'tls';
$mail->Port = 587;
$mail->Username = 'myEmail#gmail.com';
$mail->Password = 'myPwd';
return $mail->send();
} //end function sendemail
$name = $_POST['name'];
$email = $_POST['email'];
$message = $_POST['message'];
try {
sendemail(
'myEmail#address.com',
'First email subject',
'Form results to me...
<br><br>'.$message
);
sendemail(
$email,
'Second email subject',
'Confirmation email to person who submitted the form...
<br><br>'.$message
);
echo 'Email sent!';
} //end try
catch (phpmailerException $e) { //catches PHPMailer errors
echo 'There is a problem; the message did NOT send. Please go back and check that you have filled in all the required fields and there are no typos in your email address.';
echo $e->errorMessage();
}
catch (Exception $e) { //catches validation errors
echo 'There is a problem; the message did NOT send. Please either go back and try again or contact us at email#address.com';
echo $e->getMessage();
}
function validateEmpty($string, $name = 'name') {
$string = trim($string);
if ($string == '') {
throw new Exception(sprintf('%s is empty.', $name));
}
}
} //end if submit
?>
STILL...
1) Mauro suggested i log the error message using use error_log(). how do i do that? is that what produces the text file of error messages in the ftp directory?
2) Mauro also suggested using an $error & $success flag. what is that & how do i do it?
3) i want to have the custom error message in the above catch if the "name" &/or "email" fields (& possibly others) are simply empty. Mauro wrote the function validateEmpty code above, but i can't get it to work. do i have it in the wrong placement within the script or doing something else wrong with it?
3b) it looks to me like this function is just for the "name" field, do i have to duplicate it for the "email" field?
PLEASE REMEMBER...
i want to be able to have a SIMPLE validation here as a fallback in case Javascript/Jquery isn't working for some reason.
also note that the above DOES "send" the email correctly; so am now just trying to get the validation & error message to work right.
thank you for your time & expertise!
tl;dr: both statements evaluate to true. It's better to return true or false instead of strings and handle the message later.
First I'll take care of your question, then I'll make some suggestions on good practices.
When you use return x; in PHP and most languages, you're "sending" x back to where you called the function. So, when your code is executed it will be read as:
if('ok')
or
if ('Error info...')
PHP evaluates the condition on an if statement (this is the part between parenthesis) as true or false by converting it to the boolean type. The string to boolean conversion in PHP is basically as follows: any non-empty string evaluates as TRUE (follow the link, check first table, last column).
So, your function is returning 'ok' if it succeeds, 'Error info...' if it fails, these are both non-empty strings and thereof evaluated as true, so no matter if the first email sending attempt went well, your script will try to send the second one, and will always set $msg to 'Email sent!'.
Here's some advice on how to fix your script so it works (and looks) better:
As #Matt suggested it's always best to validate the data by yourself instead of relying on PHPMailer to do so. Despite PHPMailer will return an error if the destination address is invalid, it's a good practice not to even call the library if the email is not valid. So:
First, validate the data using javascript, so your user get's instant feedback.
Then, validate it using PHP (maybe create a new validate() function that may use filter_var() to validate emails.
Last, send the email only if the previous two were successful.
To follow your chain of thought, you should be evaluating if the string returned by sendemail() equals to 'ok' or not:
if (sendemail(...) == 'ok')
But, instead of evaluating two different strings ('ok' or 'Error info...') it's better if the function returned boolean values instead, and since PHPMailer's send() already does, just keep it as you have it commented:
return $mail->send()
Your last line is using $mail, a variable that you declared inside a function and you never made global, so it won't be available at that point and since you're trying to get a property (ErrorInfo) you'll be firing two PHP notices: Undefined variable and Trying to get a property from a non-object. You COULD just add global $mail at the top of the function and that will make it globally available (outside your function's scope) but this is considered a bad practice since in large pieces of code you might get confused.
Instead, a neater way of firing the error would be to throw/catch an exception:
function sendemail(...) {
// ... PHPMailer config ...
if ($mail->send()) {
return true;
} else {
throw Exception('Error: ' + $mail->ErrorInfo);
}
}
// later...
try {
sendemail()
$msg = 'Email sent!';
} catch (Exception $e) {
$msg = 'Email failed!' . $e->getMessage();
}
Here, if there's a problem with the emails sending, your function will throw a generic exception and the catch part will be executed.
EVEN BETTER
If you initialize PHPMailer like this:
$mail = new PHPMailer(true); // note the parameter set to true.
It will throw an exception by itself if it fails to send the email and you'll be able to catch the exception:
function sendemail(...) {
$mail = PHPMailer(true); // this line
// ... PHPMailer config ...
return $mail->send(); // just to return something, we aren't really using this value anymore.
}
// later...
try {
sendemail(...)
$msg = 'Email sent!';
} catch (phpmailerException $e) {
echo $e->errorMessage(); // Catch PHPMailer exceptions (email sending failure)
} catch (Exception $e) {
echo $e->getMessage(); // Boring error messages from anything else!
}
Never forget to read the docs!

phpmailer error Could not instantiate mail function on WINDOWS server

I have this weird error coming up from phpmailer (Version: 5.1 ):
exception 'phpmailerException' with message 'Could not instantiate mail function.' in C:\Inetpub\vhosts\mydomain\httpdocs\myscript\protected\components\phpmailer\class.phpmailer.php:687 Stack trace: #0 C:\Inetpub\vhosts\mydomain\httpdocs\myscript\protected\components\phpmailer\class.phpmailer.php(578): PHPMailer->MailSend('Date: Wed, 2 Oc...', '--b1_3c2b33630c...')
FYI: I am trying to send a zip file that's around 4.5MB big. But before that the script generates around 50 PDFs and adds them/creates the zip file which then gets attached to a phpmailer object and sent. (I am not using SMTP).
I know this has been asked before.. but the solutions I have found are all based on linux server involving increasing the limit on postfix.
But how do I solve this issue if the site is hosted on a windows machine ? I have plesk control panel.
Thanks in advance for your help.
[EDIT]
Here's the code snippet just incase it helps:
foreach($vars as $PDFKEY)
{
if($PDFKEY != null)
{
if((int)$PDFKEY > 0 )
{
$filename = $this->CreatePDF($PDFKEY);
$emailarr[$PDFKEY['email']][] = $filename;
$emailIdarr[$company->email][] = $PDFKEY['email'];
}
}
}
sleep(20);
//print_r($emailarr);die;
$emailTemplate = Yii::app()->params['EmailTemplate'];
$body = file_get_contents($emailTemplate);
$body = eregi_replace("[\]",'',$body);
try
{
$mail = new PHPMailer(true);
if(strtolower(Yii::app()->params['SMTPStatus']) == "enabled")
{
$mail->IsSMTP(); // telling the class to use SMTP
$mail->SMTPKeepAlive = true; // SMTP connection will not close after each email sent
$mail->Host = Yii::app()->params['SMTPHost']; // sets the SMTP server
$mail->Port = Yii::app()->params['SMTPPort']; // set the SMTP port for the GMAIL server
if(strtolower(Yii::app()->params['SMTPAuthStatus']) == "enabled")
{
$mail->SMTPAuth = true; // enable SMTP authentication
$mail->Username = Yii::app()->params['SMTPUsername']; // SMTP account username
$mail->Password = Yii::app()->params['SMTPPassword']; // SMTP account password
}
}
$mail->SetFrom(Yii::app()->params['EmailSendFrom']);
$mail->AddReplyTo(Yii::app()->params['EmailSendFrom']);
$mail->Subject = Yii::app()->params['EmailSubject'];;
$savePath = Yii::app()->params['PdfSavePath'];
$mail->AddBCC(trim(Yii::app()->params['EmailBCC']));
$b = true;
$toEmailAdded = array();
$ccEmailAdded = array();
$companyCCEmailAdded = array();
foreach($emailarr as $email=>$attachmentArr )
{
try
{
if(!in_array($email, $toEmailAdded))
{
$toEmailAdded[] = $email;
$mail->AddAddress($email);
}
if(isset($_POST['emailcc']) && strlen($_POST['emailcc']) > 0)
{
if(!in_array($_POST['emailcc'], $ccEmailAdded))
{
$ccEmailAdded[] = trim($_POST['emailcc']);
$mail->AddCC(trim($_POST['emailcc']));
}
}
$companycc = trim($emailNamearr[$email]['companyccemail']);
if(isset($companycc) && strlen($companycc) > 0)
{
foreach(explode(',',trim($companycc)) as $cc)
{
if(!in_array($cc, $companyCCEmailAdded))
{
$companyCCEmailAdded[] = trim($cc);
$mail->AddCC(trim($cc));
}
}
}
if(count($attachmentArr) > 1)
{
$zipFileName = "Archieve-".uniqid().".zip";
if($this->create_zip($attachmentArr, $zipFileName, true)) {
$mail->AddAttachment($SavePath.$zipFileName); // attachment
sleep(20);
}
} else
{
foreach($attachmentArr as $attachment)
{
$mail->AddAttachment($SavePath.$attachment); // attachment
}
}
$msgbody = str_replace("<%EMAILSENTDATE%>", date('d/m/Y', strtotime($emailNamearr[$email]['serviced'])) , $body );
if(isset($emailNamearr[$email]))
{
$msgbody = str_replace("<%CLIENTNAME%>", "for ".$emailNamearr[$email]['company'] , $msgbody );
}
else $msgbody = str_replace("<%CLIENTNAME%>", "" , $msgbody );
$mail->MsgHTML($msgbody);
try
{
$mail->Send();
}catch(Exception $e)
{
echo "<br/><br/>$e<br/><br/>".$e;die;
}
//echo "$email <br/>";
$mail->ClearAddresses();
$mail->ClearAttachments();
$mail->ClearCCs();
} catch (Exception $e) {
echo $e->getMessage(); //Boring error messages from anything else!
$b = false;
}
}
}
After tearing out quite a bit of hair on my head I think I kind of sort out the issue. Here's what I did (in case anyone else is facing the same problem )
Under IIS->My Website->error pages->Edit Features Settings By default Detailed errors for local request is selected for security purposes.
This threw the 500 error but the actual cause was hidden. By changing it to "Detailed errors" the actual error was revealed which was :
"FastCGI process exceeded" I believe by default it's 30 secs.
So even though I've max_execution_limit = 300 the process was getting stopped/failed because of the php-cgi.exe 's execution time limit.
To solve this:
edit %windir%\system32\inetsrv\config\applicationHost.config file to extend the php-cgi.exe execution time limit. set activityTimeout:3600 and requestTimeout:3600 .. i set 3600 to be on safe side and because i could.
And then the application ran just fine.
Hope this helps saving the hair on head for someone.
I think:
Yii::app()->params['SMTPStatus'] is not 'enabled'
so phpmailer uses php native mail function witch, I think, is not configured in your php.ini
Hope this helps

Categories