Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
44.07% covered (warning)
44.07%
52 / 118
16.67% covered (danger)
16.67%
1 / 6
CRAP
0.00% covered (danger)
0.00%
0 / 1
Google
44.07% covered (warning)
44.07%
52 / 118
16.67% covered (danger)
16.67%
1 / 6
451.15
0.00% covered (danger)
0.00%
0 / 1
 getMessages
34.85% covered (danger)
34.85%
23 / 66
0.00% covered (danger)
0.00%
0 / 1
296.76
 getMessage
85.71% covered (success)
85.71%
6 / 7
0.00% covered (danger)
0.00%
0 / 1
5.07
 getAttachments
23.08% covered (danger)
23.08%
6 / 26
0.00% covered (danger)
0.00%
0 / 1
22.39
 getAttachment
85.71% covered (success)
85.71%
6 / 7
0.00% covered (danger)
0.00%
0 / 1
2.01
 markAsRead
90.91% covered (success)
90.91%
10 / 11
0.00% covered (danger)
0.00%
0 / 1
3.01
 markAsUnread
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
1<?php
2/**
3 * Pop PHP Framework (http://www.popphp.org/)
4 *
5 * @link       https://github.com/popphp/popphp-framework
6 * @author     Nick Sagona, III <dev@nolainteractive.com>
7 * @copyright  Copyright (c) 2009-2024 NOLA Interactive, LLC. (http://www.nolainteractive.com)
8 * @license    http://www.popphp.org/license     New BSD License
9 */
10
11/**
12 * @namespace
13 */
14namespace Pop\Mail\Client;
15
16use GuzzleHttp\Psr7\Request;
17use Pop\Http;
18use Pop\Mail\Api\AbstractGoogle;
19use Google\Service\Gmail;
20/**
21 * Google mail client class
22 *
23 * @category   Pop
24 * @package    Pop\Mail
25 * @author     Nick Sagona, III <dev@nolainteractive.com>
26 * @copyright  Copyright (c) 2009-2024 NOLA Interactive, LLC. (http://www.nolainteractive.com)
27 * @license    http://www.popphp.org/license     New BSD License
28 * @version    4.0.0
29 */
30class Google extends AbstractGoogle implements HttpClientInterface
31{
32
33    /**
34     * Get messages
35     *
36     * @param  string $folder
37     * @param  array  $search
38     * @param  int    $limit
39     * @throws Exception|Http\Exception|Http\Client\Exception|Http\Client\Handler\Exception
40     * @return mixed
41     */
42    public function getMessages(string $folder = 'Inbox', array $search = [], int $limit = 10): mixed
43    {
44        if ($this->client === null) {
45            throw new Exception('Error: The client object has not been instantiated yet.');
46        }
47
48        $this->verifyToken();
49        $this->client->setAccessToken($this->token);
50
51        $messages      = [];
52        $options       = [];
53        $filterStrings = ['in:' . $folder];
54
55        if (!empty($limit)) {
56            $options['maxResults'] = $limit;
57        }
58
59        if (!empty($search)) {
60            foreach ($search as $key => $value) {
61                switch (strtolower($key)) {
62                    case 'unread':
63                        $filterStrings[] = "is:" . (($value) ? "unread" : "read");
64                        break;
65                    case 'sent after':
66                    case 'sent before':
67                    case 'sent older':
68                    case 'sent newer':
69                        $filterStrings[] = "in:" . $key . " " . date('m/d/Y', strtotime($value));
70                        break;
71                    default:
72                        $filterStrings[] = $key . ":" . $value;
73                }
74            }
75        }
76
77        $options['q'] = implode(' ', $filterStrings);
78
79        $gmail       = new Gmail($this->client);
80        $messageList = $gmail->users_messages->listUsersMessages($this->username, $options);
81        $batch       = $gmail->createBatch();
82
83        foreach ($messageList as $message) {
84            $batch->add(new Request('GET', 'https://gmail.googleapis.com/gmail/v1/users/' . $this->username . '/messages/' . $message->id));
85        }
86
87        $responses = $batch->execute();
88
89        foreach ($responses as $response) {
90            $responseBody = ($response->getStatusCode() == 200) ? json_decode((string)$response->getBody(), true) : [];
91            if (isset($responseBody['id'])) {
92                $hasAttachments = false;
93                if (isset($responseBody['payload'])) {
94                    if (isset($responseBody['payload']['headers'])) {
95                        foreach ($responseBody['payload']['headers'] as $header) {
96                            switch ($header['name']) {
97                                case 'Subject':
98                                    $responseBody['Subject'] = $header['value'];
99                                    break;
100                                case 'Date':
101                                    $responseBody['Date'] = $header['value'];
102                                    break;
103                                case 'To':
104                                    $responseBody['To'] = $header['value'];
105                                    break;
106                                case 'From':
107                                    $responseBody['From'] = $header['value'];
108                                    break;
109                                case 'Reply-To':
110                                    $responseBody['Reply-To'] = $header['value'];
111                                    break;
112                            }
113                        }
114                    }
115
116                    if (isset($responseBody['payload']['parts'])) {
117                        foreach ($responseBody['payload']['parts'] as $part) {
118                            if (!empty($part['filename'])) {
119                                $hasAttachments = true;
120                                break;
121                            } else if (isset($part['parts'])) {
122                                foreach ($part['parts'] as $p) {
123                                    if (!empty($p['filename'])) {
124                                        $hasAttachments = true;
125                                        break;
126                                    }
127                                }
128                            }
129                        }
130                    }
131                }
132
133                $responseBody['attachments'] = $hasAttachments;
134                $responseBody['unread']      = (isset($responseBody['labelIds']) && in_array('UNREAD', $responseBody['labelIds']));
135
136                $messages[$responseBody['id']] = $responseBody;
137            }
138
139        }
140
141        return $messages;
142    }
143
144    /**
145     * Get messages
146     *
147     * @param  string $messageId
148     * @param  bool   $raw
149     * @throws Exception|Http\Exception|Http\Client\Exception|Http\Client\Handler\Exception
150     * @return mixed
151     */
152    public function getMessage(string $messageId, bool $raw = false): mixed
153    {
154        if ($this->client === null) {
155            throw new Exception('Error: The client object has not been instantiated yet.');
156        }
157
158        $this->verifyToken();
159        $this->client->setAccessToken($this->token);
160
161        $gmail   = new Gmail($this->client);
162        $message = $gmail->users_messages->get($this->username, $messageId, ['format' => (($raw) ? 'raw' : 'full')]);
163
164        return (($raw) && isset($message['raw'])) ? base64_decode(strtr($message['raw'], '._-', '+/=')) : $message;
165    }
166
167    /**
168     * Get message attachments
169     *
170     * @param  string $messageId
171     * @param  string $folder
172     * @throws Exception|Http\Exception|Http\Client\Exception|Http\Client\Handler\Exception
173     * @return mixed
174     */
175    public function getAttachments(string $messageId, string $folder = 'Inbox'): mixed
176    {
177        if ($this->client === null) {
178            throw new Exception('Error: The client object has not been instantiated yet.');
179        }
180
181        $this->verifyToken();
182        $this->client->setAccessToken($this->token);
183
184        $gmail   = new Gmail($this->client);
185        $message = $gmail->users_messages->get($this->username, $messageId, ['format' => 'full']);
186
187        $attachments = [];
188        $payload     = $message->getPayload();
189        $parts       = $payload->getParts();
190
191        foreach ($parts as $part) {
192            if (!empty($part->getFilename())) {
193                $attachments[$part->getBody()->getAttachmentId()] = [
194                    'id'       => $part->getBody()->getAttachmentId(),
195                    'filename' => $part->getFilename(),
196                    'mimeType' => $part->getMimeType(),
197                    'size'     => $part->getBody()->getSize()
198                ];
199            } else {
200                foreach ($part->getParts() as $p) {
201                    if (!empty($p->getFilename())) {
202                        $attachments[$p->getBody()->getAttachmentId()] = [
203                            'id'       => $p->getBody()->getAttachmentId(),
204                            'filename' => $p->getFilename(),
205                            'mimeType' => $p->getMimeType(),
206                            'size'     => $p->getBody()->getSize()
207                        ];
208                    }
209                }
210            }
211        }
212
213        return $attachments;
214    }
215
216    /**
217     * Get message attachment
218     *
219     * @param  string $messageId
220     * @param  string $attachmentId
221     * @param  string $folder
222     * @throws Exception|Http\Exception|Http\Client\Exception|Http\Client\Handler\Exception
223     * @return mixed
224     */
225    public function getAttachment(string $messageId, string $attachmentId, string $folder = 'Inbox'): mixed
226    {
227        if ($this->client === null) {
228            throw new Exception('Error: The client object has not been instantiated yet.');
229        }
230
231        $this->verifyToken();
232        $this->client->setAccessToken($this->token);
233
234        $gmail      = new Gmail($this->client);
235        $attachment =  $gmail->users_messages_attachments->get($this->username, $messageId, $attachmentId);
236
237        return base64_decode(strtr($attachment->getData(), '-_', '+/'));
238    }
239
240    /**
241     * Mark message as read
242     *
243     * @param  string $messageId
244     * @param  bool   $isRead
245     * @throws Exception|Http\Exception|Http\Client\Exception|Http\Client\Handler\Exception
246     * @return Google
247     */
248    public function markAsRead(string $messageId, bool $isRead = true): Google
249    {
250        if ($this->client === null) {
251            throw new Exception('Error: The client object has not been instantiated yet.');
252        }
253
254        $this->verifyToken();
255        $this->client->setAccessToken($this->token);
256
257        $messageRequest = new Gmail\ModifyMessageRequest();
258
259        if ($isRead) {
260            $messageRequest->setRemoveLabelIds('UNREAD');
261        } else {
262            $messageRequest->setAddLabelIds('UNREAD');
263        }
264
265        $gmail      = new Gmail($this->client);
266        $gmail->users_messages->modify($this->username, $messageId, $messageRequest);
267
268        return $this;
269    }
270
271    /**
272     * Mark message as unread
273     *
274     * @param  string $messageId
275     * @throws Exception|Http\Exception|Http\Client\Exception|Http\Client\Handler\Exception
276     * @return Google
277     */
278    public function markAsUnread(string $messageId): Google
279    {
280        return $this->markAsRead($messageId, false);
281    }
282    
283}