I want to replace all links in the HTML email with tracker. As far as I know there is this EVENT_BEFORE_SEND
event. So I created some behavior that can be used like below
$mailer = \Yii::$app->mailer;
/* @var $mailer \yii\mail\BaseMailer */
$mailer->attachBehavior('archiver', [
'class' => \app\MailTracker::class
]);
Here's the content of the MyTracker
class.
class MailTracker extends Behavior {
public function events() {
return [
\yii\mail\BaseMailer::EVENT_BEFORE_SEND => 'trackMail',
];
}
/**
* @param \yii\mail\MailEvent $event
*/
public function trackMail($event) {
$message = $event->message;
$htmlOutput = $this->how_do_i_get_the_html_output();
$changedOutput = $this->changeLinkWithTracker($htmlOutput);
$message->getHtmlBody($changedOutput);
}
}
The problem now is \yii\mail\BaseMailer
doesn't provide method to get the HTML output rendered before sending.
How to do this?
UPDATE
The only way I can get this is through this hacky way.
/* @var $message \yii\swiftmailer\Message */
if ($message instanceof \yii\swiftmailer\Message) {
$swiftMessage = $message->getSwiftMessage();
$r = new \ReflectionObject($swiftMessage);
$parentClassThatHasBody = $r->getParentClass()
->getParentClass()
->getParentClass(); //\Swift_Mime_SimpleMimeEntity
$body = $parentClassThatHasBody->getProperty('_immediateChildren');
$body->setAccessible(true);
$children = $body->getValue($swiftMessage);
foreach ($children as $child) {
if ($child instanceof \Swift_MimePart &&
$child->getContentType() == 'text/html') {
$html = $child->getBody();
break;
}
}
print_r($html);
}
One approach that I've found is to use render()
instead of compose()
.
So we need to render the message string before sending and then compose it again.
$string = Yii::$app->mailer->render('path/to/view', ['params' => 'foo'], 'path/to/layout');
Yii doc: yii\mail\BaseMailer::render()
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With