Completed
Push — master ( 9eba1a...d953ee )
by Patrick
05:35 queued 02:02
created

Email::getReplyTo()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 4
nc 2
nop 0
dl 0
loc 8
rs 9.4285
c 0
b 0
f 0
1
<?php
2
/**
3
 * Email class
4
 *
5
 * This file describes the Email class
6
 *
7
 * PHP version 5 and 7
8
 *
9
 * @author Patrick Boyd / [email protected]
10
 * @copyright Copyright (c) 2015, Austin Artistic Reconstruction
11
 * @license http://www.apache.org/licenses/ Apache 2.0 License
12
 */
13
14
namespace Email;
15
16
/**
17
 * An class to represent an email
18
 */
19
class Email extends \SerializableObject
20
{
21
    /** The email's sender */
22
    protected $sender;
23
    /** An array of receipients */
24
    protected $to;
25
    /** An array of CC receipients */
26
    protected $cc;
27
    /** An array of BCC receipients */
28
    protected $bcc;
29
    /** The email's reply to address */
30
    protected $replyTo;
31
    /** The subject of the email */
32
    protected $subject;
33
    /** The email's HTML body */
34
    protected $htmlBody;
35
    /** The email's plain text body */
36
    protected $textBody;
37
    /** An array of attachements for the email */
38
    protected $attachments;
39
40
    /**
41
     * Initialize a new email
42
     */
43
    public function __construct()
44
    {
45
        $this->sender = false;
46
        $this->to = array();
47
        $this->cc = array();
48
        $this->bcc = array();
49
        $this->replyTo = false;
50
        $this->subject = false;
51
        $this->htmlBody = '';
52
        $this->textBody = '';
53
        $this->attachments = array();
54
    }
55
56
    /**
57
     * Who is this email going to be sent from
58
     *
59
     * This will return a string either in the format of 'email@address' or 'name <email@address>'
60
     *
61
     * @return string The sender of the email
62
     */
63
    public function getFromAddress()
64
    {
65
        if($this->sender === false)
66
        {
67
            return 'Burning Flipside <[email protected]>';
68
        }
69
        return $this->sender;
70
    }
71
72
    /**
73
     * Who is this email going to
74
     *
75
     * @return array The recipients of the email
76
     */
77
    public function getToAddresses()
78
    {
79
        return $this->to;
80
    }
81
82
    /**
83
     * Who is this email going to (CC)
84
     *
85
     * @return array The recipients of the email
86
     */
87
    public function getCCAddresses()
88
    {
89
        return $this->cc;
90
    }
91
92
    /**
93
     * Who is this email going to (BCC)
94
     *
95
     * @return array The recipients of the email
96
     */
97
    public function getBCCAddresses()
98
    {
99
        return $this->bcc;
100
    }
101
102
    /**
103
     * Who should a recipient reply to?
104
     *
105
     * @return string The reply to address of the email
106
     */
107
    public function getReplyTo()
108
    {
109
        if($this->replyTo === false)
110
        {
111
            return $this->getFromAddress();
112
        }
113
        return $this->replyTo;
114
    }
115
116
    /**
117
     * What is the email's subject?
118
     *
119
     * @return string The email's subject
120
     */
121
    public function getSubject()
122
    {
123
        return $this->subject;
124
    }
125
126
    /**
127
     * What should a user with an HTML capable email client see?
128
     *
129
     * @return string The email in HTML form
130
     */
131
    public function getHTMLBody()
132
    {
133
        return $this->htmlBody;
134
    }
135
136
    /**
137
     * What should a user with a plain text only email client see?
138
     *
139
     * @return string The email in ASCII form
140
     */
141
    public function getTextBody()
142
    {
143
        return $this->textBody;
144
    }
145
146
    /**
147
     * Create the address string given an email address and if specified a name
148
     *
149
     * @param string $email The email address
150
     * @param string $name  The name to associate with the address
151
     *
152
     * @return string The email address and name format
153
     */
154
    protected function constructEmailAddressString($email, $name = false)
155
    {
156
        if($name === false)
157
        {
158
            return $email;
159
        }
160
        return $name.' <'.$email.'>';
161
    }
162
163
    /**
164
     * Set the address the email should be sent from
165
     *
166
     * @param string $email The email address to send from
167
     * @param string $name  The name to associate with the from address
168
     */
169
    public function setFromAddress($email, $name = false)
170
    {
171
        $this->sender = $this->constructEmailAddressString($email, $name);
172
    }
173
174
    /**
175
     * Add a new address to the To: line
176
     *
177
     * @param string $email The email address to send to
178
     * @param string $name  The name to associate with the address
179
     */
180
    public function addToAddress($email, $name = false)
181
    {
182
        $this->addAddress($this->to, $email, $name);
183
    }
184
185
    /**
186
     * Add a new address to the CC: line
187
     *
188
     * @param string $email The email address to send to
189
     * @param string $name  The name to associate with the address
190
     */
191
    public function addCCAddress($email, $name = false)
192
    {
193
        $this->addAddress($this->cc, $email, $name);
194
    }
195
196
    /**
197
     * Add a new address to the BCC: line
198
     *
199
     * @param string $email The email address to send to
200
     * @param string $name  The name to associate with the address
201
     */
202
    public function addBCCAddress($email, $name = false)
203
    {
204
        $this->addAddress($this->bcc, $email, $name);
205
    }
206
207
    /**
208
     * Add an address to the inidicated list
209
     *
210
     * @param array  $list  The list to add the address to
211
     * @param string $email The email address to send to
212
     * @param string $name  The name to associate with the address
213
     */
214
    protected function addAddress(&$list, $email, $name = false)
215
    {
216
        array_push($list, $this->constructEmailAddressString($email, $name));
217
    }
218
219
    /**
220
     * Set the address a recipient should reply to
221
     *
222
     * @param string $email The email address to reply to
223
     * @param string $name  The name to associate with the from address
224
     */
225
    public function setReplyTo($email, $name = false)
226
    {
227
        $this->replyTo = $this->constructEmailAddressString($email, $name);
228
    }
229
230
    /**
231
     * Set the subject line for the email
232
     *
233
     * @param string $subject The email's new subject line
234
     */
235
    public function setSubject($subject)
236
    {
237
        $this->subject = $subject;
238
    }
239
240
    /**
241
     * Set the HTML body for the email
242
     *
243
     * @param string $body The email's new HTML body
244
     */
245
    public function setHTMLBody($body)
246
    {
247
        $this->htmlBody = $body;
248
    }
249
250
    /**
251
     * Set the plain text for the email
252
     *
253
     * @param string $body The email's new plain text body
254
     */
255
    public function setTextBody($body)
256
    {
257
        $this->textBody = $body;
258
    }
259
260
    /**
261
     * Append a string to the HTML Body
262
     *
263
     * @param string $body The string to append to the HTML body
264
     */
265
    public function appendToHTMLBody($body)
266
    {
267
        $this->htmlBody .= $body;
268
    }
269
270
    /**
271
     * Append a string to the Plain Text Body
272
     *
273
     * @param string $body The string to append to the plain text body
274
     */
275
    public function appendToTextBody($body)
276
    {
277
        $this->textBody .= $body;
278
    }
279
280
    /**
281
     * Add an attachment from a memory buffer
282
     *
283
     * @param string $name The file name for the attachment to be sent as
284
     * @param string $buffer The attachment as a binary string
285
     * @param string $mimeType The MIME type to send the attachment as
286
     */
287
    public function addAttachmentFromBuffer($name, $buffer, $mimeType = 'application/octet-stream')
288
    {
289
        array_push($this->attachments, array('name'=>$name, 'data'=>$buffer, 'mimeType'=>$mimeType));
290
    }
291
292
    /**
293
     * Add an attachment from a file on the local disk
294
     *
295
     * @param string $filename The file name and path on the local disk
296
     * @param string $name The file name for the attachment to be sent as
297
     */
298
    public function addAttachmentFromFile($filename, $name = false)
299
    {
300
        if($name === false)
301
        {
302
            $name = basename($filename);
303
        }
304
        $finfo = finfo_open(FILEINFO_MIME_TYPE);
305
        $mimeType = finfo_file($finfo, $filename);
306
        if($mimeType === false)
307
        {
308
            $mimeType = 'application/octet-stream';
309
        }
310
        if(file_exists($filename) && is_file($filename) && is_readable($filename))
311
        {
312
            $this->addAttachmentFromBuffer($name, file_get_contents($filename), $mimeType);
313
        }
314
    }
315
316
    /**
317
     * Does this email have an attachment?
318
     *
319
     * @return boolean True if the email has an attachment. False otherwise
320
     */
321
    public function hasAttachments()
322
    {
323
        return empty($this->attachments) !== true;
324
    }
325
326
    /**
327
     * Serialize the message to a raw MIME encoded format suitable for sending over SMTP
328
     *
329
     * @return string A text version of the message suitable for sending over SMTP
330
     */
331
    public function getRawMessage()
332
    {
333
        $boundary = uniqid(rand(), true);
334
        $rawMessage = 'To: '.$this->encodeRecipients($this->getToAddresses())."\n";
0 ignored issues
show
Documentation introduced by
$this->getToAddresses() is of type array, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
335
        $from = $this->getFromAddress();
336
        if($from === false)
337
        {
338
            throw new \Exception('Message must have a from address');
339
        }
340
        $rawMessage .= 'From: '.$this->encodeRecipients($from)."\n";
341
        if(!empty($this->cc))
342
        {
343
            $rawMessage .= 'CC: '.$this->encodeRecipients($this->getCCAddresses())."\n";
0 ignored issues
show
Documentation introduced by
$this->getCCAddresses() is of type array, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
344
        }
345
        if(!empty($this->bcc))
346
        {
347
            $rawMessage .= 'BCC: '.$this->encodeRecipients($this->getBCCAddresses())."\n";
0 ignored issues
show
Documentation introduced by
$this->getBCCAddresses() is of type array, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
348
        }
349
        $rawMessage .= 'Subject: '.$this->getSubject()."\n";
350
        $rawMessage .= 'MIME-Version: 1.0'."\n";
351
        $rawMessage .= 'Content-type: Multipart/Mixed; boundary="'.$boundary.'"'."\n";
352
        $rawMessage .= "\n--{$boundary}\n";
353
        $rawMessage .= 'Content-type: Multipart/Alternative; boundary="alt-'.$boundary.'"'."\n";
354
        $textBody    = $this->getTextBody();
355 View Code Duplication
        if($textBody !== false && strlen($textBody) > 0)
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
356
        {
357
            $rawMessage .= "\n--alt-{$boundary}\n";
358
            $rawMessage .= "Content-Type: text/plain\n\n";
359
            $rawMessage .= $textBody."\n";
360
        }
361
        $htmlBody = $this->getHTMLBody();
362 View Code Duplication
        if($htmlBody !== false && strlen($htmlBody) > 0)
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
363
        {
364
            $rawMessage .= "\n--alt-{$boundary}\n";
365
            $rawMessage .= 'Content-Type: text/html; charset="UTF-8"'."\n\n";
366
            $rawMessage .= $htmlBody."\n";
367
        }
368
        $rawMessage .= "\n--alt-{$boundary}--\n";
369
        foreach($this->attachments as $attachment)
370
        {
371
            $rawMessage .= "\n--{$boundary}\n";
372
            $rawMessage .= 'Content-Type: '.$attachment['mimeType'].'; name="'.$attachment['name']."\"\n";
373
            $rawMessage .= 'Content-Disposition: attachment'."\n";
374
            $rawMessage .= 'Content-Transfer-Encoding: base64'."\n\n";
375
            $rawMessage .= chunk_split(base64_encode($attachment['data']), 76, "\n")."\n";
376
        }
377
        $rawMessage .= "\n--{$boundary}--\n";
378
        return $rawMessage;
379
    }
380
381
    /**
382
     * Serialize a recipient so that it can be sent over SMTP
383
     *
384
     * @param string $recipient The recipient in the format 'name <email@address>'
385
     *
386
     * @return string A text version of the recipient name and address suitable for sending over SMTP
387
     */
388
    public function encodeRecipients($recipient)
389
    {
390
        if(is_array($recipient))
391
        {
392
            return join(', ', array_map(array($this, 'encodeRecipients'), $recipient));
393
        }
394
        if(preg_match("/(.*)<(.*)>/", $recipient, $regs))
395
        {
396
            $recipient = '=?UTF-8?B?'.base64_encode($regs[1]).'?= <'.$regs[2].'>';
397
        }
398
        return $recipient;
399
    }
400
}
401
/* vim: set tabstop=4 shiftwidth=4 expandtab: */
402