Issues (11)

src/Message.php (2 issues)

1
<?php
2
3
namespace Kodus\Mail;
4
5
use DateTimeImmutable;
6
use DateTimeInterface;
7
use InvalidArgumentException;
8
9
/**
10
 * This class represents an e-mail Message.
11
 */
12
class Message
13
{
14
    /**
15
     * @var Address[]
16
     */
17
    private $to = [];
18
19
    /**
20
     * @var Address[]
21
     */
22
    private $from = [];
23
24
    /**
25
     * @var Address
26
     */
27
    private $sender;
28
29
    /**
30
     * @var Address[]
31
     */
32
    private $cc = [];
33
34
    /**
35
     * @var Address[]
36
     */
37
    private $bcc = [];
38
39
    /**
40
     * @var Address[]
41
     */
42
    private $reply_to = [];
43
44
    /**
45
     * @var string
46
     */
47
    private $subject;
48
49
    /**
50
     * @var DateTimeInterface
51
     */
52
    private $date;
53
54
    /**
55
     * @var string|null
56
     */
57
    private $text;
58
59
    /**
60
     * @var string|null
61
     */
62
    private $html;
63
64
    /**
65
     * @var Attachment[]
66
     */
67
    private $attachments = [];
68
69
    /**
70
     * @var InlineAttachment[]
71
     */
72
    private $inline_attachments = [];
73
74
    /**
75
     * @var Header[]
76
     */
77
    private $headers = [];
78
79
    /**
80
     * @param Address|Address[] $to
81
     * @param Address|Address[] $from
82
     * @param string            $subject
83
     * @param string|null       $text
84 19
     * @param string|null       $html
85
     */
86 19
    public function __construct($to, $from, string $subject, ?string $text, ?string $html = null)
87 19
    {
88 19
        $this->setTo($to);
89 19
        $this->setFrom($from);
90 19
        $this->setSubject($subject);
91 19
        $this->setText($text);
92 19
        $this->setHTML($html);
93
        $this->setDate(time());
94
    }
95
96
    /**
97 17
     * @return Address[]
98
     */
99 17
    public function getTo(): array
100
    {
101
        return $this->to;
102
    }
103
104
    /**
105
     * This field contains the identity of the primary recipients of the Message.
106
     *
107 19
     * @param Address|Address[] $address
108
     */
109 19
    public function setTo($address): void
110 19
    {
111
        $this->to = is_array($address) ? $address : [$address];
112
    }
113
114
    /**
115
     * @param Address|Address[] $address
116
     */
117
    public function addTo($address): void
118
    {
119
        $this->to = array_merge($this->to, is_array($address) ? $address : [$address]);
120
    }
121
122
    /**
123 17
     * @return Address[]
124
     */
125 17
    public function getFrom(): array
126
    {
127
        return $this->from;
128
    }
129
130
    /**
131
     * Specifies the author(s) of the message; that is, the mailbox(es)
132
     * of the person(s) or system(s) responsible for the writing of the
133
     * message.
134
     *
135 19
     * @param Address|Address[] $address
136
     */
137 19
    public function setFrom($address): void
138 19
    {
139
        $this->from = is_array($address) ? $address : [$address];
140
    }
141
142
    /**
143
     * @param Address|Address[] $address
144
     */
145
    public function addFrom($address): void
146
    {
147
        $this->from = array_merge($this->from, is_array($address) ? $address : [$address]);
148
    }
149
150
    /**
151
     * Return the Sender (if any)
152
     *
153 15
     * @return Address|null
154
     */
155 15
    public function getSender(): ?Address
156 2
    {
157
        if ($this->sender) {
158
            return $this->sender;
159 14
        }
160 2
161
        if (count($this->from) > 1) {
162
            return $this->from[0];
163 13
        }
164
165
        return null;
166
    }
167
168
    /**
169
     * Specifies the mailbox of the agent responsible for the actual transmission of the message.
170
     *
171
     * This field contains the authenticated identity of the "agent" (person, system or process)
172
     * that sends the message. It is intended for use when the sender is *not* the author of
173
     * the message, or to indicate who among a group of authors actually sent the message.
174
     *
175
     * If the contents of this field would be completely redundant with the "From" field, then
176
     * the "Sender" field need not be present and its use is discouraged, though still permitted.
177
     *
178
     * In particular, the "Sender" field *must* be present if it is *not* the same as the "From" Field.
179
     *
180 2
     * @param Address|null $sender
181
     */
182 2
    public function setSender(?Address $sender): void
183 2
    {
184
        $this->sender = $sender;
185
    }
186
187
    /**
188 17
     * @return Address[]
189
     */
190 17
    public function getCC(): array
191
    {
192
        return $this->cc;
193
    }
194
195
    /**
196
     * This field contains the identity of any secondary recipients of the Message.
197
     *
198
     * @param Address|Address[] $address
199
     */
200
    public function setCC($address): void
201
    {
202
        $this->cc = is_array($address) ? $address : [$address];
203
    }
204
205
    /**
206 2
     * @param Address|Address[] $address
207
     */
208 2
    public function addCC($address): void
209 2
    {
210
        $this->cc = array_merge($this->cc, is_array($address) ? $address : [$address]);
211
    }
212
213
    /**
214 17
     * @return Address[]
215
     */
216 17
    public function getBCC(): array
217
    {
218
        return $this->bcc;
219
    }
220
221
    /**
222
     * This field contains the identity of additional recipients of the message.
223
     *
224
     * The contents of this field are not included in copies of the Message sent to the primary
225
     * or secondary recipients, e.g. the "To" and "CC" fields.
226
     *
227
     * Some systems may choose to include the text of the "BCC" field only in the author's copy,
228
     * while others may also include it in the text sent to all those indicated in the "BCC" list.
229
     *
230
     * @param Address|Address[] $address
231
     */
232
    public function setBCC($address): void
233
    {
234
        $this->bcc = is_array($address) ? $address : [$address];
235
    }
236
237
    /**
238 2
     * @param Address|Address[] $address
239
     */
240 2
    public function addBCC($address): void
241 2
    {
242
        $this->bcc = array_merge($this->bcc, is_array($address) ? $address : [$address]);
243
    }
244
245
    /**
246 15
     * @return Address[]
247
     */
248 15
    public function getReplyTo(): array
249
    {
250
        return $this->reply_to;
251
    }
252
253
    /**
254
     * @param Address|Address[] $address
255
     */
256
    public function setReplyTo($address): void
257
    {
258
        $this->reply_to = is_array($address) ? $address : [$address];
259
    }
260
261
    /**
262
     * @param Address|Address[] $address
263
     */
264
    public function addReplyTo($address): void
265
    {
266
        $this->reply_to = array_merge($this->reply_to, is_array($address) ? $address : [$address]);
267
    }
268
269
    /**
270 17
     * @return string
271
     */
272 17
    public function getSubject(): string
273
    {
274
        return $this->subject;
275
    }
276
277
    /**
278 19
     * @param string $subject
279
     */
280 19
    public function setSubject(string $subject): void
281 19
    {
282
        $this->subject = $subject;
283
    }
284
285
    /**
286 15
     * @return DateTimeInterface
287
     */
288 15
    public function getDate(): DateTimeInterface
289
    {
290
        return $this->date;
291
    }
292
293
    /**
294 19
     * @param int|string|DateTimeInterface $date DateTime in Sender's timezone (or a UNIX integer timestamp;
295
     *                                           or a string that is compatible with the strtotime() function)
296 19
     */
297 19
    public function setDate($date): void
298 19
    {
299 19
        if ($date instanceof DateTimeInterface) {
300
            $this->date = $date;
301
        } elseif (is_int($date)) {
302
            $this->date = DateTimeImmutable::createFromFormat("U", (string) $date)
303
                ->setTimezone(timezone_open(date_default_timezone_get()));
304 15
        } elseif (is_string($date)) {
0 ignored issues
show
The condition is_string($date) is always true.
Loading history...
305
            $this->date = DateTimeImmutable::createFromFormat("U", (string) strtotime($date))
306 15
                ->setTimezone(timezone_open(date_default_timezone_get()));
307
        } else {
308
            throw new InvalidArgumentException("invalid date given: " . var_export($date, true));
309
        }
310
    }
311
312
    /**
313
     * @return string|null plain text message body
314 19
     */
315
    public function getText(): ?string
316 19
    {
317 1
        return $this->text;
318
    }
319
320 19
    /**
321 19
     * @param string|null $text plain text message body
322
     *
323
     * @throws InvalidArgumentException if the given message body is not valid UTF-8
324
     */
325
    public function setText(?string $text): void
326 15
    {
327
        if (preg_match('//u', $text ?? '') !== 1) {
328 15
            throw new InvalidArgumentException("message body contains an invalid UTF-8 byte sequence");
329
        }
330
331
        $this->text = $text;
332
    }
333
334
    /**
335
     * @return string|null HTML message body
336 19
     */
337
    public function getHTML(): ?string
338 19
    {
339 1
        return $this->html;
340
    }
341
342 19
    /**
343 19
     * @param string|null $html HTML message body
344
     *
345
     * @throws InvalidArgumentException if the given message body is not valid UTF-8
346
     */
347
    public function setHTML(?string $html): void
348 15
    {
349
        if (preg_match('//u', $html ?? '') !== 1) {
350 15
            throw new InvalidArgumentException("message body contains an invalid UTF-8 byte sequence");
351
        }
352
353
        $this->html = $html;
354
    }
355
356 7
    /**
357
     * @return Attachment[]
358 7
     */
359 7
    public function getAttachments(): array
360
    {
361
        return $this->attachments;
362
    }
363
364 15
    /**
365
     * @param Attachment $attachment
366 15
     */
367
    public function addAttachment(Attachment $attachment): void
368
    {
369
        $this->attachments[] = $attachment;
370
    }
371
372
    /**
373
     * @return InlineAttachment[]
374
     */
375
    public function getInlineAttachments(): array
376
    {
377
        return $this->inline_attachments;
378
    }
379
380
    /**
381
     * Add an inline Attachment, e.g. an image you wish to display in the HTML body of your Message.
382
     *
383
     * This method returns a URI for the inline Attachment - you should substitute a placeholder,
384
     * e.g. for the `src` attribute of an `img` tag, in the body of your HTML Message content -
385 5
     * for example:
386
     *
387 5
     *     $html = '<img src="#logo-image"/>';
388
     *     $uri = $message->addInlineAttachment(Attachment::fromFile(__DIR__ . '/logo.png'));
389 5
     *     $html = strtr($html, ["#logo-image" => $uri]);
390
     *     $message->setHTML($html);
391 5
     *
392
     * @param Attachment $attachment
393
     *
394
     * @return string inline Attachment URI
395
     */
396
    public function addInlineAttachment(Attachment $attachment): string
397 16
    {
398
        $inline_attachment = new InlineAttachment($attachment);
399 16
400
        $this->inline_attachments[] = $inline_attachment;
401 16
402 3
        return "cid:" . $inline_attachment->getContentID();
403 16
    }
404
405 16
    /**
406
     * @return Header[]
407
     */
408
    public function getHeaders(): array
409
    {
410
        $all_headers = [];
411
412
        foreach ($this->headers as $headers) {
413
            $all_headers = array_merge($all_headers, $headers);
0 ignored issues
show
$headers of type Kodus\Mail\Header is incompatible with the type array expected by parameter $arrays of array_merge(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

413
            $all_headers = array_merge($all_headers, /** @scrutinizer ignore-type */ $headers);
Loading history...
414
        }
415
416 1
        return $all_headers;
417
    }
418 1
419 1
    /**
420
     * Set a custom MIME message header - for example, you may wish to set special headers
421
     * such as `Message-ID`, `X-Priority` or `X-Mailer` headers, but be aware that some
422
     * headers (such as `Message-ID`) have syntax that you need to comply with.
423
     *
424
     * @param string $name
425 3
     * @param string $value
426
     */
427 3
    public function setHeader(string $name, string $value): void
428 3
    {
429
        $this->headers[strtolower($name)] = [new Header($name, $value)];
430
    }
431
432
    /**
433
     * @param string $name
434
     * @param string $value
435
     */
436
    public function addHeader(string $name, string $value): void
437
    {
438
        $this->headers[strtolower($name)][] = new Header($name, $value);
439
    }
440
}
441