Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I get HTML email content before sending in Yii2?

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);
    }
like image 261
Petra Barus Avatar asked Feb 26 '15 03:02

Petra Barus


1 Answers

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()

like image 150
Amoo Hesam Avatar answered Sep 22 '22 22:09

Amoo Hesam