Issues (1)

src/Message.php (1 issue)

1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Mailer\Symfony;
6
7
use DateTimeImmutable;
8
use DateTimeInterface;
9
use Stringable;
10
use Symfony\Component\Mime\Address;
11
use Symfony\Component\Mime\Email;
12
use Symfony\Component\Mime\Header\HeaderInterface;
13
use Throwable;
14
use Yiisoft\Mailer\File;
15
use Yiisoft\Mailer\MessageInterface;
16
17
use function is_string;
18
19
/**
20
 * Message implements a message class based on Symfony Mailer.
21
 *
22
 * @see https://symfony.com/doc/current/mailer.html#creating-sending-messages
23
 * @see Mailer
24
 */
25
final class Message implements MessageInterface, Stringable
26
{
27
    private Email $email;
28
    private ?Throwable $error = null;
29
    private string $charset = 'utf-8';
30
31 57
    public function __construct()
32
    {
33 57
        $this->email = new Email();
34
    }
35
36 56
    public function __clone()
37
    {
38 56
        $this->email = clone $this->email;
39
    }
40
41 3
    public function getCharset(): string
42
    {
43 3
        return $this->charset;
44
    }
45
46 5
    public function withCharset(string $charset): self
47
    {
48 5
        $new = clone $this;
49 5
        $new->charset = $charset;
50 5
        return $new;
51
    }
52
53 5
    public function getFrom(): array|string
54
    {
55 5
        return $this->convertAddressesToStrings($this->email->getFrom());
56
    }
57
58 21
    public function withFrom($from): self
59
    {
60 21
        $new = clone $this;
61 21
        $new->email->from(...$this->convertStringsToAddresses($from));
62 21
        return $new;
63
    }
64
65 5
    public function getTo(): array|string
66
    {
67 5
        return $this->convertAddressesToStrings($this->email->getTo());
68
    }
69
70 21
    public function withTo($to): self
71
    {
72 21
        $new = clone $this;
73 21
        $new->email->to(...$this->convertStringsToAddresses($to));
74 21
        return $new;
75
    }
76
77 5
    public function getReplyTo(): array|string
78
    {
79 5
        return $this->convertAddressesToStrings($this->email->getReplyTo());
80
    }
81
82 6
    public function withReplyTo($replyTo): self
83
    {
84 6
        $new = clone $this;
85 6
        $new->email->replyTo(...$this->convertStringsToAddresses($replyTo));
86 6
        return $new;
87
    }
88
89 5
    public function getCc(): array|string
90
    {
91 5
        return $this->convertAddressesToStrings($this->email->getCc());
92
    }
93
94 6
    public function withCc($cc): self
95
    {
96 6
        $new = clone $this;
97 6
        $new->email->cc(...$this->convertStringsToAddresses($cc));
98 6
        return $new;
99
    }
100
101 5
    public function getBcc(): array|string
102
    {
103 5
        return $this->convertAddressesToStrings($this->email->getBcc());
104
    }
105
106 5
    public function withBcc($bcc): self
107
    {
108 5
        $new = clone $this;
109 5
        $new->email->bcc(...$this->convertStringsToAddresses($bcc));
110 5
        return $new;
111
    }
112
113 2
    public function getSubject(): string
114
    {
115 2
        return (string) $this->email->getSubject();
116
    }
117
118 16
    public function withSubject(string $subject): self
119
    {
120 16
        $new = clone $this;
121 16
        $new->email->subject($subject);
122 16
        return $new;
123
    }
124
125 2
    public function getDate(): ?DateTimeImmutable
126
    {
127 2
        return $this->email->getDate();
128
    }
129
130 3
    public function withDate(DateTimeInterface $date): self
131
    {
132 3
        $new = clone $this;
133 3
        $new->email->date($date);
134 3
        return $new;
135
    }
136
137 6
    public function getPriority(): int
138
    {
139 6
        return $this->email->getPriority();
140
    }
141
142 7
    public function withPriority(int $priority): self
143
    {
144 7
        $new = clone $this;
145 7
        $new->email->priority($priority);
146 7
        return $new;
147
    }
148
149 2
    public function getReturnPath(): string
150
    {
151 2
        $returnPath = $this->email->getReturnPath();
152 2
        return $returnPath === null ? '' : $returnPath->getAddress();
153
    }
154
155 3
    public function withReturnPath(string $address): self
156
    {
157 3
        $new = clone $this;
158 3
        $new->email->returnPath($address);
159 3
        return $new;
160
    }
161
162 2
    public function getSender(): string
163
    {
164 2
        $sender = $this->email->getSender();
165 2
        return $sender === null ? '' : $sender->getAddress();
166
    }
167
168 4
    public function withSender(string $address): self
169
    {
170 4
        $new = clone $this;
171 4
        $new->email->sender($address);
172 4
        return $new;
173
    }
174
175 4
    public function getTextBody(): string
176
    {
177 4
        return (string) $this->email->getTextBody();
178
    }
179
180 16
    public function withTextBody(string $text): self
181
    {
182 16
        $new = clone $this;
183 16
        $new->email->text($text, $this->charset);
184 16
        return $new;
185
    }
186
187 2
    public function getHtmlBody(): string
188
    {
189 2
        return (string) $this->email->getHtmlBody();
190
    }
191
192 6
    public function withHtmlBody(string $html): self
193
    {
194 6
        $new = clone $this;
195 6
        $new->email->html($html, $this->charset);
196 6
        return $new;
197
    }
198
199 3
    public function withAttached(File $file): self
200
    {
201 3
        $new = clone $this;
202
203 3
        $file->path() === null
204 2
            ? $new->email->attach((string) $file->content(), $file->name(), $file->contentType())
205 1
            : $new->email->attachFromPath($file->path(), $file->name(), $file->contentType())
206 3
        ;
207
208 3
        return $new;
209
    }
210
211 3
    public function withEmbedded(File $file): self
212
    {
213 3
        $new = clone $this;
214
215 3
        $file->path() === null
216 2
            ? $new->email->embed((string) $file->content(), $file->name(), $file->contentType())
217 1
            : $new->email->embedFromPath($file->path(), $file->name(), $file->contentType())
218 3
        ;
219
220 3
        return $new;
221
    }
222
223 6
    public function getHeader(string $name): array
224
    {
225 6
        $headers = $this->email->getHeaders();
226
227 6
        if (!$headers->has($name)) {
228 1
            return [];
229
        }
230
231 5
        $values = [];
232
233
        /** @var HeaderInterface $header */
234 5
        foreach ($headers->all($name) as $header) {
235 5
            $values[] = $header->getBodyAsString();
236
        }
237
238 5
        return $values;
239
    }
240
241 2
    public function withAddedHeader(string $name, string $value): self
242
    {
243 2
        $new = clone $this;
244 2
        $new->email
245 2
            ->getHeaders()
246 2
            ->addTextHeader($name, $value);
247 2
        return $new;
248
    }
249
250 6
    public function withHeader(string $name, $value): self
251
    {
252 6
        $new = clone $this;
253 6
        $headers = $new->email->getHeaders();
254
255 6
        if ($headers->has($name)) {
256 1
            $headers->remove($name);
257
        }
258
259 6
        foreach ((array) $value as $v) {
260 6
            $headers->addTextHeader($name, $v);
261
        }
262
263 6
        return $new;
264
    }
265
266 3
    public function withHeaders(array $headers): self
267
    {
268 3
        $new = clone $this;
269
270 3
        foreach ($headers as $name => $value) {
271 2
            $new = $new->withHeader($name, $value);
272
        }
273
274 3
        return $new;
275
    }
276
277 2
    public function getError(): ?Throwable
278
    {
279 2
        return $this->error;
280
    }
281
282 2
    public function withError(Throwable $e): self
283
    {
284 2
        $new = clone $this;
285 2
        $new->error = $e;
286 2
        return $new;
287
    }
288
289 5
    public function __toString(): string
290
    {
291 5
        return $this->email->toString();
292
    }
293
294
    /**
295
     * Returns a Symfony email instance.
296
     *
297
     * @return Email Symfony email instance.
298
     */
299 12
    public function getSymfonyEmail(): Email
300
    {
301 12
        return $this->email;
302
    }
303
304
    /**
305
     * Converts address instances to their string representations.
306
     *
307
     * @param Address[] $addresses
308
     *
309
     * @return array<string, string>|string
310
     */
311 21
    private function convertAddressesToStrings(array $addresses): array|string
312
    {
313 21
        $strings = [];
314
315 21
        foreach ($addresses as $address) {
316 20
            $strings[$address->getAddress()] = $address->getName();
317
        }
318
319 21
        return empty($strings) ? '' : $strings;
320
    }
321
322
    /**
323
     * Converts string representations of address to their instances.
324
     *
325
     * @param array<int|string, string>|string $strings
326
     *
327
     * @return Address[]
328
     */
329 37
    private function convertStringsToAddresses(array|string $strings): array
330
    {
331 37
        if (is_string($strings)) {
0 ignored issues
show
The condition is_string($strings) is always false.
Loading history...
332 22
            return [new Address($strings)];
333
        }
334
335 15
        $addresses = [];
336
337 15
        foreach ($strings as $address => $name) {
338 15
            if (!is_string($address)) {
339
                // email address without name
340 5
                $addresses[] = new Address($name);
341 5
                continue;
342
            }
343
344 10
            $addresses[] = new Address($address, $name);
345
        }
346
347 15
        return $addresses;
348
    }
349
}
350