PluginProbe
ERP: Complete HR, Accounting & CRM Suite Built for WooCommerce / 1.3.13
ERP: Complete HR, Accounting & CRM Suite Built for WooCommerce v1.3.13
1.17.9 1.17.8 1.17.7 1.17.6 1.17.5 1.17.4 1.2.2 1.2.3 1.2.4 1.2.5 1.2.6 1.2.7 1.2.8 1.3.0 1.3.1 1.3.11 1.3.12 1.3.13 1.3.14 1.3.2 1.3.3 1.3.4 1.3.5 1.3.6 1.3.7 All 143 releases
erp / includes / class-imap.php

class-imap.php in ERP: Complete HR, Accounting & CRM Suite Built for WooCommerce 1.3.13, at includes/class-imap.php

413 lines 11.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 namespace WeDevs\ERP;
3
4 /**
5 * Incoming email reader class
6 *
7 * Instructions
8 * =========================================================
9 * sudo apt-get install php5-imap
10 * sudo php5enmod imap
11 * sudo service apache2 restart
12 *
13 * Host: {imap.gmail.com:993/imap/ssl}INBOX
14 * Host: {imap.gmail.com:993/imap/ssl/novalidate-cert}INBOX
15 * Host: {imap.mail.yahoo.com:993/imap/ssl}INBOX
16 * Host: {imap-mail.outlook.com:993/imap/ssl}INBOX
17 * https://www.google.com/settings/security/lesssecureapps
18 * =========================================================
19 */
20 class Imap {
21 /**
22 * Mailbox
23 */
24 protected $mailbox;
25
26 /**
27 * Imap connection
28 */
29 protected $connection;
30
31 /**
32 * Class contsructor
33 *
34 * @param string $host
35 * @param string $port (993|995)
36 * @param string $protocol
37 * @param string $username
38 * @param string $password
39 * @param string $authentication (ssl|tls|notls)
40 * @param boolean $cert
41 *
42 * @return void
43 */
44 public function __construct( $host, $port, $protocol, $username, $password, $authentication = 'ssl', $cert = false ) {
45 set_time_limit( 3000 );
46
47 $this->host = $host;
48
49 $option = '';
50
51 if ( $protocol ) {
52 $option .= '/' . $protocol;
53 }
54
55 $option .= '/' . $authentication;
56
57 if ( $cert ) {
58 $option .= '/validate-cert';
59 } else {
60 $option .= '/novalidate-cert';
61 }
62
63 if ( preg_match( "/google|gmail/i", $host ) ) {
64 $this->mailbox = "{" . $host . ":" . $port . $option . "}INBOX";
65 } else {
66 $this->mailbox = "{" . $host . ":" . $port . $option . "}";
67 }
68
69 if ( ! $this->is_extension_loaded() ) {
70 throw new \Exception( 'Your server isn\'t connected with imap.' );
71 }
72
73 $this->connection = imap_open( $this->mailbox, $username, $password );
74
75 if ( ! $this->connection ) {
76 throw new \Exception( 'Cannot connect to Email: ' . imap_last_error() );
77 }
78 }
79
80 /**
81 * Determine the imap entension is loaded or try to load it dynamically
82 *
83 * @return boolean
84 */
85 public function is_extension_loaded() {
86 if ( ! extension_loaded( 'imap' ) || ! function_exists( 'imap_open' ) ) {
87 // $prefix = ( PHP_SHLIB_SUFFIX == 'dll' ) ? 'php_' : '';
88 // $extension = $prefix . 'imap.' . PHP_SHLIB_SUFFIX;
89
90 // if ( function_exists( 'dl' ) ) {
91 // return dl( $extension );
92 // }
93
94 return false;
95 }
96
97 return true;
98 }
99
100 /**
101 * Determine if the imap stream is connected
102 *
103 * @return boolean
104 */
105 public function is_connected() {
106 if ( imap_ping( $this->connection ) ) {
107 return true;
108 }
109
110 return false;
111 }
112
113 /**
114 * Open the inbox
115 *
116 * @param string $mailbox (optional)
117 * @param string $query (optional)
118 *
119 * @return array
120 */
121 public function open( $mailbox = 'inbox', $query = 'UNSEEN' ) {
122 if ( strtolower( $mailbox ) != 'inbox' ) {
123 $mailboxes = imap_list( $this->connection, $this->mailbox, $mailbox );
124
125 imap_reopen( $this->connection , $mailboxes[0] );
126 }
127
128 $emails = imap_search( $this->connection, $query );
129
130 if ( $emails ) {
131 rsort( $emails );
132
133 return $emails;
134 }
135
136 return [];
137 }
138
139 /**
140 * Get all emails with body & attachments
141 *
142 * @param string $mailbox (optional)
143 * @param string $query (optional)
144 *
145 * @return array
146 */
147 public function get_emails( $mailbox = 'inbox', $query = 'UNSEEN' ) {
148 $email_ids = $this->open( $mailbox, $query );
149
150 $emails = [];
151
152 foreach ( $email_ids as $email_id ) {
153 $emails[] = [
154 'id' => $email_id,
155 'subject' => $this->get_subject( $email_id ),
156 'body' => $this->get_body( $email_id ),
157 'attachments' => $this->get_attachments( $email_id ),
158 'headers' => $this->get_headers( $email_id ),
159 ];
160 }
161
162 return $emails;
163 }
164
165 /**
166 * Get email overview
167 *
168 * @param int $email_id
169 *
170 * @return array
171 */
172 public function get_overview( $email_id ) {
173 $overview = imap_fetch_overview( $this->connection, $email_id, 0 );
174
175 return $overview;
176 }
177
178 /**
179 * Get email headers
180 *
181 * @param int $email_id
182 *
183 * @return array
184 */
185 public function get_headers( $email_id ) {
186 $header_string = imap_fetchheader( $this->connection, $email_id );
187
188 preg_match_all( '/([^: ]+): (.+?(?:\r\n\s(?:.+?))*)\r\n/m', $header_string, $matches );
189 $headers = array_combine( $matches[1], $matches[2] );
190
191 return $headers;
192 }
193
194 /**
195 * Get email subject
196 *
197 * @param int $email_id
198 *
199 * @return string
200 */
201 public function get_subject( $email_id ) {
202 $headers = $this->get_headers( $email_id );
203
204 return $headers['Subject'];
205 }
206
207 /**
208 * Get email body
209 *
210 * @param int $email_id
211 *
212 * @return text
213 */
214 public function get_body( $email_id ) {
215 $body = $this->get_part( $email_id, "TEXT/HTML" );
216
217 // if HTML body is empty, try getting text body
218 if ( $body == "" ) {
219 $body = $this->get_part( $email_id, "TEXT/PLAIN" );
220 }
221
222 return $body;
223 }
224
225 /**
226 * Get email part for decoding email body
227 *
228 * @param int $email_id
229 * @param int $mimetype
230 * @param int $structure
231 * @param int $part_number
232 *
233 * @return string
234 */
235 protected function get_part( $email_id, $mimetype, $structure = false, $part_number = false ) {
236 if ( ! $structure ) {
237 $structure = imap_fetchstructure( $this->connection, $email_id );
238 }
239
240 if ( $structure ) {
241 if ( $mimetype == $this->get_mime_type( $structure ) ) {
242 if ( ! $part_number ) {
243 $part_number = 1;
244 }
245
246 $text = imap_fetchbody( $this->connection, $email_id, $part_number, FT_PEEK );
247
248 switch ( $structure->encoding ) {
249 case 3: return imap_base64( $text );
250 case 4: return imap_qprint( $text );
251
252 default: return $text;
253 }
254 }
255
256 // multipart
257 if ( $structure->type == 1 ) {
258 foreach ( $structure->parts as $index => $sub_struct ) {
259 $prefix = "";
260 if ( $part_number ) {
261 $prefix = $part_number . ".";
262 }
263
264 $data = $this->get_part( $email_id, $mimetype, $sub_struct, $prefix . ( $index + 1 ) );
265
266 if ( $data ) {
267 return $data;
268 }
269 }
270 }
271 }
272
273 return '';
274 }
275
276 /**
277 * Get mimetype by given email structure
278 *
279 * @param array $structure
280 *
281 * @return string
282 */
283 protected function get_mime_type( $structure ) {
284 $primary_mimetypes = [ "TEXT", "MULTIPART", "MESSAGE", "APPLICATION", "AUDIO", "IMAGE", "VIDEO", "OTHER" ];
285
286 if ( $structure->subtype ) {
287 return $primary_mimetypes[(int)$structure->type] . "/" . $structure->subtype;
288 }
289
290 return "TEXT/PLAIN";
291 }
292
293 /**
294 * Get email attachments
295 *
296 * @param int $email_id
297 *
298 * @return array
299 */
300 public function get_attachments( $email_id ) {
301 $structure = imap_fetchstructure( $this->connection, $email_id );
302
303 $attachments = [];
304
305 /* if any attachment found... */
306 if ( isset( $structure->parts ) && count( $structure->parts ) ) {
307 for ( $i = 0; $i < count( $structure->parts ); $i++ ) {
308 $attachments[$i] = array(
309 'is_attachment' => false,
310 'filename' => '',
311 'attachment' => '',
312 );
313
314 if ( $structure->parts[$i]->ifdparameters ) {
315 foreach ( $structure->parts[$i]->dparameters as $object ) {
316 if ( strtolower($object->attribute ) == 'filename' ) {
317 $attachments[$i]['is_attachment'] = true;
318 $attachments[$i]['filename'] = $object->value;
319 }
320 }
321 }
322
323 if ( $structure->parts[$i]->ifparameters ) {
324 foreach ( $structure->parts[$i]->parameters as $object ) {
325 if ( strtolower( $object->attribute ) == 'name' ) {
326 $attachments[$i]['is_attachment'] = true;
327 $attachments[$i]['filename'] = $object->value;
328 }
329 }
330 }
331
332 if ( $attachments[$i]['is_attachment'] ) {
333 $attachments[$i]['attachment'] = imap_fetchbody( $this->connection, $email_id, $i + 1 );
334
335 if ( $structure->parts[$i]->encoding == 3 ) {
336 $attachments[$i]['attachment'] = base64_decode( $attachments[$i]['attachment'] );
337 } else if ( $structure->parts[$i]->encoding == 4 ) {
338 $attachments[$i]['attachment'] = quoted_printable_decode( $attachments[$i]['attachment'] );
339 }
340 }
341 }
342 }
343
344 $filtered_attachments = [];
345 foreach ( $attachments as $attachment ) {
346 if ( $attachment['is_attachment'] ) {
347 $filtered_attachments[] = $attachment;
348 }
349 }
350
351 return $filtered_attachments;
352 }
353
354 /**
355 * Mark emails as seen
356 *
357 * @param array $email_ids
358 *
359 * @return boolean
360 */
361 public function mark_seen_emails( $email_ids ) {
362 $comma_separated_ids = implode( ',', $email_ids );
363
364 if ( empty( $comma_separated_ids ) ) {
365 return false;
366 }
367
368 $status = imap_setflag_full( $this->connection, $comma_separated_ids, "\\Seen" );
369
370 return $status;
371 }
372
373 /**
374 * Download email attachments as zip
375 *
376 * @param array $attachments
377 *
378 * @return void
379 */
380 public function download_attachments( $attachments ) {
381 $zip_file = 'email-attachment.zip';
382
383 $zip = new ZipArchive;
384 $zip->open( $zip_file, ZipArchive::CREATE | ZipArchive::OVERWRITE );
385
386 foreach ( $attachments as $file ) {
387 $zip->addFromString( $file['filename'], $file['attachment'] ) ;
388 }
389
390 $zip->close();
391
392 header( "Content-Description: File Transfer" );
393 header( "Content-Type: application/octet-stream" );
394 header( "Content-Disposition: attachment; filename=email-attachment.zip" );
395 header( "Content-Transfer-Encoding: binary" );
396 header( "Expires: 0" );
397 header( "Cache-Control: must-revalidate" );
398 header( "Pragma: public" );
399
400 readfile( $zip_file );
401 exit;
402 }
403
404 /**
405 * Close the connection
406 *
407 * @return void
408 */
409 public function close() {
410 imap_close( $this->connection );
411 }
412 }
413