1

I need to send batch emails, and every mail have unique message. I am trying foreach loop, but I keep getting Allowed memory size of 104857600 bytes exhausted (tried to allocate 66 bytes) error. Is it possible to perform foreach with swiftmailer, or there is some other way (message contains unique token). Code:

$users = Users::find()->where(['email' => $emails])->all();

        foreach($users as $user):


                $user->scenario = 'saveToken';

                $token = hash('sha256',microtime() . Yii::$app->security->generateRandomString(32));

                $user->token = $token;

                $user->save();

               Email::oldUsers($user->email, $token);


        endforeach;

Sending emails:

static function oldUsers($userEmail, $token)
    {
        Yii::$app->mailer->compose('_oldUsers', ['token' => $token])
            ->setFrom('no-reply@sketchlist.com')
            ->setTo($userEmail)
            ->setBcc(['vlad@sketchlist.com'])
            ->setSubject('Sketchlist Account Activation')
            ->send();
    }
Sasha
  • 8,521
  • 23
  • 91
  • 174
  • There are a few things you might be doing to produce this error. maybe you are exhausting the memory when creating a to large array of recipients. ? Try to get a single email at a time instead of all the emails in 1 try? – izk Mar 07 '16 at 20:41

3 Answers3

0

Try these in the function you are performing email.

ini_set("memory_limit", "-1");
set_time_limit(0);

If this doesn't help then follow this post

Community
  • 1
  • 1
ankitr
  • 5,992
  • 7
  • 47
  • 66
0

I want to show you how I would code this. Just in case it helps someone, as this is an old, unanswered, question.

There really isn't a need to use scenarios for this. It is such a simple task. Also, you don't need to hash on top of generateRandomString(). If your wanting to create a unique and random token, just use generateRandomKey() which defaults to 32 in length as well.

Also, use save(false) or update(false). The false turns validation off. When you are not using user input, and you yourself are programmatically entering the data based off controlled values, you should disable validation rules. I prefer to use update when I am doing this, as it makes more sense when we are working with an already existing model.

In your User IdentityInterface (common\models\User.php in advanced):

public function generateToken()
{
    $this->token = Yii::$app->security->generateRandomString();
}

public function getToken()
{
    return $this->token;
}

In your controller:

public function actionTest()
{
    $emails = ['email@example.com', 'email2@example.com', 'email3@example.com'];
    $users = Users::find()->where(['email' => $emails])->all();

    foreach ($users as $user)
    {
        $user->generateToken();

        if ( $user->update(false) )
        {
            Yii::$app->mailer->compose('_oldUsers', ['token' => $user->getToken()])
                ->setFrom(['no-reply@sketchlist.com' => 'Your Name'])
                ->setTo($user->email)
                ->setBcc(['vlad@sketchlist.com'])
                ->setSubject('Sketchlist Account Activation')
                ->send();
        }
    }
}
Wade
  • 3,757
  • 2
  • 32
  • 51
0

if you have memory problems in foreach loop you should try to retrieve data in batches like this retrieve for example 10 records in each iteration

foreach (Users::find()->where(['email' => $emails])->each(10) as $user) {

}
vasillis
  • 342
  • 4
  • 9