Yii2 Swiftmailer foreach sending same email to first to - php

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 :)

Related

How to improve the efficiency of PHP mail sending?

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.)

sending bulk email using cakePHP

I'm trying to send an email to more then 2000 email ids at a time but It's throwing 502 Bad Gateway error.
If I send an email to within 600 mails it's working fine but it's taking 10 minutes time to send to all. please help me if anyone has know about it.
Here my code
foreach ($submail as $mail) {
$email = new Email();
$email->template('abc');
$email->emailFormat('both');
$email->from(['abc#abc.com' => 'abc']);
$email->to($mail);
$email->subject('abc');
if ($email->send()) {
} else {
}
}
It might be better create a queue for your emails, and use a CLI worker to actually send your emails. Check out one of the many plugins:
lorenzo-cakephp-email-queue
nodesagency-cakephp-email-queue
etc.
queueing your emails and using a CLI worker dedicated to sending the emails will open up some extra opportunities like sending the emails at a specific time with cronjobs etc.

Symfony swift_mail: send to multiple address but only display one address per email

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.

Class MailerPHP strange behaviour (looping array of address)

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);
}

How to not make PHPmailer send an email with multiple 'to' addresses?

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

Categories