phpmailer addBCC not storing addresses - phpmailer

I am using PHPMailer and use AddBCC to send to most of my addresses (only use 1 required in AddAddress). It seems to work okay (no errors), but I have found that it isn't saving (or sending to) all of the addresses that I process with $mail->AddBCC. It skips some of them, yet keeps others. So, when I do a print_r($mail->getBccAddresses()), I can see that it only has some of the email addresses. I am processing my lists of addresses in small groups, so I can control things better, so I wouldn't think there'd be any problems like this. I am including the applicable code from my program:
<?php session_start();
require '../PHPMailer/PHPMailerAutoload.php';
$mail = new PHPMailer;
$emailist_cnt = 3;
for ($i=1; $i<= $emailist_cnt; $i++) {
//loop to gather email addresses into array $emailistAry[][]
}
// First, set up email message and required parameters.
$toname = "Grp-members";// Unused mailbox name
$fromname = "Webmaster";
$replyname ="Grpwebmaster";
$fromaddr = $fromname."#mydomain.org";
$toaddr = $toname."#mydomain.org";
$rplyaddr = $replyname."#gmail".".com";
$subject = "-- Website Update--";
$note1 = "New content has been added to the website";
$note2 = "Go check it out, if you want to stay up-to-date:";
$message = "Greetings HLCA Member! ".$note1." ".$note2;
// Set mail environment variables
$mail->isSMTP();
$mail->Host = 'smtp.hiddenlakeonline.org';
$mail->SMTPAuth = true;
$mail->Username = $fromname."#".$domain.".org";
$mail->Password = $webpass;
$mail->SMTPSecure = 'tls';
$mail->Port = 587;
// Set mail details that remain constant for every recipient
$mail->SetFrom($fromaddr);
$mail->AddAddress($toaddr);
$mail->AddReplyTo($rplyaddr);
$mail->Subject = $subject;
$mail->Body = $message;
$max_emails = 25; // max num emails per list
for ($i=1; $i <= $emailist_cnt; $i+=1) {
for ($j=1; $j <= $max_emails; $j+=1) {
// Addresses in current list will be added to BCC param.
if ($emailistAry[$i][$j] != '') {
$mail->AddBCC($emailistAry[$i][$j]); // add email to BCC }
} // for j loop
echo "would send to email list here. ";
print_r($mail->getBccAddresses());
// Clear cumulative recipient list for next loop
$mail->clearBCCs();
} // for i loop
?>
As you can see, I'm just doing a loop to add BCC entries. But, when I print out the getBCCaddresses array, there is always at least one email missing from each list. Is there a bug in PHP Mailer? Or am I doing something wrong?
I have seen a similar post (without any code) on another site (sourceforge.net?), but the question never got answered. Otherwise, there hasn't been anything similar that could help. Hopefully someone on here knows something about this.
Here are some results I get using echo outputs:
i,j,adding this email: 1,1,ImxEarth#gmail.com
i,j,adding this email: 1,2,heffxdog#me.com
i,j,adding this email: 1,3,imxearth#gmail.com
i,j,adding this email: 1,4,Aaronx72#yahoo.com
print: Array ( [0] => Array ( [0] => ImForEarth#gmail.com [1] => ) [1] => Array ( [0] => heffdog#me.com [1] => ) [2] => Array ( [0] => AaronTW72#yahoo.com [1] => ) )
Is it possible that phpMailer prevents duplicate addresses in BCC array?

I think I found my answer! It appears that AddBCC will only add unique email addresses to its array. So if an email address already exists in the BCCaddresses array, then the Mail->AddBCC('email') statement will not add it again. This becomes apparent when testing, because we often need to use duplicates to create a good size batch of emails. Well, you can process the duplicates, but they won't be added to the BCC parameter and won't be mailed more than once. Thx to all that responded!

Related

How to Specify File Type and Size Limits With PHPMailer Mailing Multiple Attachments

Can someone please let me know using the PHPMailer how I can specifiy the limit of size and type of attachment?
For example if I want to enable Only PDF file to be attached and with limited size how I can update this part of the code?
foreach ($_FILES["attachment"]["name"] as $k => $v) {
$mail->AddAttachment( $_FILES["attachment"]["tmp_name"][$k], $_FILES["attachment"]["name"][$k] );
}
Here is the entire code
<?php
require('phpmailer/class.phpmailer.php');
$mail = new PHPMailer();
$mail->IsSMTP();
$mail->SMTPDebug = 0;
$mail->SMTPAuth = TRUE;
$mail->SMTPSecure = "ssl";
$mail->Port = 465;
$mail->Username = "YOUR USER_NAME";
$mail->Password = "YOUR PASSWORD";
$mail->Host = "YOUR HOST";
$mail->Mailer = "smtp";
$mail->SetFrom($_POST["userEmail"], $_POST["userName"]);
$mail->AddReplyTo($_POST["userEmail"], $_POST["userName"]);
$mail->AddAddress("RECIPIENT_EMAIL");
$mail->Subject = $_POST["subject"];
$mail->WordWrap = 80;
$mail->MsgHTML($_POST["content"]);
foreach ($_FILES["attachment"]["name"] as $k => $v) {
$mail->AddAttachment( $_FILES["attachment"]["tmp_name"][$k], $_FILES["attachment"]["name"][$k] );
}
$mail->IsHTML(true);
if(!$mail->Send()) {
echo "<p class='error'>Problem in Sending Mail.</p>";
} else {
echo "<p class='success'>Mail Sent Successfully.</p>";
}
?>
This isn't PHPMailer's responsibility – it's up to you to control the size and type of files before it gets to PHPMailer.
First of all, you're using a very old and unsupported version of PHPMailer, so upgrade to the latest version.
Secondly, your handling of uploads is unsafe. Follow the PHPMailer file upload example for how to do it safely.
In your form, set a hidden field named MAX_FILE_SIZE before your file input, set to whatever maximum size you want to impose:
<input type="hidden" name="MAX_FILE_SIZE" value="123456">
This can't actually control the size of submissions, but by convention, browsers will use it to reject oversize files before they are submitted, saving the user considerable hassle.
After validating the $_FILES element you're looking at (with move_uploaded_file, as in the example), take a look at the size of the submitted file by looking at the size element:
if ($_FILES['attachment']['size'] <= 123456) {
//We know file is under our size limit
To check the file type, extract the extension from the provided filename:
if (pathinfo($_FILES['userfile']['name'], PATHINFO_EXTENSION) === 'pdf')) {
//We know file has a `.pdf` extension
For good measure, you could also check that the provided file type is what we want too:
if ($_FILES['userfile']['type'] === 'application/pdf')) {
//We know file has a PDF MIME type
After checking all of those things, you're now safe to pass the validated file to PHPMailer:
$mail->addAttachment($uploadedFilePath);

PHPMailer is causing long cc strings to separate

I use PHPMailer to send HTML emails. The code looks as follows:
$mail = new PHPMailer;
$mail->SMTPDebug = 3; // 3 = Enable verbose debug output
$mail->setFrom($mgr_email);
$mail->addReplyTo($mgr_email);
$mail->Encoding = 'base64';
$mail->isHTML(true);
// $legacy is an array we loop through of emails
$first = true;
foreach ($legacy as $x => $theiremail) {
if ($first == true) {
$mail->addAddress(trim($theiremail));
$first = false;
} else {
$mail->AddCC(trim($theiremail));
}
}
...
// later, we add an image every time (the company logo)
$mail->addEmbeddedImage($paths[$i]['path'], $paths[$i]['cid'], "image$i.jpg");
However, when I have many recipients, the email address string starts to break with a space in them, and always around the same spot. Example:
george#george.com, anyone#anyone.com, example#example.com, steven#we bsite.com
Steven here does not get the email. I've experienced something like this in HTML once where our longer emails just needed a space somewhere because our "headers" were a long, single word, but I can't figure out how to accomplish this with PHPMailer. In that case, all I had to do was add a space somewhere in the code. Any insight is appreciated.

Gmail script forward without attachment

I am editing online available snooze script for gmail, where i would like to bring back an email unread, in inbox and on top of the list. I am able to make it unread, and bring back to inbox based on the available script, but to bring on top of the inbox, i am forwarding the email to myself. By this, I am able to get the email thread on top of the list, but when an email which is snoozed has an attachment, it forwards the email with attachment. I have tons of emails, and have limited available space. Hence i am ending up using extra storage for duplicate attachment which is unneeded.
I would like to forward the email, without attachment. Below is my current script:
var firstThread = page[i];
var giattachment = null;
var sub = firstThread.getFirstMessageSubject();
var newsub = "Reminder: " + firstThread.getFirstMessageSubject() + " : ";
var id = newsub + firstThread.getPermalink();
var messages = firstThread.getMessages();
var totalThreadCount= firstThread.getMessageCount();
for (var j = 0; j < messages.length; j++) {
var forwardlength=messages.length-1;
if(j == forwardlength) {
if (MARK_UNREAD) {
messages[j].markUnread();
}
messages[j].forward(userEmail,{subject: newsub, from:userEmail, name: EmailFrom, body: newbody, attachments:giattachment});
}
}
Inspite of this, the email gets forwarded with an attachment. Please advise..
Thanks in advance
To selectively forward messages, use filters to create rules that forward in response to message attributes or content.
You can filter messages by properties such as the sender, subject date, size, and message contents. Any query using Gmail's advanced search syntax can also be used in a filter. Try to set criteria.hasAttachment=true to false.
For more information, follow this link: https://developers.google.com/gmail/api/v1/reference/users/settings/filters
You can't forward using Class GmailMessage because it forces you to forward the original attachments. While unforunately undocumented, its advanced parameter attachments can only add new attachments.
However, you can forward by creating a new message using Class MailApp instead, in your case it would be:
var from, firstThread = page[i];
var sub = firstThread.getFirstMessageSubject();
var newsub = "Reminder: " + firstThread.getFirstMessageSubject() + " : ";
var id = newsub + firstThread.getPermalink();
var messages = firstThread.getMessages();
var totalThreadCount= firstThread.getMessageCount();
for (var j = 0; j < messages.length; j++) {
var forwardlength=messages.length-1;
if(j == forwardlength) {
if (MARK_UNREAD) {
messages[j].markUnread();
}
from = message.getHeader('From');
if (from.indexOf(' <') > -1)
from = from.substring(0, from.indexOf(' <'));
else
from = '';
MailApp.sendEmail(userEmail, newsub, '', {htmlBody: messages[j].getBody(), name: from, replyTo: message[j].getFrom()});
}
}
Changes:
Removed your var giattachment = null;
Replaced your messages[j].forward with MailApp.sendEmail
Used messages[j].getBody() to simulate the original body
Added the original sender's name as the "sender's" name
Added the original sender's address as reply-to
The last 2 points mean the forwarded message will arrive from "someone else's name" <your#address> which for most recipients will appear like a true forward.

Netsuite Past Due Reminder using SuiteScript

The script is complete! Thanks for all those who replied :)
/*
* Author: Laura Micek
* Date: 5-13-15
* Purpose: This script creates a saved search in order to pull the information needed to send out an email to alert customers that
* their account is past due. The saved searched makes sure that the customer is 11 days or more past due, checks to see if they are
* exempt from past due reminders, and that their account balance is greater than 1. Once the saved search runs, it will loop thru the
* customers that meet these requirements and it will use the days past due to determine if an email needs to be sent. An email will
* only be sent if the days past due are equal to 11 or if the days past due minus 11, modded by 8 equals 0 which means that it has
* been 8 days since the last notification.
*/
function email_late_customers(type) {
//variables
var send_from = 22730; // Internal ID of NS User
//setup filters and result columns for a customer saved search
var filters = new Array();
filters[0] = new nlobjSearchFilter('daysoverdue',null,'greaterthanorequalto',11);
filters[1] = new nlobjSearchFilter('custentitypastdueremind',null,'is', 'F');
filters[2] = new nlobjSearchFilter('balance',null,'greaterthan', 1);
var columns = new Array();
columns[0] = new nlobjSearchColumn('internalid');
columns[1] = new nlobjSearchColumn('email');
columns[2] = new nlobjSearchColumn('daysoverdue');
//run saved search and loop thru results
var customers = nlapiSearchRecord('customer',null,filters,columns);
for (var i = 0; customers != null && i < customers.length; i++) {
//grab all the customer data
var this_customer = customers[i];
var cust_id = this_customer.getValue('internalid');
var send_to = this_customer.getValue('email');
var getpastduedays = this_customer.getValue('daysoverdue');
//this is the check to see if the amount of days is over 11 to see if another email needs to be sent.
if(getpastduedays > 11) {
var checkPastDue = (getpastduedays - 11) % 8;
}
/*
if the above checkPastDues evaluates to zero then it has been 8 days since the last notification, this is the other condition to send an email. The first being that the customer is 11 days past due.
*/
if(getpastduedays == 11 || checkPastDue == 0) {
//email subject
var subject = 'Your Account is Past Due';
// create body text
var body = 'Hello, \r\r';
body += ' This is a reminder that your account is currently past due. Attached is a current detailed aging of your account for your reference.\r\r ';
body += ' Can you please review and let me know the status of payment?\r\r';
body += ' Your prompt attention to this matter would be greatly appreciated. If you have any questions reguarding this account, please ';
body += ' contact us as soon as possible. Any questions or invoice copy requests can be email to ar#doubleradius.com.\r\r';
body += ' If payment has been recently been made, please accept our thanks and ignore this reminder.\r\r';
body += 'Thank You!\r\r';
//setup filters and result columns for a transaction saved search
var filters = new Array();
filters[0] = new nlobjSearchFilter('status',null,'is', 'CustInvc:A');
filters[1] = new nlobjSearchFilter('type',null,'is', 'CustInvc');
filters[2] = new nlobjSearchFilter('email',null,'is', send_to);
filters[3] = new nlobjSearchFilter('mainline',null,'is', 'T');
var columns = new Array();
columns[0] = new nlobjSearchColumn('internalid');
//run saved search and loop thru results
var transactions = nlapiSearchRecord('transaction',null,filters,columns);
var invoices = [];
for (var i = 0; transactions != null && i < transactions.length; i++) {
//grab all the transaction data
var this_transaction = transactions[i];
invoices[i] = this_transaction.getValue('internalid');
}
//print the statement to a PDF file object
var attachment = [];
for (var i = 0; invoices != null && i < invoices.length; i++) {
attachment[i] = nlapiPrintRecord('TRANSACTION',invoices[i],'DEFAULT',null);
}
//send the PDF as an attachment
nlapiSendEmail(send_from,/*send_to*/ 'lauram#doubleradius.com', subject, body, null, null, null, attachment);
}
}
}
You don't need scripting to achieve this simple requirement. All you need is a saved search and a workflow. The key thing here is you need to come up with the right criteria on your saved search. Once you have the right saved search you set your workflow's Initiation to run on Scheduled and choose the frequency. Use the Send Email action to send the email to the customers and you are good to go.
Also, from the saved search you can join the customer record to the Messages Field so you will have the ability to check when was the last email sent.
You might also need a Email Template.
If you're going to use a Scheduled Script you will need to collect the records you want to inspect. If these are Customer records then be sure to setup searchFilters and searchColumns to come back and then collect the results.
// set Customer record filters and columns to return
var filters = new Array();
filters.push( new nlobjSearchFilter('isActive', null, 'is', 'F') );
filters.push( new nlobjSearchFilter('someotherfield', null, 'isempty') );
var cust_cols = new Array();
cust_cols.push( new nlobjSearchColumn('companyname') );
cust_cols.push( new nlobjSearchColumn('someotherfield') );
// now get the records that fit your filters and return the cols specified
overdue_customers = nlapiSearchRecord('customer', null, searchfilter, columns);
I generally like to move my content/body creating code into separate functions but it's really not that important depending on how complicated your script is. For instance I have a couple of scripts that do a lot of processing that have to send some information on a record by record basis but also sends "digest" type emails to others. Think customers and account managers. While it was a pain to set up everything up to handle both cases having a email content generating function was much saner and easier to read.
Though there are many approaches you could use for this, I think your scheduled script approach will work just fine. You can make the logic for identifying which emails to send by offloading the 8-day calculation to your search filters, instead of manually trying to compute. I would have a filter in my search of something like:
new nlobjSearchFilter('custentity_dayssincelastemailed', null, 'before', 'previousOneWeek');
See the Help article titled Search Date Filters for more details on what you can do with Dates in filters.
After that, I believe you should be able to create an Email Template and utilize that in your code to set the title and the boilerplate of the email body.
Where I'm a little less certain, and what may be more difficult for you, is your A/R Aging attachment. Not sure I've worked with attaching statements.

Is there a PHPmailer parameter to limit re-sends?

When I use PHPmailer to send to a group of email addresses, it gets caught in a loop and keeps re-sending the email over and over (100 times or more). It doesn't always do this however. I can send to 10 or 12 addresses and it works fine. But a larger list (25 addresses) seems to have trouble. I did find some non-existent email addresses in my list that rebound back to my "from" address mailbox. So I thought that might be the problem. But, I ran a test with just 3 addresses (one non-existent) and it worked as expected (good addresses received the mail, and the bad one was rebounded back to the sender mailbox). No duplicate emails were sent.
I do use BCC to send my email, but I don't think that should matter. I'm wondering if maybe there is some parameter I can set for PHPmailer that will tell it not to re-send any emails. My web hosting site says it is not their server or mail system that is sending these emails, so I'm guessing it is something in PHPmailer.
When my real-life use of PHPmailer doesn't work like it did when I tested it, that makes it very difficult to fix. Anyone have any suggestions as to why my emails keep getting sent multiple times?
Also, I'd like to know if there's a way to stop PHPmailer, after $mail->Send() has been issued? I'm getting a little embarrassed with the spam-like behavior of my emails (and my users are getting mad).
My basic code is below. But, the PHP program code is the same in the cases where it works and doesn't work; it's just the input data that changes. When it has worked, there were 2 smaller arrays:
emailistAry(1) = array(email1,email2,email3,...email10) and
emailistAry(2) = array(email1,email2,email3,email4,email5).
When it keeps looping, there are 2 larger arrays:
emailistAry(1) = array(email1,email2,bademail1,email3,email4,bademail2,email5,...email25) and emailistAry(2) = array(mail26,email27,email28,bademail3,email29,...email50).
I haven't found the exact number that I can process successfully, because it would mean running tests that possibly fill people's mailboxes with endless multiple emails. No one wants that.
Here's my code:
<?php session_start();
// uses arrays of addresses to send emails to multiple people (with BCC)
require '../PHPMailer/PHPMailerAutoload.php';
$mail = new PHPMailer;
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<head>
<link href="../root.css" rel="stylesheet" type="text/CSS"/>
<title> Website Notification </title>
<meta http-equiv= "content-type" content="text/html; charset=iso-8859-1"/>
</head>
<body>
<div style="top:0;padding:0;width:850px;margin-left:70px;">
<?php
//$emailistAry is gathered from addresses in a database.
// it contains 2 arrays of email arrays (multi-dimensional).
//$emailist_cnt is determined from building above array (currently a 2)
$fromaddr = "myaddress#mywebsite.org";
$toaddr = "groupaddress#mywebsite.com";
$rplyaddr = "my2address#gmail.com";
$subject = "--Special Notice--";
$messageH = "<p style='font-family:Arial,Helvetica,Georgia,\"Times New Roman\";font-size:90%;'>
<span style='font-size:120%;color:#336699;'>Greetings HLCA Member!</span> <br/><br/>".
"This is my message text....".
"</p>";
// Set mail environment variables
$mail->isSMTP();
$mail->Host = 'smtp.mywebsite.org';
$mail->SMTPAuth = true;
$mail->Username = $fromaddr;
$mail->Password = "mypasswd";
$mail->SMTPSecure = 'tls';
$mail->Port = 587;
// Set mail details that remain constant for every recipient
$mail->SetFrom($fromaddr); // mailbox you want email to come from
$mail->AddAddress($toaddr); // set recipient group (empty mailbox)
$mail->AddReplyTo($rplyaddr); // where reject msgs are sent
$mail->Subject = make_goodemail($nly,'subj',$subject);
$mail->Body = $messageH;
$goodlist_cnt = $emailist_cnt;
$max_emails = 25; // max num emails per list
$bcc_out_total = 0; //number emails output with BCC
$badlist_cnt = 0;
$badlist = ''; // save emails that didn't get sent
$email_badlist = array(); // store email lists that didn't get sent
$duplist = "";
$stop_err = false;
$rcN = 0;
// Loop through email arrays and send one at a time (each contains an array of emails).
// (Note that we do not use the 0 array positions. First entries are in position 1.)
for ($i=1; $i <= $emailist_cnt; $i+=1) {
echo "<p style='margin-top:40px;font-size:120%;'><b> Processing list # ".$i."...</b></p>";
$duplist = "";
for ($j=1; $j <= $max_emails; $j+=1) {
// add addresses from this list array to BCC parameter,
if ($emailistAry[$i][$j] != '') {
// add current email to BCC for this list (save rc)
$BCCresult = $mail->AddBCC($emailistAry[$i][$j]);
if(!$BCCresult) {
$duplist = $duplist.$emailistAry[$i][$j].", ";
}
}
else {
$j = $max_emails; //set as end of list
}
} // for j loop
// Loop thru this BCC array and show list on screen.
$bccArray = $mail->GetBCCAddresses();
$bcc_out = 0;
echo "<br/>Mail BCC list: ";
for ($k=0;$k<=$max_emails;$k+=1) {
if ($bccArray[$k][0] != '') {
if ($k==0) { //first one
echo " ".$bccArray[$k][0]; } //no comma
else {
echo ", ".$bccArray[$k][0]; }
$bcc_out += 1;
}
else {
$k=$max_emails;
}
}
// $bcc_out_total = $bcc_out_total + $bcc_out;
echo "<br/>BCC count = ".$bcc_out;
if ($duplist != "") { //print duplicate list
echo "<br/> >>Duplicate or invalid emails not included: ".$duplist;
}
//echo "<br/><br/>would send email list here. webpass=".$webpass;
// ********** *********** ************* ************
// SEND THE MAIL with current BCC list of recipients.
// Output message indicating if mail for this group was successfully or not.
if (!$mail->Send()) { // Send mail, else save emailist.
// see if connection error, and process accordingly
$mail_err = $mail->ErrorInfo;
$pos = strpos($mail_err,'SMTP connect() failed');
if ($pos===true || $pos >= 0) {
$addmsg = "(Probably a password error. Try again.) <br/>";
if ($i == 1) { // connect error on first try, so
$stop_err = true; // stop processing cuz this error will continue
$rcN = 2;
}
}
else {
$addmsg = "";
$rcN = 1; //set general error for return
}
echo "<h4 style='color:red;margin-top:20px;margin-bottom:5px;text-align:center;'>
Problem sending emails. ".$addmsg." Mailer Error: ".$mail->ErrorInfo."</h4>";
echo "<h4 style='color:blue;margin-top:10px;margin-left:20px;margin-bottom:0px;'>Email List #".$i." not sent. </h4>";
if (!$stop_err) { //other error, so handle and keep going.
$goodlist_cnt = $goodlist_cnt - 1;
//save list in array (as one long string).
$badlist_cnt+=1;
$email_badlist[$badlist_cnt] = implode(",",$emailistAry[$i]); //save as a string
}
} //if !Mail-send
else { // Successful email
$bcc_out_total = $bcc_out_total + $bcc_out;
echo "<h4 style='color:blue;margin-top:20px;font-weight:bold;'>
Email group ".$i." sent successfully! </h4>";
}
// Clear cumulative recipient list for next loop
$mail->clearBCCs();
if ($stop_err) {
$i = $emailist_cnt; //set to last list so loop will stop
}
} // for i loop
if ($badlist_cnt > 0) { // error, but not stop_err, so lists are saved elsewhere.
$badlist_txt = "<span style='color:red;font-size:80%;'> (".$badlist_cnt." list(s) not sent)</span>";
//write badlists out to file for fixing and later processing
include ('includes/memNotifyErrSave.php');
}
else {
$badlist_txt = '';
}
if ($stop_err) {
echo "<br/> <h4 style='color:red;margin-top:50px;text-align:center;'> Processing stopped due to serious error! ".
"If password error, try again with correct password.<br/><br/>".
"<span style='font-size:120%;color:blue;font-weight:bold;'>* No emails were sent * </span></h4>";
}
else {
echo "<h4 style='color:blue;font-size:125%;font-weight:bold;margin-top:40px;'>
Sent this notice to ".$bcc_out_total." unique address(es), using ".$goodlist_cnt." email(s)".$badlist_txt.".</h4>";
}
// code for exit/return buttons
// Clear remaining cumulative lists
$mail->clearReplyTos();
$mail->clearAddresses();
?>
</div>
</body>
</html>

Resources