3

我正在使用 Swift Mailer 将邮件发送到相当大的电子邮件地址列表。消息是为每个收件人稍微定制的。一些占位符被替换为唯一的文本。

Swift_Message我认为多次重用一个实例会更有效(更少的垃圾收集等) 。我只是setTo()setBody()然后再次发送到下一个地址。

这适用于单个部分主体,通常只是 html。但是...当我想要第二部分(通常是文本)时,我可以这样做addPart(),但是下次在循环中,这将添加另一个部分,然后是另一个部分等...问题不会发生,setBody因为它会覆盖现有的身体。

有没有办法覆盖或删除现有部分?

谢谢

4

3 回答 3

1

为了扩展 Hendrik 和 Alasdair 的答案,我建议考虑使用装饰器插件。 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);

他们没有使用 detach 来迭代各个部分,而是查看如何addPartattach工作,而是简单地调用setChildren(array_merge($this->getChildren(), array($part)))

因此,您可以通过定义它们来手动设置子部件,这取代了调用addPartor attach

$message->setChildren([$htmlPart, $textPart]);

出于所有意图和目的,如果您要删除消息的一部分以及另一个收件人的不同内容(尽管是轻微的),那么您实际上是在创建一条新消息。$message = \Swift_Message::newInstance()编程逻辑可以通过在需要替换消息部分时调用来反映这一点。

于 2016-07-21T11:34:47.667 回答
0

根据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 没有任何影响。

于 2014-02-08T11:48:06.960 回答
0

@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

于 2015-07-06T16:12:57.813 回答