I have a table in my database which contains emails to be sent. A script runs periodically as a cron job to read the data from table and dispatch the emails via the SMTP server. I am using PHPMailer for the work here. The script runs a loop for sending emails until all the emails in the table have been sent.
The problem is that most consecutive emails being sent have a common subject. So when the loop runs, somehow all the emails that get sent have a long 'to' list. So basically if 5 email entries (with different to addresses) have the same subject and same content, then it ends up sending only 1 email with 5 addresses (one of each email entry) in the 'to' field. This reveals the email address of every person to everyone else on the list. This is undesirable and the emails must be sent to only that one person for whom it is meant.
I don't know what's at play here. Any suggestions?
Are you doing something like this?
$mailer = new PHPMailer();
while($row = fetch_from_db()) {
$mailer->AddAddress($row['email']);
$mailer->send();
}
If so, you need to do a
$mailer->ClearAllRecipients()
after you send each email, so you start out with a "fresh" To: list.
while($row = fetch_from_db()) {
$mailer->AddAddress($row['email']);
$mailer->send();
$mailer->ClearAllRecipients()
}
1st, get the contacts from your db
$contacts = 'GET CONTACTS ARRAY FROM DB'
if(!empty($contacts)){
foreach ($contacts as $crt_contact){
$emails[] = $crt_contact->email ;
}
}
2nd use the following to create the "to" field
$to = implode(',', array_unique($emails));
Use the $to to send in mail() function
Related
I'm using PHP to send mails to multiple people in CakePHP.
I'm currently using foreach on the recipient array, which contains mail address and names, and send the mails. It's taking quite a while to send mails and can't be done as put recipients' mail as array since there's a tiny different between all mails such as receiver's names.
The mails are using same template but different parameters, is there anyway I can improve the efficiency of it?
Update: Here is the Email Template
<?= $userSex ?> <?= $userName ?>, <br>
Thanks for ordering!<br>
Your order's ID is "<?= $orderID ?>".<br>
You can check the shipping status on our website.<br>
Thank you and hope you have a wonderful day.
and here's the code.
$mail_list = {
[0]=>{
'userSex'=>'Miss',
'userName'=>'V',
'orderID'=>'xxxxxxxx'
},
[1]=>{
'userSex'=>'Mr.',
'userName'=>'Arasaka',
'orderID'=>'xxxxxxxx'
}
}
foreach($mail_list as $target) {
$email = new Email();
$email->viewBuilder()->setTemplate('notify_template');
$email->setEmailFormat('html')
->setSubject($subject)
->setViewVars([
'userSex' => $target['userSex'],
'userName' => $target['userName'],
'orderID' => $target['orderID'],
]);
$emailRes = $email
->setFrom(['no-reply#service.com' => 'service announence'])
->setTo($target['email'])
->setSubject($subject)
->send();
if (!$emailRes) {
$res = false;
break;
}
}
Every mail sent is slightly different.
Is there a way to improve the mailing speed?
The speed of your mailing will be dictated by the speed of your configured transport (See https://book.cakephp.org/3/en/core-libraries/email.html#using-transports).
Sending the emails sequentially like this will always take time and it's normally done in some sort of background process (like a cron job).
If you really need to send emails quicker than what a quick transport can offer (for orders and other transactional email, I doubt it) you could investigate other options. Most email API services provide some sort of way to send bulk messages using templates (such as Sendgrid, Mandrill, Mailgun, Postmark, etc.)
I am trying to send emails by swiftmailer in foreach. But it always sends only to first email addressee times number of users. (say, there are 3 users, it will send 3 mails to first user).
I have checked that every iteration of sendmail have different email address, that address is in $email instance ($email->getTo()) and as long as it cannot send email (ie. on localhost) it works fine. It creates 3 emails, with 3 different addresses. But when it actually can send it via SMTP it will send all mails to same person with same text rendered.
I am thinking that issue is with $app->mailer->compose, but i am not really sure. (seems like that instance is holding its data and it cannot be rewritten, till app resets)
Controller:
foreach ($invitations as $invitation_id) {
$model = Invitation::findOne($invitation_id);
if (!empty($model)) {
if (!$model->sendMail('Test mail')) {
$errors[] = $model->userName;
}
} else {
$errors[] = "Non existing $invitation_id?";
}
}
Model Invitation:
public function sendMail ($text){
$user = User::findOne($this->user_id);
$email = Yii::$app->mailer->compose('layouts/bulk-email', ['user' => $user, 'text' => $text])
->setFrom('test#test.com')
->setTo($user['mail'])
->setSubject('Test subject');
return $email->send();
}
I tried using the sendMultiple method (creating messages first to array, and then send them all at once), but instead they were all send 6 times to first address.
Is there something obvious i am missing?
Actual issue was that localhost is not caching ldap answers, but the dev server is. So the issue was actually what Muhammad Omer Aslam somewhat suggested :)
I have a situation where I sending an 2 different emails, one to a customer and one to a member after the member accepts a task. Within the function I am calling 2 functions, one that sends to the client and one is sent to the member. The what is happening is that the second email is being sent to both the member and the client, yet the client, the first email, only gets the email expected.
What I figured is happening is that because both of these functions are occurring at the same time, some how the addAddress() function is taking both email addresses over to the second email. My proof of this is I changed the order of the functions so the Member send first and the Client sent second and they both got the Client email where before the Client sent first and the Member sent second.
My question than is how do I make the first email break for a few seconds before the second email is sent to stop this from happening.
Here is the basic set up of the code.
function memberAccept()
{
// SQL to mark in DB that member accept task
$this->memberEmail($id)
$this->clientEmail($id)
}
function memberEmail($id)
{
// SQL to gather information about member inner join with task
$subject = 'Email';
$body = 'Email to member'
$this->sendEmail($member['email'], $subject, $body)
}
function clientEmail($id)
{
// SQL to gather information about client inner join with task
$subject = 'Email';
$body = 'Email to client'
$this->sendEmail($client['priemail'], $subject, $body)
}
sendEmail() is in another Class set up to use PHPMailer functions to send the email.
In your case, you must use the following function before adding new recipient for the mail:
$mailer->ClearAllRecipients( ); // clear all
Basically, the problem is that, when you add first recipient, mailer successfully delivers the mail, but the object is not destroyed yet. Hence, when the next mail is sent, member's email is still in the recipient, so alter your code to call this ClearAllRecipients function before adding the new recipient.
I want to send an email to a list of address but I want each person to receive the email with his email address in to: (and not with the other email addresses of the diffusion list).
I am using symfony and Swift mail. My code look like that at the moment (it is working):
public function sendmail(Notification $notification, $alert){
$to = array();
foreach ($members as $member) {
$to[] = $member->getUser()->getEmail();
}
$html = $this->templating->render(
'PlatformBundle:Emails:email.html.twig',
array('alert' => $alert, 'notification' => $notification, 'user' => $this->user)
);
// Configure and send the mail
$message = \Swift_Message::newInstance()
->setSubject('an email ')
->setFrom($this->sender_email)
->setCc($this->user->getEmail())
->setTo($to)
->setBody($html, 'text/html');
$mailStatus = $this->mailer->send($message);
}
I have 2 solutions (I do not like any for them!).
using BCC (Sending to multiple Email addresses but displaying only one C#) but it makes my email looking like a spam
looping and sending the same email to each member (seems really server resource consuming)
public function sendmail(Notification $notification, $alert){
$to = array();
foreach ($members as $member) {
$to[] = $member->getUser()->getEmail();
$html = $this->templating->render(
'PlatformBundle:Emails:email.html.twig',
array('alert' => $alert, 'notification' => $notification, 'user' => $this->user)
);
// Configure and send the mail
$message = \Swift_Message::newInstance()
->setSubject('an email ')
->setFrom($this->sender_email)
->setCc($this->user->getEmail())
->setTo($to)
->setBody($html, 'text/html');
$mailStatus = $this->mailer->send($message);
}
Is this loop OK?
Any better idea?
Looping is really the only solution.
If you have many recipients, you will be marked as spam (and banned) pretty fast. You will want to go through a dedicated mail platform (with a bit of time between each send), which you can code yourself (pretty heavy work), or there are many mail platform as service around, like MailChimp or MailJet for instance.
It all depends on the number of mails to send. Up to about 100 per day might be OK (although it's an arbitrary number from the top of my head).
More than a certain threshold, and depending on the mail server you use (local on your server or gmail for instance), your IP or account might get banned. Most email providers have a mail limit per day, for instance.
Email services have many rules for sending, for instance, they delay the emails ; they send using multiple domains and addresses ; they work with the main mail providers (gmail, yahoo...) to make sure their domains are not marked as spam automatically...
Basically, if you really want to send many emails to many people, I really don't recommend doing it yourself. There are too many caveats.
I am using Class MailerPHP to send emails on the website. Actually is working perfect as it have to work but there is some strange stuff that i can not figure out why is like this.
1. I have an array of address that i am sending emails, the array is like this:
$email = new sendEmail();
$_ADMIN_EMAIL = array('first_email', 'second_email', 'third_email');
$email->setEmail($_ADMIN_EMAIL);
The problem is when is sending emails, is sending 3 emails:
1. sending to first_email
2. after sending to first_email and second_email
3. and at the end sending to first_email, second_email and third_email
I would like to send only one to all 3 and do not send 3 times email, i do not understand why is sending like this.
2. And second problem is i am using my Google account to connect to the SMTP to send emails, and i do not know why in the TO field of the email is showing my gmail address that i connect to the SMTP, i setup which address to show there and is showing + my gmail account:
I have this configuration only and i didn't put anywhere else my gmail account only for SMTP connection:
public $Username = 'my_gmail_account_to connect_to_smtp';
public $Password = 'my_gmail_account_password';
The result of this when i get emails is first email that i setup to show for reply + my_gmail_account_to connect_to_smtp, i need to take out my_gmail_account_to connect_to_smtp from the email that the user will not see it.
If you need for information about the code i use please let me know i will put.
All the code that i send email:
$_ADMIN_EMAIL = array("first_email", "second_email", "third_email");
$email2 = new sendEmail();
$email2->setSubject("Subject");
$email2->setUserName($_USER['name']);
$email2->setMT4Account($_USER['login']);
$email2->setDate($_USER['date']);
$email2->setAmount($_USER['amount']);
$email2->setCurrency($_USER['currency']);
$email2->setRegisteredBankAccount($_USER['type']);
$email2->setBankAccountName($_USER['card']);
$email2->setTemplate('template_for_the_email');
$email2->setEmail($_ADMIN_EMAIL);
echo $email2->send();
Try this:
$_ADMIN_EMAIL = array('first_email', 'second_email', 'third_email');
foreach($_ADMIN_EMAIL as $ademail)
{
$email->setEmail($ademail);
}