You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

CakePHP 4自定义邮件传输中获取自定义变量(Postmark批量邮件)

解决Postmark批量邮件个性化内容的问题

方法1:在Mailer中预渲染每个收件人的邮件内容

既然自定义Transport无法直接访问NewsletterMailer里的ViewVars,你可以提前在Mailer层为每个订阅者生成渲染好的个性化HTML内容,再传递给Transport处理批量发送。

修改NewsletterMailer.php

// NewsletterMailer.php
$viewBuilder = $this->viewBuilder()
    ->setTemplate('newsletter_mail')
    ->setLayout('default');

// 遍历订阅者,生成每封邮件的个性化内容
$batchEmails = [];
foreach ($subscribers->all() as $subscriber) {
    // 为当前订阅者设置专属ViewVars
    $viewBuilder->setVars([
        'company' => $company,
        'subscriber' => $subscriber // 订阅者信息用于个性化展示
    ]);
    // 渲染HTML内容
    $htmlContent = $this->getView()->render($viewBuilder);
    
    $batchEmails[] = [
        'To' => $subscriber->email,
        'From' => "{$newsletter->sender} <{$company->companyname}>",
        'Subject' => $newsletter->name,
        'HtmlBody' => $htmlContent
    ];
}

// 将预生成的邮件数组传递给Transport
return $this
    ->setEmailFormat('html')
    ->setProfile('newsletter')
    ->set(['batch_emails' => $batchEmails]);

修改NewslettersTransport.php

在Transport的send()方法中直接获取预生成的邮件数据,按Postmark要求拆分批量发送:

// NewslettersTransport.php
public function send(Email $email)
{
    $batchEmails = $email->get('batch_emails');
    // 按每500封一组拆分
    $batches = array_chunk($batchEmails, 500);
    
    foreach ($batches as $batch) {
        // 调用Postmark Batch API发送
        $this->postmarkClient->sendEmailBatch($batch);
    }
    
    return true;
}

方法2:让Transport直接访问View配置与ViewVars

如果希望在Transport中动态渲染内容,可以通过Email对象传递ViewBuilder和基础ViewVars,在Transport层完成个性化渲染。

修改NewsletterMailer.php

// NewsletterMailer.php
$viewBuilder = $this->viewBuilder()
    ->setTemplate('newsletter_mail')
    ->setLayout('default')
    ->setVars([
        'company' => $company
    ]);

return $this
    ->setEmailFormat('html')
    ->setTo($subscribers->all()->toArray())
    ->setFrom([$newsletter->sender => $company->companyname])
    ->setSubject($newsletter->name)
    ->setProfile('newsletter')
    ->set([
        'view_builder' => $viewBuilder,
        'base_view_vars' => $viewBuilder->getVars()
    ]);

修改NewslettersTransport.php

初始化View实例,为每个收件人合并ViewVars并渲染:

// NewslettersTransport.php
use Cake\View\View;
use Cake\ORM\TableRegistry;

public function send(Email $email)
{
    $viewBuilder = $email->get('view_builder');
    $baseVars = $email->get('base_view_vars');
    $toRecipients = $email->getTo();
    $from = $email->getFrom();
    $subject = $email->getSubject();
    
    $batchEmails = [];
    foreach ($toRecipients as $emailAddress => $name) {
        // 根据邮箱获取订阅者信息(需自行实现查询逻辑)
        $subscriberTable = TableRegistry::getTableLocator()->get('Subscribers');
        $subscriber = $subscriberTable->findByEmail($emailAddress)->first();
        
        // 合并基础变量与订阅者专属变量
        $viewBuilder->setVars(array_merge($baseVars, [
            'subscriber' => $subscriber
        ]));
        
        // 初始化View并渲染内容
        $view = new View();
        $htmlContent = $view->render($viewBuilder);
        
        $batchEmails[] = [
            'To' => $emailAddress,
            'From' => key($from) . ' <' . current($from) . '>',
            'Subject' => $subject,
            'HtmlBody' => $htmlContent
        ];
    }
    
    // 拆分批量并发送
    $batches = array_chunk($batchEmails, 500);
    foreach ($batches as $batch) {
        $this->postmarkClient->sendEmailBatch($batch);
    }
    
    return true;
}

方法3:利用Postmark官方模板功能

如果你的Postmark账户已创建模板,可以直接传递模板变量,让Postmark平台帮你完成个性化渲染,省去本地视图处理步骤。

修改NewsletterMailer.php

// NewsletterMailer.php
return $this
    ->setTo($subscribers->all()->toArray())
    ->setFrom([$newsletter->sender => $company->companyname])
    ->setSubject($newsletter->name)
    ->setProfile('newsletter')
    ->set([
        'postmark_template_id' => '你的Postmark模板ID',
        'base_template_vars' => [
            'company_name' => $company->companyname
            // 其他基础模板变量
        ]
    ]);

修改NewslettersTransport.php

// NewslettersTransport.php
use Cake\ORM\TableRegistry;

public function send(Email $email)
{
    $templateId = $email->get('postmark_template_id');
    $baseVars = $email->get('base_template_vars');
    $toRecipients = $email->getTo();
    $from = $email->getFrom();
    
    $batchEmails = [];
    foreach ($toRecipients as $emailAddress => $name) {
        $subscriberTable = TableRegistry::getTableLocator()->get('Subscribers');
        $subscriber = $subscriberTable->findByEmail($emailAddress)->first();
        
        $batchEmails[] = [
            'To' => $emailAddress,
            'From' => key($from) . ' <' . current($from) . '>',
            'TemplateId' => $templateId,
            'TemplateModel' => array_merge($baseVars, [
                'subscriber_name' => $subscriber->name
                // 其他订阅者专属模板变量
            ])
        ];
    }
    
    $batches = array_chunk($batchEmails, 500);
    foreach ($batches as $batch) {
        $this->postmarkClient->sendEmailBatch($batch);
    }
    
    return true;
}

内容的提问来源于stack exchange,提问作者DvL

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 01:07:46