Issues (21)

src/Mail/MailConverter.php (1 issue)

Labels
Severity
1
<?php
2
3
namespace NotificationTracker\Mail;
4
5
use Illuminate\Support\Str;
6
use NotificationTracker\Models\TrackedChannel;
7
use Symfony\Component\Mime\Email;
8
use Symfony\Component\Mime\Part\Multipart\AlternativePart;
9
use Symfony\Component\Mime\Part\Multipart\MixedPart;
10
use Symfony\Component\Mime\Part\Multipart\RelatedPart;
11
use Symfony\Component\Mime\Part\TextPart;
12
13
class MailConverter
14
{
15
    protected bool $pixelAdded = false;
16
17 3
    public function __construct(
18
        protected TrackedChannel $tracker,
19
        protected Email          $email,
20
    ) {
21 3
    }
22
23 3
    public function format()
24
    {
25 3
        $emailBody = $this->email->getBody();
26
        if (
27 3
            ($emailBody instanceof (AlternativePart::class)) ||
0 ignored issues
show
A parse error occurred: Syntax error, unexpected '(' on line 27 at column 35
Loading history...
28
            ($emailBody instanceof (MixedPart::class))       ||
29 3
            ($emailBody instanceof (RelatedPart::class))
30
        ) {
31 3
            $newParts = [];
32 3
            foreach ($emailBody->getParts() as $part) {
33 3
                if ($part->getMediaSubtype() === 'html') {
34 3
                    $newParts[] = new TextPart(
35 3
                        $this->makeTrackable($part->getBody()),
36 3
                        $this->email->getHtmlCharset(),
37 3
                        $part->getMediaSubtype(),
38 3
                        null
39 3
                    );
40
41 3
                    continue;
42
                }
43
44 3
                if ($part->getMediaSubtype() === 'alternative') {
45
                    if (method_exists($part, 'getParts')) {
46
                        foreach ($part->getParts() as $subPart) {
47
                            if ($subPart->getMediaSubtype() == 'html') {
48
                                $newParts[] = new TextPart(
49
                                    $this->makeTrackable($subPart->getBody()),
50
                                    $this->email->getHtmlCharset(),
51
                                    $subPart->getMediaSubtype(),
52
                                    null
53
                                );
54
55
                                break;
56
                            }
57
                        }
58
                    }
59
60
                    continue;
61
                }
62
63 3
                $newParts[] = $part;
64
            }
65 3
            $this->email->setBody(new (get_class($emailBody))(...$newParts));
66
67 3
            return;
68
        }
69
70
        if ($emailBody->getMediaSubtype() == 'html') {
71
            $this->email->setBody(
72
                new TextPart(
73
                    $this->makeTrackable($emailBody->getBody()),
74
                    $this->email->getHtmlCharset(),
75
                    $emailBody->getMediaSubtype(),
76
                    null
77
                )
78
            );
79
80
            return;
81
        }
82
    }
83
84 3
    protected function makeTrackable(string $content): string
85
    {
86 3
        $content = $this->addPixelImage($content);
87
88
        // TODO: future extension: add other trackers like click?
89
90 3
        return $content;
91
    }
92
93 3
    protected function addPixelImage(string $content): string
94
    {
95 3
        if ($this->pixelAdded) {
96
            return $content;
97
        }
98
99
        do {
100 3
            $br = Str::random();
101 3
        } while (str_contains($content, $br));
102 3
        $content = str_replace("\n", $br, $content);
103
104 3
        if (preg_match('/^(.*<body[^>]*>)(.*)$/im', $content, $matches)) {
105 3
            $content = $matches[1] . $this->tracker->getPixelImageHtml() . $matches[2];
106
        } else {
107
            $content .= $this->tracker->getPixelImageHtml();
108
        }
109
110 3
        $content = str_replace($br, "\n", $content);
111
112 3
        $this->pixelAdded = true;
113
114 3
        return $content;
115
    }
116
}
117