我正在使用Swift Mailer将邮件发送到相当大的电子邮件地址列表。邮件会针对每个收件人进行轻微自定义。某些占位符将替换为唯一文本。
我认为多次重用一个Swift_Message
实例会更有效(更少的垃圾收集等)。我只是setTo()
,setBody()
并再次发送到下一个地址。
这适用于单个部分主体,通常只是 html。但。。。当我想要第二部分时,通常是文本,我可以做addPart()
,但下次循环时,这将添加另一部分,然后是另一部分等...... setBody
不会出现问题,因为这会覆盖现有正文。
有没有办法覆盖或删除现有零件?
谢谢
为了扩展亨德里克和阿拉斯代尔的答案,我建议考虑使用装饰器插件。http://swiftmailer.org/docs/plugins.html#using-the-decorator-plugin
该插件不会操作单个消息部分,而是为每个收件人替换整个消息的所需占位符。
例如
$message = 'Swift_Message::newInstance();
$replacements = array();
foreach ($users as $user) {
$replacements[$user['email']] = array(
'{username}' => $user['username'],
'{password}' => $user['password']
);
$message->addTo($user['email']);
}
$decorator = new 'Swift_Plugins_DecoratorPlugin($replacements);
$mailer->registerPlugin($decorator);
$message
->setSubject('Important notice for {username}')
->setBody(
"Hello {username}, we have reset your password to {password}'n" .
"Please log in and change it at your earliest convenience."
);
$message->addPart('{username} has been reset with the password: {password}', 'text/plain');
//..
$mailer->send($message);
此外,在 PHP 中,对象是通过引用传递的,因此您可以直接操作各个部件主体或内容类型。
$textPart = 'Swift_MimePart::newInstance('Hello World', 'text/plain');
$htmlPart = clone $textPart;
$htmlPart->setContentType('text/html');
$message->setTo('someone@example.com');
$message->attach($htmlPart);
$message->attach($textPart);
//...
$mailer->send($message);
$textPart->setBody('Something Else');
$htmlPart->setBody('Something Else');
$message->setTo('someone.else@example.com');
$mailer->send($message);
您还可以使用
$message->detach($textPart);
他们不使用分离来迭代零件,查看addPart
和attach
的工作方式,而是简单地调用setChildren(array_merge($this->getChildren(), array($part)))
因此,您可以通过定义子部分来手动设置子部分,这将替换调用addPart
或attach
。
$message->setChildren([$htmlPart, $textPart]);
出于所有意图和目的,如果您要删除消息的某些部分以及另一个收件人的不同内容(尽管只是轻微),那么您实际上是在创建新消息。编程逻辑可以通过在需要替换消息部分时调用$message = 'Swift_Message::newInstance()
来反映这一点。
根据 Swift Mailer Docs,实际上没有getBody()
这样的方法。
我建议您将包含占位符的实际消息模板存储在变量中,并在每次迭代中使用setBody()
将消息的完整正文替换为新收件人的解析模板,而不是尝试替换其中的一小部分。
我认为您的代码可能如下所示:
$template = '<h1>Hello {{firstname}}</h1>, ...';
$recipients = [
['firstname' => 'John', 'email' => 'john@example.com'],
...
];
$message = Swift_Message::newInstance('Subject here');
foreach ($recipients as $recipient) {
$body = str_replace('{{firstname}}', $recipient['firstname'], $template);
$message->setBody($body, 'text/html');
// continue building the mail object and send it ...
}
这样,您确实可以为每封邮件重复使用Swift_Message实例。尽管如果您在每次循环迭代中重用实例或创建一个新实例,这对 PHP 没有任何影响。
@tetranz 如@Hendrik大纲,您可以使用$message->getBody()
和$message->setBody($body)
作为主体部分。
您可以通过与子级相同的方法访问(您提到的多部分addPart()
)部分。 即类似于:
$children = $message->getChildren();
foreach($children as &$child) {
$c_body = $child->getBody();
//manipulate as you wish
$child->setBody($c_body);
}
$message->setChildren($children);
这适用于 Swift v5.0.1