1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace Ddomanskyi\LaravelGmail\Traits; |
4
|
|
|
|
5
|
|
|
use Ddomanskyi\LaravelGmail\Services\Message\Mail; |
6
|
|
|
use Google_Service_Gmail; |
7
|
|
|
use Google_Service_Gmail_Message; |
8
|
|
|
use Swift_Attachment; |
9
|
|
|
use Swift_Message; |
10
|
|
|
use Symfony\Component\HttpFoundation\File\Exception\FileNotFoundException; |
11
|
|
|
|
12
|
|
|
/** |
13
|
|
|
* @property Google_Service_Gmail $service |
14
|
|
|
*/ |
15
|
|
|
trait Replyable |
16
|
|
|
{ |
17
|
|
|
use HasHeaders; |
18
|
|
|
|
19
|
|
|
private $swiftMessage; |
20
|
|
|
|
21
|
|
|
/** |
22
|
|
|
* Gmail optional parameters |
23
|
|
|
* |
24
|
|
|
* @var array |
25
|
|
|
*/ |
26
|
|
|
private $parameters = []; |
27
|
|
|
|
28
|
|
|
/** |
29
|
|
|
* Text or html message to send |
30
|
|
|
* |
31
|
|
|
* @var string |
32
|
|
|
*/ |
33
|
|
|
private $message; |
34
|
|
|
|
35
|
|
|
/** |
36
|
|
|
* Subject of the email |
37
|
|
|
* |
38
|
|
|
* @var string |
39
|
|
|
*/ |
40
|
|
|
private $subject; |
41
|
|
|
|
42
|
|
|
/** |
43
|
|
|
* Sender's email |
44
|
|
|
* |
45
|
|
|
* @var string |
46
|
|
|
*/ |
47
|
|
|
private $from; |
48
|
|
|
|
49
|
|
|
/** |
50
|
|
|
* Sender's name |
51
|
|
|
* |
52
|
|
|
* @var string |
53
|
|
|
*/ |
54
|
|
|
private $nameFrom; |
55
|
|
|
|
56
|
|
|
/** |
57
|
|
|
* Email of the recipient |
58
|
|
|
* |
59
|
|
|
* @var string|array |
60
|
|
|
*/ |
61
|
|
|
private $to; |
62
|
|
|
|
63
|
|
|
/** |
64
|
|
|
* Name of the recipient |
65
|
|
|
* |
66
|
|
|
* @var string |
67
|
|
|
*/ |
68
|
|
|
private $nameTo; |
69
|
|
|
|
70
|
|
|
/** |
71
|
|
|
* Single email or array of email for a carbon copy |
72
|
|
|
* |
73
|
|
|
* @var array|string |
74
|
|
|
*/ |
75
|
|
|
private $cc; |
76
|
|
|
|
77
|
|
|
/** |
78
|
|
|
* Name of the recipient |
79
|
|
|
* |
80
|
|
|
* @var string |
81
|
|
|
*/ |
82
|
|
|
private $nameCc; |
83
|
|
|
|
84
|
|
|
/** |
85
|
|
|
* Single email or array of email for a blind carbon copy |
86
|
|
|
* |
87
|
|
|
* @var array|string |
88
|
|
|
*/ |
89
|
|
|
private $bcc; |
90
|
|
|
|
91
|
|
|
/** |
92
|
|
|
* Name of the recipient |
93
|
|
|
* |
94
|
|
|
* @var string |
95
|
|
|
*/ |
96
|
|
|
private $nameBcc; |
97
|
|
|
|
98
|
|
|
/** |
99
|
|
|
* List of attachments |
100
|
|
|
* |
101
|
|
|
* @var array |
102
|
|
|
*/ |
103
|
|
|
private $attachments = []; |
104
|
|
|
|
105
|
|
|
private $priority = 2; |
106
|
|
|
|
107
|
|
|
public function __construct() |
108
|
|
|
{ |
109
|
|
|
$this->swiftMessage = new Swift_Message(); |
110
|
|
|
} |
111
|
|
|
|
112
|
|
|
/** |
113
|
|
|
* Receives the recipient's |
114
|
|
|
* If multiple recipients will receive the message an array should be used. |
115
|
|
|
* Example: array('[email protected]', '[email protected]' => 'A name') |
116
|
|
|
* |
117
|
|
|
* If $name is passed and the first parameter is a string, this name will be |
118
|
|
|
* associated with the address. |
119
|
|
|
* |
120
|
|
|
* @param string|array $to |
121
|
|
|
* |
122
|
|
|
* @param string|null $name |
123
|
|
|
* |
124
|
|
|
* @return Replyable |
125
|
|
|
*/ |
126
|
|
|
public function to($to, $name = null) |
127
|
|
|
{ |
128
|
|
|
$this->to = $to; |
129
|
|
|
$this->nameTo = $name; |
130
|
|
|
|
131
|
|
|
return $this; |
132
|
|
|
} |
133
|
|
|
|
134
|
|
|
public function from($from, $name = null) |
135
|
|
|
{ |
136
|
|
|
$this->from = $from; |
137
|
|
|
$this->nameFrom = $name; |
138
|
|
|
|
139
|
|
|
return $this; |
140
|
|
|
} |
141
|
|
|
|
142
|
|
|
/** |
143
|
|
|
* @param array|string $cc |
144
|
|
|
* |
145
|
|
|
* @param string|null $name |
146
|
|
|
* |
147
|
|
|
* @return Replyable |
148
|
|
|
*/ |
149
|
|
|
public function cc($cc, $name = null) |
150
|
|
|
{ |
151
|
|
|
$this->cc = $this->emailList($cc, $name); |
152
|
|
|
$this->nameCc = $name; |
153
|
|
|
|
154
|
|
|
return $this; |
155
|
|
|
} |
156
|
|
|
|
157
|
|
|
private function emailList($list, $name = null) |
158
|
|
|
{ |
159
|
|
|
if (is_array($list)) { |
160
|
|
|
return $this->convertEmailList($list, $name); |
161
|
|
|
} else { |
162
|
|
|
return $list; |
163
|
|
|
} |
164
|
|
|
} |
165
|
|
|
|
166
|
|
|
private function convertEmailList($emails, $name = null) |
167
|
|
|
{ |
168
|
|
|
$newList = []; |
169
|
|
|
$count = 0; |
170
|
|
|
foreach ($emails as $key => $email) { |
171
|
|
|
$emailName = isset($name[$count]) ? $name[$count] : explode('@', $email)[0]; |
172
|
|
|
$newList[$email] = $emailName; |
173
|
|
|
$count = $count + 1; |
174
|
|
|
} |
175
|
|
|
|
176
|
|
|
return $newList; |
177
|
|
|
} |
178
|
|
|
|
179
|
|
|
/** |
180
|
|
|
* @param array|string $bcc |
181
|
|
|
* |
182
|
|
|
* @param string|null $name |
183
|
|
|
* |
184
|
|
|
* @return Replyable |
185
|
|
|
*/ |
186
|
|
|
public function bcc($bcc, $name = null) |
187
|
|
|
{ |
188
|
|
|
$this->bcc = $this->emailList($bcc, $name); |
189
|
|
|
$this->nameBcc = $name; |
190
|
|
|
|
191
|
|
|
return $this; |
192
|
|
|
} |
193
|
|
|
|
194
|
|
|
/** |
195
|
|
|
* @param string $subject |
196
|
|
|
* |
197
|
|
|
* @return Replyable |
198
|
|
|
*/ |
199
|
|
|
public function subject($subject) |
200
|
|
|
{ |
201
|
|
|
$this->subject = $subject; |
202
|
|
|
|
203
|
|
|
return $this; |
204
|
|
|
} |
205
|
|
|
|
206
|
|
|
/** |
207
|
|
|
* @param string $view |
208
|
|
|
* @param array $data |
209
|
|
|
* @param array $mergeData |
210
|
|
|
* |
211
|
|
|
* @return Replyable |
212
|
|
|
* @throws \Throwable |
213
|
|
|
*/ |
214
|
|
|
public function view($view, $data = [], $mergeData = []) |
215
|
|
|
{ |
216
|
|
|
$this->message = view($view, $data, $mergeData)->render(); |
|
|
|
|
217
|
|
|
|
218
|
|
|
return $this; |
219
|
|
|
} |
220
|
|
|
|
221
|
|
|
/** |
222
|
|
|
* @param string $message |
223
|
|
|
* |
224
|
|
|
* @return Replyable |
225
|
|
|
*/ |
226
|
|
|
public function message($message) |
227
|
|
|
{ |
228
|
|
|
$this->message = $message; |
229
|
|
|
|
230
|
|
|
return $this; |
231
|
|
|
} |
232
|
|
|
|
233
|
|
|
/** |
234
|
|
|
* Attaches new file to the email from the Storage folder |
235
|
|
|
* |
236
|
|
|
* @param array $files comma separated of files |
237
|
|
|
* |
238
|
|
|
* @return Replyable |
239
|
|
|
* @throws \Exception |
240
|
|
|
*/ |
241
|
|
|
public function attach(...$files) |
242
|
|
|
{ |
243
|
|
|
|
244
|
|
|
foreach ($files as $file) { |
245
|
|
|
|
246
|
|
|
if (!file_exists($file)) { |
247
|
|
|
throw new FileNotFoundException($file); |
248
|
|
|
} |
249
|
|
|
|
250
|
|
|
array_push($this->attachments, $file); |
251
|
|
|
} |
252
|
|
|
|
253
|
|
|
return $this; |
254
|
|
|
} |
255
|
|
|
|
256
|
|
|
/** |
257
|
|
|
* The value is an integer where 1 is the highest priority and 5 is the lowest. |
258
|
|
|
* |
259
|
|
|
* @param int $priority |
260
|
|
|
* |
261
|
|
|
* @return Replyable |
262
|
|
|
*/ |
263
|
|
|
public function priority($priority) |
264
|
|
|
{ |
265
|
|
|
$this->priority = $priority; |
266
|
|
|
|
267
|
|
|
return $this; |
268
|
|
|
} |
269
|
|
|
|
270
|
|
|
/** |
271
|
|
|
* @param array $parameters |
272
|
|
|
* |
273
|
|
|
* @return Replyable |
274
|
|
|
*/ |
275
|
|
|
public function optionalParameters(array $parameters) |
276
|
|
|
{ |
277
|
|
|
$this->parameters = $parameters; |
278
|
|
|
|
279
|
|
|
return $this; |
280
|
|
|
} |
281
|
|
|
|
282
|
|
|
/** |
283
|
|
|
* Reply to a specific email |
284
|
|
|
* |
285
|
|
|
* @return Mail |
286
|
|
|
* @throws \Exception |
287
|
|
|
*/ |
288
|
|
|
public function reply() |
289
|
|
|
{ |
290
|
|
|
if (!$this->getId()) { |
291
|
|
|
throw new \Exception('This is a new email. Use send().'); |
292
|
|
|
} |
293
|
|
|
|
294
|
|
|
$this->setReplyThread(); |
295
|
|
|
$this->setReplySubject(); |
296
|
|
|
$this->setReplyTo(); |
297
|
|
|
$this->setReplyFrom(); |
298
|
|
|
$body = $this->getMessageBody(); |
299
|
|
|
$body->setThreadId($this->getThreadId()); |
300
|
|
|
|
301
|
|
|
return new Mail($this->service->users_messages->send('me', $body, $this->parameters)); |
302
|
|
|
} |
303
|
|
|
|
304
|
|
|
public abstract function getId(); |
305
|
|
|
|
306
|
|
|
private function setReplyThread() |
307
|
|
|
{ |
308
|
|
|
$threadId = $this->getThreadId(); |
309
|
|
|
if ($threadId) { |
310
|
|
|
$this->setHeader('In-Reply-To', $this->getHeader('In-Reply-To')); |
311
|
|
|
$this->setHeader('References', $this->getHeader('References')); |
312
|
|
|
$this->setHeader('Message-ID', $this->getHeader('Message-ID')); |
313
|
|
|
} |
314
|
|
|
} |
315
|
|
|
|
316
|
|
|
public abstract function getThreadId(); |
317
|
|
|
|
318
|
|
|
/** |
319
|
|
|
* Add a header to the email |
320
|
|
|
* |
321
|
|
|
* @param string $header |
322
|
|
|
* @param string $value |
323
|
|
|
*/ |
324
|
|
|
public function setHeader($header, $value) |
325
|
|
|
{ |
326
|
|
|
$headers = $this->swiftMessage->getHeaders(); |
327
|
|
|
|
328
|
|
|
$headers->addTextHeader($header, $value); |
329
|
|
|
|
330
|
|
|
} |
331
|
|
|
|
332
|
|
|
private function setReplySubject() |
333
|
|
|
{ |
334
|
|
|
if (!$this->subject) { |
335
|
|
|
$this->subject = $this->getSubject(); |
336
|
|
|
} |
337
|
|
|
} |
338
|
|
|
|
339
|
|
|
private function setReplyTo() |
340
|
|
|
{ |
341
|
|
|
if (!$this->to) { |
342
|
|
|
$replyTo = $this->getReplyTo(); |
343
|
|
|
|
344
|
|
|
$this->to = $replyTo['email']; |
345
|
|
|
$this->nameTo = $replyTo['name']; |
346
|
|
|
} |
347
|
|
|
} |
348
|
|
|
|
349
|
|
|
private function setReplyFrom() |
350
|
|
|
{ |
351
|
|
|
if (!$this->from) { |
352
|
|
|
$this->from = $this->getUser(); |
353
|
|
|
if(!$this->from) { |
354
|
|
|
throw new \Exception('Reply from is not defined'); |
355
|
|
|
} |
356
|
|
|
} |
357
|
|
|
} |
358
|
|
|
|
359
|
|
|
public abstract function getSubject(); |
360
|
|
|
|
361
|
|
|
public abstract function getReplyTo(); |
362
|
|
|
|
363
|
|
|
public abstract function getUser(); |
364
|
|
|
|
365
|
|
|
/** |
366
|
|
|
* @return Google_Service_Gmail_Message |
367
|
|
|
*/ |
368
|
|
|
private function getMessageBody() |
369
|
|
|
{ |
370
|
|
|
$body = new Google_Service_Gmail_Message(); |
371
|
|
|
|
372
|
|
|
$this->swiftMessage |
373
|
|
|
->setSubject($this->subject) |
374
|
|
|
->setFrom($this->from, $this->nameFrom) |
375
|
|
|
->setTo($this->to, $this->nameTo) |
376
|
|
|
->setCc($this->cc, $this->nameCc) |
377
|
|
|
->setBcc($this->bcc, $this->nameBcc) |
378
|
|
|
->setBody($this->message, 'text/html') |
379
|
|
|
->setPriority($this->priority); |
380
|
|
|
|
381
|
|
|
foreach ($this->attachments as $file) { |
382
|
|
|
$this->swiftMessage |
383
|
|
|
->attach(Swift_Attachment::fromPath($file)); |
384
|
|
|
} |
385
|
|
|
|
386
|
|
|
$body->setRaw($this->base64_encode($this->swiftMessage->toString())); |
387
|
|
|
|
388
|
|
|
return $body; |
389
|
|
|
} |
390
|
|
|
|
391
|
|
|
private function base64_encode($data) |
392
|
|
|
{ |
393
|
|
|
return rtrim(strtr(base64_encode($data), ['+' => '-', '/' => '_']), '='); |
394
|
|
|
} |
395
|
|
|
|
396
|
|
|
/** |
397
|
|
|
* Sends a new email |
398
|
|
|
* |
399
|
|
|
* @return self|Mail |
400
|
|
|
*/ |
401
|
|
|
public function send() |
402
|
|
|
{ |
403
|
|
|
$body = $this->getMessageBody(); |
404
|
|
|
|
405
|
|
|
$this->setMessage($this->service->users_messages->send('me', $body, $this->parameters)); |
406
|
|
|
|
407
|
|
|
return $this; |
408
|
|
|
} |
409
|
|
|
|
410
|
|
|
protected abstract function setMessage($message); |
411
|
|
|
} |
412
|
|
|
|
Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.
For example, imagine you have a variable
$accountId
that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to theid
property of an instance of theAccount
class. This class holds a proper account, so the id value must no longer be false.Either this assignment is in error or a type check should be added for that assignment.