<p>Yes, you can pass through the customer ID to your queue job, then the job itself can look up the customer and send the email.</p>
<p>Here's a super-simple example console controller action method that passes through a user ID to a queue job class called <code>SendEmail</code>:</p>
<pre><code>public function actionSend()
{
    $userIds = User::find()
        -&gt;status(User::STATUS_ACTIVE)
        -&gt;ids();
    
    foreach ($userIds as $userId) {
        Craft::$app-&gt;getQueue()-&gt;delay(0)-&gt;push(new SendEmail([
            'userId' =&gt; $userId
        ])); 
    }
}
</code></pre>
<p>Then here's the <code>SendEmail</code> job class. This has a property called <code>userId</code> which represents the variable that's passed in when the new instance of the <code>SendEmail</code> class is created in the code example above. You can use that <code>userId</code> property to fetch the User object, and then send an email:</p>
<pre><code>class SendEmail extends BaseJob
{
    // Public Properties
    // =========================================================================

    /**
     * @var string
     */
    public $userId;

    // Public Methods
    // =========================================================================

    /**
     * @param QueueInterface|Queue $queue
     * @return void
     */
    public function execute($queue)
    {  
        $user = Craft::$app-&gt;getUsers()-&gt;getUserById($this-&gt;userId);

        if ($user) {
            Craft::$app-&gt;getMailer()
                -&gt;composeFromKey('my-plugin_email_key, [
                    'firstName' =&gt; $user-&gt;firstName,
                ])
                -&gt;setTo($user)
                -&gt;send();
        }

        $this-&gt;setProgress($queue, 1);
    }

    // Protected Methods
    // =========================================================================

    /**
     * @return string
     */
    protected function defaultDescription(): string
    {
        return Craft::t(
            'my-plugin',
            'Sending email for user Id {userId}',
            [
                'userId' =&gt; $this-&gt;userId,
            ]
        );
    }
}
</code></pre>
<p>I've left out the <code>namespace</code> and <code>use</code> statements etc., but hopefully that gives you an idea of how this works.</p>
<p>You'll need to register the email you want to send in your plugin/module's base class. I do this via a <code>_registerEmailMessages</code> class called from the plugin/module's <code>init</code> method:</p>
<pre><code>public function init()
{
    parent::init();
    self::$plugin = $this;

    // Do a bunch of init stuff
    $this-&gt;_registerEmailMessages();
}

private function _registerEmailMessages()
{
    Event::on(
        SystemMessages::class,
        SystemMessages::EVENT_REGISTER_MESSAGES,
        function(RegisterEmailMessagesEvent $event) {
            $event-&gt;messages = array_merge($event-&gt;messages, [
                [
                    'key' =&gt; 'my-plugin_email_key',
                    'heading' =&gt; Craft::t('my-plugin', 'my-plugin_email_key_heading'),
                    'subject' =&gt; Craft::t('my-plugin', 'my-plugin_email_key_subject'),
                    'body' =&gt; Craft::t('my-plugin', 'my-plugin_email_key_body'),
                ],
           ]);
        }
    );
}
</code></pre>

CC BY-SA 4.0
2021-06-23T15:36:07.110Z
I just came on to post my own answer, but your's is definitely better presented!
  
Can I check the line:
`Craft::$app->getQueue()->delay(0)->push(new SendEmail([ 'userId' => $userId ]));`
  Would this process the job when it's added?
Jaytrix
CC BY-SA 4.0
2021-06-24T07:29:13.443Z
That depends on how you have your queue set up. I use the Async Queue plugin from Oliver Stark (https://github.com/ostark/craft-async-queue) to run the queue using background processes, so in my setup it wouldn't run straight away. In a stock setup, I believe it would be processed as soon as the next request (i.e. page load) to Craft was made.
Martin Spain
CC BY-SA 4.0
2021-06-22T08:56:39.220Z
2021-06-24T07:29:55.037Z
2021-06-24T07:29:55.037Z
Martin Spain
<p>Is there a way to parse a variable to a queue job? I want to re-send some Craft commerce emails via a cron job, so have created a console controller for the cron job to run a command against. This then will get all the customers to email and create a queued job (I'd like the jobs to run automatically somehow).
To save having one big job to email 100's of customers, I thought to create 1 job per customer ... only way I can think is to have the controller parse the customer email through each new job it creates.</p>
<p>I'm currently testing with sending a email to a sandbox email account in 1 queued job that loops through a <code>range</code> of 1-10. This method is becoming too unreliable where I might get emails 1-5 out of 10, or 1-5 then 15-20 in a loop of 20. The test I've just run only sent 18-20 out of 20.
When I've tested with creating a job per email, I get a consistent amount of emails.</p>

<craft3><queue><console><commands>
Parse variable to new queue job
# Parse variable to new queue job

(Asked by: username_0 on 2021-06-21)

Is there a way to parse a variable to a queue job? I want to re-send some Craft commerce emails via a cron job, so have created a console controller for the cron job to run a command against. This then will get all the customers to email and create a queued job (I'd like the jobs to run automatically somehow).
To save having one big job to email 100's of customers, I thought to create 1 job per customer ... only way I can think is to have the controller parse the customer email through each new job it creates.

I'm currently testing with sending a email to a sandbox email account in 1 queued job that loops through a `range` of 1-10. This method is becoming too unreliable where I might get emails 1-5 out of 10, or 1-5 then 15-20 in a loop of 20. The test I've just run only sent 18-20 out of 20.
When I've tested with creating a job per email, I get a consistent amount of emails.

**Tags:** craft3, queue, console, commands

---

## 1 answers

### Answer by username_1 on 2021-06-22. Score: 2

Yes, you can pass through the customer ID to your queue job, then the job itself can look up the customer and send the email.
Here's a super-simple example console controller action method that passes through a user ID to a queue job class called SendEmail:
public function actionSend()
{
    $userIds = User::find()
        ->status(User::STATUS_ACTIVE)
        ->ids();
    
    foreach ($userIds as $userId) {
        Craft::$app->getQueue()->delay(0)->push(new SendEmail([
            'userId' => $userId
        ])); 
    }
}

Then here's the SendEmail job class. This has a property called userId which represents the variable that's passed in when the new instance of the SendEmail class is created in the code example above. You can use that userId property to fetch the User object, and then send an email:
class SendEmail extends BaseJob
{
    // Public Properties
    // =========================================================================

    /**
     * @var string
     */
    public $userId;

    // Public Methods
    // =========================================================================

    /**
     * @param QueueInterface|Queue $queue
     * @return void
     */
    public function execute($queue)
    {  
        $user = Craft::$app->getUsers()->getUserById($this->userId);

        if ($user) {
            Craft::$app->getMailer()
                ->composeFromKey('my-plugin_email_key, [
                    'firstName' => $user->firstName,
                ])
                ->setTo($user)
                ->send();
        }

        $this->setProgress($queue, 1);
    }

    // Protected Methods
    // =========================================================================

    /**
     * @return string
     */
    protected function defaultDescription(): string
    {
        return Craft::t(
            'my-plugin',
            'Sending email for user Id {userId}',
            [
                'userId' => $this->userId,
            ]
        );
    }
}

I've left out the namespace and use statements etc., but hopefully that gives you an idea of how this works.
You'll need to register the email you want to send in your plugin/module's base class. I do this via a _registerEmailMessages class called from the plugin/module's init method:
public function init()
{
    parent::init();
    self::$plugin = $this;

    // Do a bunch of init stuff
    $this->_registerEmailMessages();
}

private function _registerEmailMessages()
{
    Event::on(
        SystemMessages::class,
        SystemMessages::EVENT_REGISTER_MESSAGES,
        function(RegisterEmailMessagesEvent $event) {
            $event->messages = array_merge($event->messages, [
                [
                    'key' => 'my-plugin_email_key',
                    'heading' => Craft::t('my-plugin', 'my-plugin_email_key_heading'),
                    'subject' => Craft::t('my-plugin', 'my-plugin_email_key_subject'),
                    'body' => Craft::t('my-plugin', 'my-plugin_email_key_body'),
                ],
           ]);
        }
    );
}

> **Comments:**
> **username_0**: I just came on to post my own answer, but your's is definitely better presented!    Can I check the line: `Craft::$app->getQueue()->delay(0)->push(new SendEmail([ 'userId' => $userId ]));`   Would this process the job when it's added?  
> **username_1**: That depends on how you have your queue set up. I use the Async Queue plugin from Oliver Stark (https://github.com/ostark/craft-async-queue) to run the queue using background processes, so in my setup it wouldn't run straight away. In a stock setup, I believe it would be processed as soon as the next request (i.e. page load) to Craft was made.  

---

