Fatal error: Call to undefined method stdClass::AddAddress() in PHP mailer - php

I'm trying to send an e-mail to multiple e-mail address in my database. Here is my current code.I need to have them query my database and send the e-mail to each e-mail address.It is working but email was send to the first e-mail address only, and got an error "Fatal error: Call to undefined method stdClass::AddAddress()".Where am I going wrong here?
<?php
$elist = $database->getRows("SELECT * FROM `emails`");
foreach($elist as $emails){
$frm = 'test#gmail.com';
$sub = 'Weekly Work Report';
ob_start();
include_once('mail_content.php');
$mail_body = ob_get_contents();
ob_end_clean();
$to = $emails['email'];
$mailstatus = lm_mail('1', '2', $to, '3', $frm, 'HR', $sub, $mail_body);
if ($mailstatus == 'ok') {
$response->redirect('index.php?com_route=user_report');
} else {
echo $mailstatus;
}
}
?>
function lm_mail($head_mid='',$head_mname='',$to_mid ,$to_mname='',$reply_mid,$reply_mname='',$subject,$body,$attachments='')
{
include_once 'phpmailer/mail_config.php';
if(SMTP_mail)
{
// Send SMTP Mails
$mail->From =$head_mid ; // From Mail id
$mail->FromName = $head_mname; // From Name
$mail->AddAddress($to_mid,$to_mname); // To Address
$mail->AddReplyTo($reply_mid,$reply_mname); // From Address
$mail->Subject=$subject;
$mail->Body = $mail_body.$body; //HTML Body
$mail->AltBody = "This is the body when user views in plain text format"; //Text Body
if(!$mail->Send())
{
return $mail->ErrorInfo;
}
else
{
return 'ok';
}
}
else
{
$mail = new PHPMailer(); // defaults to using php "mail()"
$mail->AddReplyTo($reply_mid,$reply_mname); // Sender address
$mail->AddReplyTo($reply_mid,$reply_mname); // replay to address
$address = $to_mid; // to addtesas
$mail->AddAddress($address, $to_mname);
$mail->Subject = $subject;
$mail->AltBody = "To view the message, please use an HTML compatible email viewer!"; // optional, comment out and test
$mail->MsgHTML($mail_body.$body);
if(!$mail->Send())
{
return $mail->ErrorInfo;
}
else { return 'ok'; }
}
}

In the first conditional of the lm_mail function call there is no object being instantiated.
if(SMTP_mail)
{
// No $mail object?
// Send SMTP Mails
$mail->From =$head_mid ; // From Mail id
Try adding:
if(SMTP_mail)
{
$mail = new PHPMailer(); // create a new object
$mail->IsSMTP(); // enable SMTP
// Have to manually set language if PHPMailer can't determine
$mail->SetLanguage("en", 'includes/phpMailer/language/');

I'm guessing you are using SMTP, because I don't see where $mail comes from.
Since one email is sending, my guess is that phpmailer/mail_config.php sets up a $mail object and sets the SMTP_mail constant, and then it goes out of scope after the first function call and the file is only included once so it doesn't get defined again.
After that it wasn't defined as a PHPMailer object, so it is cast as a stdClass when you do the object assignment $mail->From = $head_mid.
Try taking the code out of mail_config.php and replicating it in your send function, or add a function to mail_config.php that provides a factory to getting a PHPMailer object that is configured for your needs.

Related

Send multiple email address using phpmailer function

I have a problem sending multiple email addresses functions. If I send a single email address, I can work. If I send multiple emails to the receiver, they cannot receive my message. I am using the PHPMailer function to do the email function with XAMPP. I am using the PHP array function to put the receiver's address in the array and use the while function to loop the receiver address to send it.
Below is my coding:
$address = array('st9overfindsolution#gmail','st7overfindsolution#gmail');
require 'class/class.phpmailer.php';
$mail = new PHPMailer(true);
$mail->IsSMTP();
$mail->Host = 'smtp.gmail.com';
// $mail->SMTPDebug = 1;
$mail->Port = 465;
$mail->SMTPAuth = true;
$mail->Username = 'example#gmail.com';
$mail->Password = '1233aqqq';
$mail->SMTPSecure = 'ssl';
$mail->From = $_POST["email"];
$mail->FromName = $_POST["name"];
$mail->AddCC($_POST["email"], $_POST["name"]);
$mail->WordWrap = 50;
$mail->IsHTML(true);
$mail->Subject = $_POST["subject"];
$mail->Body = $_POST["message"];
while(list ($key, $val) = each($address)){
$mail->AddAddress($val);
}
What I've tried?
1.I put all receiver email addresses in the array $address = array('st9overfindsolution#gmail','st7overfindsolution#gmail'); and use below while function code, but cannot work.
2.If send single email address without using while function, just can work, like below coding:
Hope someone can guide me on how to solve this problem. Thanks.
i have created new function named "sendmyemail" and inserted the code inside this function, so you can sent multiple emails by calling this function with email address.
<?php
/**
* This example shows sending a message using a local sendmail binary.
*/
//Import the PHPMailer class into the global namespace
use PHPMailer\PHPMailer\PHPMailer;
require '../vendor/autoload.php';
function sendmyemail($whotoEmail){
//Create a new PHPMailer instance
$mail = new PHPMailer();
//Set PHPMailer to use the sendmail transport
$mail->isSendmail();
//Set who the message is to be sent from
$mail->setFrom('from#example.com', 'First Last');
//Set who the message is to be sent to
$mail->addAddress($whotoEmail);
//Set the subject line
$mail->Subject = 'PHPMailer sendmail test';
//Read an HTML message body from an external file, convert referenced images to
embedded,
//convert HTML into a basic plain-text alternative body
$mail->msgHTML(file_get_contents('contents.html'), __DIR__);
//Replace the plain text body with one created manually
$mail->AltBody = 'This is a plain-text message body';
//Attach an image file
$mail->addAttachment('images/phpmailer_mini.png');
//send the message, check for errors
if (!$mail->send()) {
echo 'Mailer Error: ' . $mail->ErrorInfo;
} else {
echo 'Message sent to '.$whotoEmail.'!';
}
}
sendmyemail('abcduser#gmail.com');
sendmyemail('efguser#gmail.com');
sendmyemail('hijkuser#gmail.com');
sendmyemail('lmnouser#gmail.com');

MVC PHPMailer flow

I would like to use PHPMailer in my MVC site but the view content doesn't come for the $emailTemplate variable. This is my own MVC. The problem starts here:
$emailTemplate = $this->view('emails/expirityRemainder'); Could somebody tell me how to manage that change?
If I will do that everything works fine, but I need to load different views:
$emailTemplate = 'The email body';
Here is my controller:
<?php
class Emails extends Controller{
//Send email to remamber the expirity date
public function sendReinder($data){
$emailTemplate = $this->view('emails/expirityRemainder');
$data=[
'recipient'=>'anEmail#yahoo.com',
'subject'=>'TheSubject',
'htmlBody'=>$emailTemplate,
'nonHtmlBody'=>'This is the body in plain text for non-HTML mail clients',
'sentMessage'=>'Message has been sent'
];
$email = new Email();
$email->sendMail($data);
}
}
The 'expirityRemainder.php' file contains a text:
Here will be the HTML code formatted
The PHPMailer file is inside of that libraries/PHPMailer folder.
The Email class send the email (on my server the below blank details are filled):
<?php
// Import PHPMailer classes into the global namespace
// These must be at the top of your script, not inside a function
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception;
require 'src/Exception.php';
require 'src/PHPMailer.php';
require 'src/SMTP.php';
class Email{
public function sendMail($data){
$mail = new PHPMailer(true); // Passing `true` enables exceptions
try {
//Server settings
$mail->SMTPDebug = 0; // Enable verbose debug output
$mail->isSMTP(); // Set mailer to use SMTP
$mail->Host = ''; // Specify main and backup SMTP servers smtp.topwebdeveloper.co.uk
$mail->SMTPAuth = true; // Enable SMTP authentication
$mail->Username = ''; // SMTP username
$mail->Password = ''; // SMTP password
$mail->SMTPSecure = 'tls'; // Enable TLS encryption, `ssl` also accepted
$mail->Port = 587; // TCP port to connect to 465 25 587
//Recipients
$mail->setFrom('', '');
//$mail->addAddress('', ''); // Add a recipient
//$mail->addAddress(''); // Name is optional
$mail->addAddress($data['recipient'], 'Nameee');
$mail->addReplyTo('', 'Information');
//Content
$mail->isHTML(true); // Set email format to HTML
$mail->Subject = 'Here is the subject';
$mail->Body = $data['htmlBody'];
$mail->AltBody = 'This is the body in plain text for non-HTML mail clients';
$mail->send();
echo 'Message has been sent';
print_r($data);
} catch (Exception $e) {
echo 'Message could not be sent. Mailer Error: ', $mail->ErrorInfo;
print_r($data);
}
}
}
?>
This is the output:
Here will be the html code formatted
Message could not be sent.
Mailer Error: Message body emptyArray ( [recipient] => anEmail#yahoo.com [subject] => TheSubject [htmlBody] => [nonHtmlBody] => This is the body in plain text for non-HTML mail clients [sentMessage] => Message has been sent )`
I think the view content is expected to not be a string... The $data['htmlBody']inside if sendMail($data) did not receive the view content.
The view method works perfect for my MVC, except that situation when I try to load an mail text:
<?php
class Controller{
public function model($model){
require_once '../app/models/'.$model.'.php';
return new $model();
}
public function view($view, $data=[]){
if(file_exists('../app/views/'.$view.'.php')){
require_once '../app/views/'.$view.'.php';
} else {
die('vien not exists');
}
}
}
I created a new method but still not working:
<?php
public function loadEmailView($view, $data=[]){
if(file_exists('../app/views/'.$view.'.php')){
//ob_start();
//include('../app/views/'.$view.'.php');
//$file = ob_end_flush();
//echo file_get_contents('../app/views/'.$view.'.php');
//$data['htmlBody'] = require_once '../app/views/'.$view.'.php';
} else {
die('Email vien not exists');
}
}
None of the 3 above solutions not add the view content to my htmlBody variable:
<?php
class Emails extends Controller{
//Send email to remamber the expirity date
public function sendReinder($data){
$emailTemplate = $this->loadEmailView('emails/expirityRemainder');
//$emailTemplate = file_get_contents('email_template.php');
$data=[
'recipient'=>'anEmail#yahoo.com',
'subject'=>'TheSubject',
'htmlBody'=>$emailTemplate,
'nonHtmlBody'=>'This is the body in plain text for non-HTML mail clients',
'sentMessage'=>'Message has been sent'
];
$email = new Email();
$email->sendMail($data);
}
}
Thank you!

Could not instantiate mail function - Codeigniter and PHPMailer

I want to send an email using PHPMailer and I'm using Codeigniter
public function check_email(){
$response = array('error' => false);
$email = $this->input->post('email');
$check_email = $this->fp_m->check_email($email);
if($check_email){
$this->load->library('phpmailer_library');
$mail = $this->phpmailer_library->load();
$mail->setFrom('from#example.com', 'Mailer');
$mail->addAddress($email);
$mail->isHTML(true);
$mail->Subject = "Reset Password";
$mail->Body = "
Hi,<br><br>
In order to reset your password, please click on the link below:<br>
<a href='
http://example.com/resetPassword.php?email=$email
'>http://example.com/resetPassword.php?email=$email</a><br><br>
Kind Regards,<br>
Kokushime
";
if($mail->send()){
$response['error'] = false;
$response['message'] = "The Email Sent. Please Chect Your Inbox";
}else{
$response['error'] = true;
$response['message'] = "There's Something wrong while sending the message". $mail->ErrorInfo;
;
}
}else{
$response['error'] = true;
$response['message'] = 'The email that you entered is not associated with admin account';
}
echo json_encode($response);
}
But it gives me error Could not instantiate mail function.
BTW, I'm not using SMTP because i don't need that..
I hope that you can help me :)
You did not include your PHPMailer config. Since you are not using SMTP do you have this set?
$mail->isSendmail();
Also, assuming you are using CI3 it would probably be easier if you installed PHPMailer with composer and had it autoload.
I just tested this and it works fine using sendmail.
<?php
if (!defined('BASEPATH')) exit('No direct script access allowed');
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception;
class Phpmailer_test extends CI_Controller
{
public function __construct()
{
parent::__construct();
}
public function index()
{
$mail = new PHPMailer(true); // Passing `true` enables exceptions
try {
//Server settings
$mail->isSendmail();
//Recipients
$mail->setFrom('from#example.com', 'Mailer');
$mail->addAddress('joe#example.net', 'Joe User'); // Add a recipient
$mail->addReplyTo('info#example.com', 'Information');
//Content
$mail->isHTML(true); // Set email format to HTML
$mail->Subject = 'Here is the subject';
$mail->Body = 'This is the HTML message body <b>in bold!</b>';
$mail->AltBody = 'This is the body in plain text for non-HTML mail clients';
$mail->send();
echo 'Message has been sent';
} catch (Exception $e) {
echo 'Message could not be sent. Mailer Error: ', $mail->ErrorInfo;
}
}
}

Sending multiple emails with PHPmailer

Edit: I forgot I'd created the SendMail(); function myself, which is why the explanation doesn't mention at first what it does.
I'm having some trouble with PHPMailer (https://github.com/PHPMailer/PHPMailer) when attempting to send two emails, one directly after the other.
The script is almost completely 'out of the box', with only a few modifications such as a foreach loop to allow for multiple addresses, and everything still works perfectly.
However, if I attempt to call more than one instance of SendMail(); I get the error message:
Fatal error: Cannot override final method Exception::__clone() in .... online 0
Previously I was using the in-built mail(); function, which allowed me to use it as many times as I liked in quick succession , but it doesn't appear to be that simple with PHPmailer:
$to = me#me.com;
$to2 = me2#me2.com';
$headers = 'php headers etc';
$subject = 'generic subject';
$message = 'generic message';
mail($to, $subject, $message, $headers);
mail($to2, $subject, $message, $headers);
The above would result in two identical emails being sent to different people, however I can't easily replicate this functionality with PHPmailer.
Is there a way of stacking these requests so that I can send successive emails without it failing? Forcing the script to wait until the first email has been sent would also be acceptable, although not preferential.
As I mentioned I know it works when only one instance is called, but I don't seem to be able to re-use the function.
I haven't included the source code, although it is all available on the link provided above.
Thanks in advance
Edit as requested
// First Email
$to = array(
'test#test.com',
'test2#test.com',);
$subject = "Subject";
$message = $message_start.$message_ONE.$message_end;
sendMail();
// Second Email
$to = array(
'test#test.com',
'test2#test.com',);
$subject = "Subject";
$message = $message_start.$message_TWO.$message_end;
sendMail();
The above is how I want this to work, as it would work with mail();. The first email will work fine, the second will not.
SendMail() code
This is from the PHPmailer website, and is what is defined as SendMail();. The only difference from the example is the loop for AddAddress, and the inclusion of $to as a global variable.
$mail = new PHPMailer();
$mail->IsSMTP(); // set mailer to use SMTP
$mail->Host = "smtp1.example.com;smtp2.example.com"; // specify main and backup server
$mail->SMTPAuth = true; // turn on SMTP authentication
$mail->Username = "jswan"; // SMTP username
$mail->Password = "secret"; // SMTP password
$mail->From = "from#example.com";
$mail->FromName = "Mailer";
foreach($to as $to_add){
$mail->AddAddress($to_add); // name is optional
}
$mail->AddReplyTo("info#example.com", "Information");
$mail->WordWrap = 50; // set word wrap to 50 characters
$mail->AddAttachment("/var/tmp/file.tar.gz"); // add attachments
$mail->AddAttachment("/tmp/image.jpg", "new.jpg"); // optional name
$mail->IsHTML(true); // set email format to HTML
$mail->Subject = "Here is the subject";
$mail->Body = "This is the HTML message body <b>in bold!</b>";
$mail->AltBody = "This is the body in plain text for non-HTML mail clients";
if(!$mail->Send())
{
echo "Message could not be sent. <p>";
echo "Mailer Error: " . $mail->ErrorInfo;
exit;
}
echo "Message has been sent";
You haven't posted this code that lets me make this a complete conclusion, but from the Exception and the way you've defined an overriding class inside a function, you probably have class.phpmailer.php loading every time like this:
require('class.phpmailer.php');
or
include('class.phpmailer.php');
You should change that line to
require_once('class.phpmailer.php');
The reason you need to change it to require_once is so that PHP will not load the class file the second time when you try to create the new/second PHPMailer class. Otherwise, the line class PHPMailer throws the __clone() exception.
Added an example below:
<?php
/**
* This example shows how to send a message to a whole list of recipients efficiently.
*/
//Import the PHPMailer class into the global namespace
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception;
error_reporting(E_STRICT | E_ALL);
date_default_timezone_set('Etc/UTC');
require '../vendor/autoload.php';
//Passing `true` enables PHPMailer exceptions
$mail = new PHPMailer(true);
$body = file_get_contents('contents.html');
$mail->isSMTP();
$mail->Host = 'smtp.example.com';
$mail->SMTPAuth = true;
$mail->SMTPKeepAlive = true; // SMTP connection will not close after each email sent, reduces SMTP overhead
$mail->Port = 25;
$mail->Username = 'yourname#example.com';
$mail->Password = 'yourpassword';
$mail->setFrom('list#example.com', 'List manager');
$mail->addReplyTo('list#example.com', 'List manager');
$mail->Subject = 'PHPMailer Simple database mailing list test';
//Same body for all messages, so set this before the sending loop
//If you generate a different body for each recipient (e.g. you're using a templating system),
//set it inside the loop
$mail->msgHTML($body);
//msgHTML also sets AltBody, but if you want a custom one, set it afterwards
$mail->AltBody = 'To view the message, please use an HTML compatible email viewer!';
//Connect to the database and select the recipients from your mailing list that have not yet been sent to
//You'll need to alter this to match your database
$mysql = mysqli_connect('localhost', 'username', 'password');
mysqli_select_db($mysql, 'mydb');
$result = mysqli_query($mysql, 'SELECT full_name, email, photo FROM mailinglist WHERE sent = FALSE');
foreach ($result as $row) {
try {
$mail->addAddress($row['email'], $row['full_name']);
} catch (Exception $e) {
echo 'Invalid address skipped: ' . htmlspecialchars($row['email']) . '<br>';
continue;
}
if (!empty($row['photo'])) {
//Assumes the image data is stored in the DB
$mail->addStringAttachment($row['photo'], 'YourPhoto.jpg');
}
try {
$mail->send();
echo 'Message sent to :' . htmlspecialchars($row['full_name']) . ' (' . htmlspecialchars($row['email']) . ')<br>';
//Mark it as sent in the DB
mysqli_query(
$mysql,
"UPDATE mailinglist SET sent = TRUE WHERE email = '" .
mysqli_real_escape_string($mysql, $row['email']) . "'"
);
} catch (Exception $e) {
echo 'Mailer Error (' . htmlspecialchars($row['email']) . ') ' . $mail->ErrorInfo . '<br>';
//Reset the connection to abort sending this message
//The loop will continue trying to send to the rest of the list
$mail->getSMTPInstance()->reset();
}
//Clear all addresses and attachments for the next iteration
$mail->clearAddresses();
$mail->clearAttachments();
}
In addition to #Amr most excellent code.
In order to use this in a cron fasion, two adds are useful.
$mail-> SMTPDebug = true;
$mail-> Debugoutput = function( $str, $level ) {_log($str);};
The function _log is up to you. Writing to a file, to a database or wherever. I personally have reduced this to
$mail-> Debugoutput = function( $str, $level ) {if( $level===3 ) {_log( $str ); } };
to only write the more juicier messages
the solution is to reset recipients data like this:
$Mailer->clearAddresses()
use your own variable as an instance of PHPMailer (instead of $Mailer)
$Mailer->clearAddresses()
This is the solution to avoid multiple msj to be send to the same recipient.

PHPMail - can I send two unique emails

I'm using PHPMailer to successfully send an email upon a webform submission (so just using basic post data, no mysql databases or any lookups).
What I need to do is send two seperate emails, one version for the customer and the other for a customer service agent - so that when a user completes a webform, they will receive a 'marketing' version of the email, whilst the customer service agent will receive an email just containing the details submitted by the user.
See below what im using at the moment, but not sure how to best implement to send the secoind email? It presently fails and the script exits after sending only one email.
$body = ob_get_contents();
$to = 'removed';
$email = 'removed';
$fromaddress = "removed";
$fromname = "removed";
require("phpmailer.php");
$mail = new PHPMailer();
$mail->From = $fromaddress;
$mail->FromName = $fromname ;
$mail->AddAddress("email#example.com");
$mail->WordWrap = 50;
$mail->IsHTML(true);
$mail->Subject = "Subject";
$mail->Body = $body;
$mail->AltBody = "This is the text-only body";
if(!$mail->Send()) {
$recipient = 'email#example.com';
$subject = 'Contact form failed';
$content = $body;
mail($recipient, $subject, $content,
"From: mail#yourdomain.com\r\nReply-To: $email\r\nX-Mailer: DT_formmail");
exit;
}
//Send the customer version
$mail=new PHPMailer();
$mail->SetFrom('email', 'FULLNAME');
$mail->AddAddress($mail_vars[2], 'sss');
$mail->Subject = "Customers email";
$mail->MsgHTML("email body here");
//$mail->Send();
In the customer version you are not setting the email's properties the same way you are in the first. For example you use $mail->From = $fromaddress; in the first and $mail->SetFrom('email', 'FULLNAME'); in the second.
Because you instantiated a new $mail=new PHPMailer(); you need to set the properties again.
Instead of just bailing out with a useless "something didn't work" message, why not have PHPMailer TELL you what the problem is?
if (!$mail->send()) {
$error = $mail->ErrorInfo;
echo "Mail failed with error: $error";
}

Categories