dolibarr 24.0.0-beta
emailcollector_card.php
Go to the documentation of this file.
1<?php
2/* Copyright (C) 2018 Laurent Destailleur <eldy@users.sourceforge.net>
3 * Copyright (C) 2022 Charlene Benke <charlene@patas-monkey.com>
4 * Copyright (C) 2024 MDW <mdeweerd@users.noreply.github.com>
5 * Copyright (C) 2024-2026 Frédéric France <frederic.france@free.fr>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <https://www.gnu.org/licenses/>.
19 */
20
27// Load Dolibarr environment
28require '../main.inc.php';
38require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php';
39require_once DOL_DOCUMENT_ROOT.'/core/lib/agenda.lib.php';
40require_once DOL_DOCUMENT_ROOT.'/core/class/events.class.php';
41
42include_once DOL_DOCUMENT_ROOT.'/core/class/html.formcompany.class.php';
43include_once DOL_DOCUMENT_ROOT.'/core/class/html.formfile.class.php';
44include_once DOL_DOCUMENT_ROOT.'/emailcollector/class/emailcollector.class.php';
45include_once DOL_DOCUMENT_ROOT.'/emailcollector/class/emailcollectorfilter.class.php';
46include_once DOL_DOCUMENT_ROOT.'/emailcollector/class/emailcollectoraction.class.php';
47include_once DOL_DOCUMENT_ROOT.'/emailcollector/lib/emailcollector.lib.php';
48
49use Webklex\PHPIMAP\ClientManager;
50use Webklex\PHPIMAP\Exceptions\ConnectionFailedException;
51
52
53use OAuth\Common\Storage\DoliStorage;
54use OAuth\Common\Consumer\Credentials;
55
56if (!$user->admin) {
58}
59if (!isModEnabled('emailcollector')) {
61}
62
63// Load traductions files required by page
64$langs->loadLangs(array("admin", "mails", "other"));
65
66// Get parameters
67$id = GETPOSTINT('id');
68$ref = GETPOST('ref', 'alpha');
69$action = GETPOST('action', 'aZ09');
70$confirm = GETPOST('confirm', 'alpha');
71$cancel = GETPOST('cancel', 'alpha');
72$contextpage = GETPOST('contextpage', 'aZ') ? GETPOST('contextpage', 'aZ') : 'emailcollectorcard'; // To manage different context of search
73$backtopage = GETPOST('backtopage', 'alpha');
74
75$operationid = GETPOSTINT('operationid');
76
77// Initialize a technical objects
79
80$diroutputmassaction = $conf->emailcollector->dir_output.'/temp/massgeneration/'.$user->id;
81$hookmanager->initHooks(array('emailcollectorcard')); // Note that conf->hooks_modules contains array
82
83// Fetch optionals attributes and labels
84$extrafields->fetch_name_optionals_label($object->table_element);
85
86$search_array_options = $extrafields->getOptionalsFromPost($object->table_element, '', 'search_');
87
88// Initialize array of search criteria
89$search_all = GETPOST("search_all", 'alpha');
90$search = array();
91foreach ($object->fields as $key => $val) {
92 if (GETPOST('search_'.$key, 'alpha')) {
93 $search[$key] = GETPOST('search_'.$key, 'alpha');
94 }
95}
96
97if (GETPOST('saveoperation2')) {
98 $action = 'updateoperation';
99}
100if (empty($action) && empty($id) && empty($ref)) {
101 $action = 'view';
102}
103
104// Load object
105include DOL_DOCUMENT_ROOT.'/core/actions_fetchobject.inc.php'; // Must be 'include', not 'include_once'.
106
107// Security check - Protection if external user
108//if ($user->socid > 0) accessforbidden();
109//if ($user->socid > 0) $socid = $user->socid;
110//$isdraft = (($object->statut == MyObject::STATUS_DRAFT) ? 1 : 0);
111//restrictedArea($user, 'mymodule', $object->id, '', '', 'fk_soc', 'rowid', $isdraft);
112
113$permissionnote = $user->admin; // Used by the include of actions_setnotes.inc.php
114$permissiondellink = $user->admin; // Used by the include of actions_dellink.inc.php
115$permissiontoadd = $user->admin; // Used by the include of actions_addupdatedelete.inc.php and actions_lineupdown.inc.php
116
117$debuginfo = '';
118$error = 0;
119
120
121/*
122 * Actions
123 */
124
125$parameters = array();
126$reshook = $hookmanager->executeHooks('doActions', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
127
128if ($reshook < 0) {
129 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
130}
131
132if (empty($reshook)) {
133 $permissiontoadd = 1;
134 $permissiontodelete = 1;
135 if (empty($backtopage)) {
136 $backtopage = DOL_URL_ROOT.'/admin/emailcollector_card.php?id='.($id > 0 ? $id : '__ID__');
137 }
138 $backurlforlist = DOL_URL_ROOT.'/admin/emailcollector_list.php';
139
140 // Actions cancel, add, update, delete or clone
141 include DOL_DOCUMENT_ROOT.'/core/actions_addupdatedelete.inc.php';
142
143 // Actions when linking object each other
144 include DOL_DOCUMENT_ROOT.'/core/actions_dellink.inc.php';
145
146 // Actions when printing a doc from card
147 include DOL_DOCUMENT_ROOT.'/core/actions_printing.inc.php';
148}
149
150if (GETPOST('addfilter', 'alpha')) {
151 $emailcollectorfilter = new EmailCollectorFilter($db);
152 $emailcollectorfilter->type = GETPOST('filtertype', 'aZ09');
153 $emailcollectorfilter->rulevalue = GETPOST('rulevalue', 'alpha');
154 $emailcollectorfilter->fk_emailcollector = $object->id;
155 $emailcollectorfilter->status = 1;
156
157 $result = $emailcollectorfilter->create($user);
158
159 if ($result > 0) {
160 $object->fetchFilters();
161 } else {
162 setEventMessages($emailcollectorfilter->error, $emailcollectorfilter->errors, 'errors');
163 }
164}
165
166if ($action == 'deletefilter') {
167 $emailcollectorfilter = new EmailCollectorFilter($db);
168 $emailcollectorfilter->fetch(GETPOSTINT('filterid'));
169 if ($emailcollectorfilter->id > 0) {
170 $result = $emailcollectorfilter->delete($user);
171 if ($result > 0) {
172 $object->fetchFilters();
173 } else {
174 setEventMessages($emailcollectorfilter->error, $emailcollectorfilter->errors, 'errors');
175 }
176 }
177}
178
179if (GETPOST('addoperation', 'alpha')) {
180 $emailcollectoroperation = new EmailCollectorAction($db);
181 $emailcollectoroperation->type = GETPOST('operationtype', 'aZ09');
182 $emailcollectoroperation->actionparam = GETPOST('operationparam', 'alphawithlgt');
183 $emailcollectoroperation->fk_emailcollector = $object->id;
184 $emailcollectoroperation->status = 1;
185 $emailcollectoroperation->position = 50;
186
187 if ($emailcollectoroperation->type == '-1') {
188 $error++;
189 setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Operation")), null, 'errors');
190 }
191
192 if (in_array($emailcollectoroperation->type, array('loadthirdparty', 'loadandcreatethirdparty'))
193 && empty($emailcollectoroperation->actionparam)) {
194 $error++;
195 setEventMessages($langs->trans("ErrorAParameterIsRequiredForThisOperation"), null, 'errors');
196 }
197
198 if (!$error) {
199 $result = $emailcollectoroperation->create($user);
200
201 if ($result > 0) {
202 $object->fetchActions();
203 } else {
204 $error++;
205 setEventMessages($emailcollectoroperation->error, $emailcollectoroperation->errors, 'errors');
206 }
207 }
208}
209
210if ($action == 'updateoperation') {
211 $emailcollectoroperation = new EmailCollectorAction($db);
212 $emailcollectoroperation->fetch(GETPOSTINT('rowidoperation2'));
213
214 $emailcollectoroperation->actionparam = GETPOST('operationparam2', 'alphawithlgt');
215
216 if (in_array($emailcollectoroperation->type, array('loadthirdparty', 'loadandcreatethirdparty'))
217 && empty($emailcollectoroperation->actionparam)) {
218 $error++;
219 setEventMessages($langs->trans("ErrorAParameterIsRequiredForThisOperation"), null, 'errors');
220 }
221
222 if (!$error) {
223 $result = $emailcollectoroperation->update($user);
224
225 if ($result > 0) {
226 $object->fetchActions();
227 } else {
228 $error++;
229 setEventMessages($emailcollectoroperation->error, $emailcollectoroperation->errors, 'errors');
230 }
231 }
232}
233if ($action == 'deleteoperation') {
234 $emailcollectoroperation = new EmailCollectorAction($db);
235 $emailcollectoroperation->fetch(GETPOSTINT('operationid'));
236 if ($emailcollectoroperation->id > 0) {
237 $result = $emailcollectoroperation->delete($user);
238 if ($result > 0) {
239 $object->fetchActions();
240 } else {
241 setEventMessages($emailcollectoroperation->error, $emailcollectoroperation->errors, 'errors');
242 }
243 }
244}
245
246if ($action == 'collecttest') {
247 dol_include_once('/emailcollector/class/emailcollector.class.php');
248
249 $res = $object->doCollectOneCollector(1);
250 if ($res > 0) {
251 $debuginfo = $object->debuginfo;
252 setEventMessages($object->lastresult, null, 'mesgs');
253 } else {
254 $debuginfo = $object->debuginfo;
255 setEventMessages($object->error, $object->errors, 'errors');
256 }
257
258 $action = '';
259}
260
261if ($action == 'confirm_collect') {
262 dol_include_once('/emailcollector/class/emailcollector.class.php');
263
264 $res = $object->doCollectOneCollector(0);
265 if ($res > 0) {
266 $debuginfo = $object->debuginfo;
267 setEventMessages($object->lastresult, null, 'mesgs');
268 } else {
269 $debuginfo = $object->debuginfo;
270 setEventMessages($object->error, $object->errors, 'errors');
271 }
272
273 $action = '';
274}
275
276
277
278/*
279 * View
280 */
281
282$form = new Form($db);
283$formfile = new FormFile($db);
284
285$help_url = "EN:Module_EMail_Collector|FR:Module_Collecteur_de_courrier_électronique|ES:Module_EMail_Collector";
286
287llxHeader('', 'EmailCollector', $help_url, '', 0, 0, '', '', '', 'mod-admin page-emailcollector_card');
288
289// Part to create
290if ($action == 'create') {
291 print load_fiche_titre($langs->trans("NewEmailCollector", $langs->transnoentitiesnoconv("EmailCollector")));
292
293 print '<form method="POST" action="'.dolBuildUrl($_SERVER["PHP_SELF"]).'">';
294 print '<input type="hidden" name="token" value="'.newToken().'">';
295 print '<input type="hidden" name="action" value="add">';
296 print '<input type="hidden" name="backtopage" value="'.$backtopage.'">';
297
298 print dol_get_fiche_head(array(), '');
299
300 print '<table class="border centpercent tableforfield">'."\n";
301
302 //unset($fields[]);
303
304 // Common attributes
305 include DOL_DOCUMENT_ROOT.'/core/tpl/commonfields_add.tpl.php';
306
307 // Other attributes
308 include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_add.tpl.php';
309
310 print '</table>'."\n";
311
312 print dol_get_fiche_end();
313
314 print $form->buttonsSaveCancel("Create");
315
316 print '</form>';
317}
318
319// Part to edit record
320if (($id || $ref) && $action == 'edit') {
321 print load_fiche_titre($langs->trans("EmailCollector"));
322
323 print '<form method="POST" action="'.dolBuildUrl($_SERVER["PHP_SELF"]).'">';
324 print '<input type="hidden" name="token" value="'.newToken().'">';
325 print '<input type="hidden" name="action" value="update">';
326 print '<input type="hidden" name="backtopage" value="'.$backtopage.'">';
327 print '<input type="hidden" name="id" value="'.$object->id.'">';
328
329 print dol_get_fiche_head();
330
331 print '<table class="border centpercent tableforfield">'."\n";
332
333 // Common attributes
334 include DOL_DOCUMENT_ROOT.'/core/tpl/commonfields_edit.tpl.php';
335
336 // Other attributes
337 include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_edit.tpl.php';
338
339 print '</table>';
340
341 print dol_get_fiche_end();
342
343 print $form->buttonsSaveCancel();
344
345 print '</form>';
346}
347
348// Part to show record
349if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'create'))) {
350 $res = $object->fetch_optionals();
351
352 $object->fetchFilters();
353 $object->fetchActions();
354
355 $head = emailcollectorPrepareHead($object);
356 print dol_get_fiche_head($head, 'card', $langs->trans("EmailCollector"), -1, 'email');
357
358 $formconfirm = '';
359
360 // Confirmation to delete
361 if ($action == 'delete') {
362 $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id, $langs->trans('DeleteEmailCollector'), $langs->trans('ConfirmDeleteEmailCollector'), 'confirm_delete', '', 0, 1);
363 }
364
365 // Clone confirmation
366 if ($action == 'clone') {
367 // Create an array for form
368 $formquestion = array();
369 $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id, $langs->trans('ToClone'), $langs->trans('ConfirmCloneEmailCollector', $object->ref), 'confirm_clone', $formquestion, 'yes', 1);
370 }
371
372 // Confirmation of action process
373 if ($action == 'collect') {
374 $formquestion = array();
375 $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id, $langs->trans('EmailCollectorConfirmCollectTitle'), $langs->trans('EmailCollectorConfirmCollect'), 'confirm_collect', $formquestion, 0, 1, 220);
376 }
377
378 // Call Hook formConfirm
379 $parameters = array('formConfirm' => $formconfirm);
380 $reshook = $hookmanager->executeHooks('formConfirm', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
381 if (empty($reshook)) {
382 $formconfirm .= $hookmanager->resPrint;
383 } elseif ($reshook > 0) {
384 $formconfirm = $hookmanager->resPrint;
385 }
386
387 // Print form confirm
388 print $formconfirm;
389
390 // Object card
391 // ------------------------------------------------------------
392 $linkback = '<a href="'.DOL_URL_ROOT.'/admin/emailcollector_list.php?restore_lastsearch_values=1'.(!empty($socid) ? '&socid='.$socid : '').'">'.$langs->trans("BackToList").'</a>';
393
394 $morehtmlref = '<div class="refidno">';
395 $morehtmlref .= '</div>';
396
397 $morehtml = '';
398
399 $sourcedir = $object->source_directory;
400 $targetdir = ($object->target_directory ? $object->target_directory : ''); // Can be '[Gmail]/Trash' or 'mytag'
401
402 $connection = null;
403 $connectstringserver = $object->getConnectStringIMAP(); // Note: $object->host has been loaded by the fetch
404 $connectstringsource = '';
405 $connectstringtarget = '';
406
407
408 if ($action == 'scan') {
409 if (getDolGlobalString('MAIN_IMAP_USE_PHPIMAP')) {
410 require_once DOL_DOCUMENT_ROOT.'/includes/webklex/php-imap/vendor/autoload.php';
411
412 if ($object->acces_type == 1) {
413 dol_syslog("Scan IMAP with authentication mode = OAUTH2");
414
415 // Mode OAUth2 with PHP-IMAP
416 require_once DOL_DOCUMENT_ROOT.'/core/lib/oauth.lib.php';
417
418 $supportedoauth2array = getSupportedOauth2Array();
419
420 $keyforsupportedoauth2array = $object->oauth_service;
421 if (preg_match('/^.*-/', $keyforsupportedoauth2array)) {
422 $keyforprovider = preg_replace('/^.*-/', '', $keyforsupportedoauth2array);
423 } else {
424 $keyforprovider = '';
425 }
426 $keyforsupportedoauth2array = preg_replace('/-.*$/', '', strtoupper($keyforsupportedoauth2array));
427 $keyforsupportedoauth2array = 'OAUTH_'.$keyforsupportedoauth2array.'_NAME';
428
429 if (!empty($supportedoauth2array)) {
430 $nameofservice = ucfirst(strtolower(empty($supportedoauth2array[$keyforsupportedoauth2array]['callbackfile']) ? 'Unknown' : $supportedoauth2array[$keyforsupportedoauth2array]['callbackfile']));
431 $nameofservice .= ($keyforprovider ? '-'.$keyforprovider : '');
432 $OAUTH_SERVICENAME = $nameofservice;
433 } else {
434 $OAUTH_SERVICENAME = 'Unknown';
435 }
436
437 $keyforparamtenant = 'OAUTH_'.strtoupper(empty($supportedoauth2array[$keyforsupportedoauth2array]['callbackfile']) ? 'Unknown' : $supportedoauth2array[$keyforsupportedoauth2array]['callbackfile']).($keyforprovider ? '-'.$keyforprovider : '').'_TENANT';
438
439 require_once DOL_DOCUMENT_ROOT.'/includes/OAuth/bootstrap.php';
440 //$debugtext = "Host: ".$this->host."<br>Port: ".$this->port."<br>Login: ".$this->login."<br>Password: ".$this->password."<br>access type: ".$this->acces_type."<br>oauth service: ".$this->oauth_service."<br>Max email per collect: ".$this->maxemailpercollect;
441 //dol_syslog($debugtext);
442
443 $token = '';
444
445 $storage = new DoliStorage($db, $conf, $keyforprovider, getDolGlobalString($keyforparamtenant));
446
447 try {
448 $tokenobj = $storage->retrieveAccessToken($OAUTH_SERVICENAME);
449
450 $expire = true;
451 // Is token expired or will token expire in the next 30 seconds
452 // if (is_object($tokenobj)) {
453 // $expire = ($tokenobj->getEndOfLife() !== -9002 && $tokenobj->getEndOfLife() !== -9001 && time() > ($tokenobj->getEndOfLife() - 30));
454 // }
455 // Token expired so we refresh it
456 if (is_object($tokenobj) && $expire) {
457 $credentials = new Credentials(
458 getDolGlobalString('OAUTH_'.$object->oauth_service.'_ID'),
459 getDolGlobalString('OAUTH_'.$object->oauth_service.'_SECRET'),
460 getDolGlobalString('OAUTH_'.$object->oauth_service.'_URLCALLBACK')
461 );
462 $serviceFactory = new \OAuth\ServiceFactory();
463 $oauthname = explode('-', $OAUTH_SERVICENAME);
464
465 // ex service is Google-Emails we need only the first part Google
466 $apiService = $serviceFactory->createService($oauthname[0], $credentials, $storage, array());
467 '@phan-var-force OAuth\OAuth2\Service\AbstractService|OAuth\OAuth1\Service\AbstractService $apiService'; // createService is only ServiceInterface
468
469 // We need to save the token because Google provides it only once
470 $refreshtoken = $tokenobj->getRefreshToken();
471
472 //var_dump($tokenobj);
473 try {
474 $tokenobj = $apiService->refreshAccessToken($tokenobj);
475 } catch (Exception $e) {
476 throw new Exception("Failed to refresh access token: ".$e->getMessage());
477 }
478
479 // @phan-suppress-next-line PhanPluginUnknownObjectMethodCall
480 $tokenobj->setRefreshToken($refreshtoken);
481 $storage->storeAccessToken($OAUTH_SERVICENAME, $tokenobj);
482 }
483
484 $tokenobj = $storage->retrieveAccessToken($OAUTH_SERVICENAME);
485 if (is_object($tokenobj)) {
486 $token = $tokenobj->getAccessToken();
487 } else {
488 $error++;
489 $morehtml .= "Token not found";
490 }
491 } catch (Exception $e) {
492 $error++;
493 $morehtml .= $e->getMessage();
494 }
495
496 if (empty($object->login)) {
497 $error++;
498 $morehtml .= 'Error: Login is empty. Must be email owner when using MAIN_IMAP_USE_PHPIMAP and OAuth.';
499 }
500
501 $cm = new ClientManager();
502 $client = $cm->make([
503 'host' => $object->host,
504 'port' => $object->port,
505 'encryption' => 'ssl',
506 'validate_cert' => true,
507 'protocol' => 'imap',
508 'username' => $object->login,
509 'password' => $token,
510 'authentication' => "oauth",
511 ]);
512 } else {
513 dol_syslog("Scan IMAP with authentication mode = PASS");
514
515 // Mode login/pass with PHP-IMAP
516 $cm = new ClientManager();
517 $client = $cm->make([
518 'host' => $object->host,
519 'port' => $object->port,
520 'encryption' => 'ssl',
521 'validate_cert' => true,
522 'protocol' => 'imap',
523 'username' => $object->login,
524 'password' => $object->password,
525 'authentication' => "login",
526 ]);
527 }
528
529 if (!$error) {
530 try {
531 // To emulate the command connect, you can run
532 // openssl s_client -crlf -connect outlook.office365.com:993
533 // TAG1 AUTHENTICATE XOAUTH2 dXN...
534 // TO Get debug log, you can set protected $debug = true; in Protocol.php file
535 //
536 // A MS bug make this not working !
537 // See https://github.com/MicrosoftDocs/office-developer-exchange-docs/issues/100
538 // See github.com/MicrosoftDocs/office-developer-exchange-docs/issues/87
539 // See github.com/Webklex/php-imap/issues/81
540 $client->connect();
541
542 // Uncomment this to output debug info
543 //$client->getConnection()->enableDebug(); // Add debug
544
545 $f = $client->getFolders(false, $object->source_directory);
546 if ($f) { // $f is Webklex\PHPIMAP\Support\FolderCollection
547 $folder = $f[0];
548 if ($folder instanceof Webklex\PHPIMAP\Folder) {
549 $nbemail = $folder->examine()["exists"];
550 } else {
551 $nbemail = 0;
552 }
553 } else {
554 $nbemail = 0;
555 }
556 $morehtml .= $nbemail;
557 } catch (ConnectionFailedException $e) {
558 $morehtml .= 'ConnectionFailedException '.$e->getMessage();
559 }
560 }
561 } else {
562 if (function_exists('imap_open')) {
563 try {
564 if ($sourcedir) {
565 //$connectstringsource = $connectstringserver.imap_utf7_encode($sourcedir);
566 $connectstringsource = $connectstringserver.$object->getEncodedUtf7($sourcedir);
567 }
568 if ($targetdir) {
569 //$connectstringtarget = $connectstringserver.imap_utf7_encode($targetdir);
570 $connectstringtarget = $connectstringserver.$object->getEncodedUtf7($targetdir);
571 }
572
573 $timeoutconnect = getDolGlobalInt('MAIN_USE_CONNECT_TIMEOUT', 5);
574 $timeoutread = getDolGlobalInt('MAIN_USE_RESPONSE_TIMEOUT', 20);
575
576 dol_syslog("imap_open connectstring=".$connectstringsource." login=".$object->login." password=".$object->password." timeoutconnect=".$timeoutconnect." timeoutread=".$timeoutread);
577
578 $result1 = imap_timeout(IMAP_OPENTIMEOUT, $timeoutconnect); // timeout seems ignored with ssl connect
579 $result2 = imap_timeout(IMAP_READTIMEOUT, $timeoutread);
580 $result3 = imap_timeout(IMAP_WRITETIMEOUT, 5);
581 $result4 = imap_timeout(IMAP_CLOSETIMEOUT, 5);
582
583 dol_syslog("result1=".$result1." result2=".$result2." result3=".$result3." result4=".$result4);
584
585 $connection = imap_open($connectstringsource, $object->login, $object->password);
586
587 //dol_syslog("end imap_open connection=".var_export($connection, true));
588 } catch (Exception $e) {
589 $morehtml .= $e->getMessage();
590 }
591
592 if (!$connection) {
593 $morehtml .= 'Failed to open IMAP connection '.$connectstringsource;
594 if (function_exists('imap_last_error')) {
595 $morehtml .= '<br>'.imap_last_error();
596 }
597 dol_syslog("Error ".$morehtml, LOG_WARNING);
598 //var_dump(imap_errors())
599 } else {
600 dol_syslog("Imap connected. Now we call imap_num_msg()");
601 $morehtml .= imap_num_msg($connection);
602 }
603
604 if ($connection) {
605 dol_syslog("Imap close");
606 imap_close($connection);
607 }
608 } else {
609 $morehtml .= 'IMAP functions not available on your PHP. ';
610 }
611 }
612 }
613
614 $morehtml = $form->textwithpicto($langs->trans("NbOfEmailsInInbox"), 'Connect string = '.$connectstringserver.'<br>Option MAIN_IMAP_USE_PHPIMAP = '.getDolGlobalInt('MAIN_IMAP_USE_PHPIMAP')).': '.($morehtml !== '' ? $morehtml : '?');
615 $morehtml .= '<a class="flat paddingleft marginleftonly" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&action=scan&token='.newToken().'">'.img_picto('', 'refresh', 'class="paddingrightonly"').$langs->trans("Refresh").'</a>';
616
617 dol_banner_tab($object, 'ref', $linkback, 1, 'ref', 'ref', $morehtmlref.'<div class="refidno">'.$morehtml.'</div>', '', 0, '', '', 0, '');
618
619 print '<div class="fichecenter">';
620 print '<div class="fichehalfleft">';
621 print '<div class="underbanner clearboth"></div>';
622 print '<table class="border centpercent tableforfield">'."\n";
623
624 // Clean info (in view mode only)
625 if ($object->acces_type == 0) {
626 // If authent is using LOGIN and not OAUTHTOKEN, we don't need to show the OAUTH token
627 unset($object->fields['oauth_service']);
628 }
629 if ($object->acces_type == 1) {
630 // If authent is using OAUTHTOKEN, we don't need to show the password
631 unset($object->fields['password']);
632 }
633
634 // Common attributes
635 //$keyforbreak='fieldkeytoswithonsecondcolumn';
636 $nounderbanner = 1;
637 include DOL_DOCUMENT_ROOT.'/core/tpl/commonfields_view.tpl.php';
638
639 // Other attributes
640 include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_view.tpl.php';
641
642 print '</table>';
643
644
645 print '<form method="POST" action="'.dolBuildUrl($_SERVER["PHP_SELF"]).'">';
646 print '<input type="hidden" name="token" value="'.newToken().'">';
647 print '<input type="hidden" name="action" value="updatefiltersactions">';
648 print '<input type="hidden" name="backtopage" value="'.$backtopage.'">';
649 print '<input type="hidden" name="id" value="'.$object->id.'">';
650
651 // Filters
652 print '<div class="div-table-responsive-no-min">';
653 print '<table id="tablelineoffilters" class="noborder noshadow">';
654 print '<tr class="liste_titre nodrag nodrop">';
655 print '<td>'.img_picto('', 'filter', 'class="pictofixedwidth opacitymedium"').$form->textwithpicto($langs->trans("Filters"), $langs->trans("EmailCollectorFilterDesc")).'</td><td></td><td></td>';
656 print '</tr>';
657 // Add filter
658 print '<tr class="oddeven nodrag nodrop">';
659 print '<td>';
660 $arrayoftypes = array(
661 'from' => array('label' => 'MailFrom', 'data-placeholder' => $langs->trans('SearchString')),
662 'to' => array('label' => 'MailTo', 'data-placeholder' => $langs->trans('SearchString')),
663 'cc' => array('label' => 'Cc', 'data-placeholder' => $langs->trans('SearchString')),
664 'bcc' => array('label' => 'Bcc', 'data-placeholder' => $langs->trans('SearchString')),
665 'replyto' => array('label' => 'ReplyTo', 'data-placeholder' => $langs->trans('SearchString')),
666 'excludeemail' => array('label' => 'EmailCollectorExcludeEmails', 'data-placeholder' => $langs->trans('EmailCollectorExcludeEmailsPlaceholder')),
667 'excludedomain' => array('label' => 'EmailCollectorExcludeDomains', 'data-placeholder' => $langs->trans('EmailCollectorExcludeDomainsPlaceholder')),
668 'subject' => array('label' => 'Subject', 'data-placeholder' => $langs->trans('SearchString')),
669 'body' => array('label' => 'Body', 'data-placeholder' => $langs->trans('SearchString')),
670 // disabled because PHP imap_search is not compatible IMAPv4, only IMAPv2
671 //'header'=>array('label'=>'Header', 'data-placeholder'=>'HeaderKey SearchString'), // HEADER key value
672 //'X1'=>'---',
673 'X2' => '---',
674 'seen' => array('label' => 'AlreadyRead', 'data-noparam' => 1),
675 'unseen' => array('label' => 'NotRead', 'data-noparam' => 1),
676 'unanswered' => array('label' => 'Unanswered', 'data-noparam' => 1),
677 'answered' => array('label' => 'Answered', 'data-noparam' => 1),
678 'smaller' => array('label' => $langs->trans("Size").' ('.$langs->trans("SmallerThan").")", 'data-placeholder' => $langs->trans('NumberOfBytes')),
679 'larger' => array('label' => $langs->trans("Size").' ('.$langs->trans("LargerThan").")", 'data-placeholder' => $langs->trans('NumberOfBytes')),
680 'X3' => '---',
681 'withtrackingid' => array('label' => 'WithDolTrackingID', 'data-noparam' => 1),
682 'withouttrackingid' => array('label' => 'WithoutDolTrackingID', 'data-noparam' => 1),
683 'withtrackingidinmsgid' => array('label' => 'WithDolTrackingIDInMsgId', 'data-noparam' => 1),
684 'withouttrackingidinmsgid' => array('label' => 'WithoutDolTrackingIDInMsgId', 'data-noparam' => 1),
685 'X4' => '---',
686 'isnotanswer' => array('label' => 'IsNotAnAnswer', 'data-noparam' => 1),
687 'isanswer' => array('label' => 'IsAnAnswer', 'data-noparam' => 1)
688 );
689 print $form->selectarray('filtertype', $arrayoftypes, '', 1, 0, 0, '', 1, 0, 0, '', 'maxwidth300', 1, '', 2);
690
691 print "\n";
692 print '<script>';
693 print 'jQuery("#filtertype").change(function() {
694 console.log("We change a filter");
695 if (jQuery("#filtertype option:selected").attr("data-noparam")) {
696 jQuery("#rulevalue").attr("placeholder", "");
697 jQuery("#rulevalue").text("");
698 jQuery("#rulevalue").prop("disabled", true);
699 jQuery("#rulevaluehelp").addClass("unvisible");
700 } else {
701 jQuery("#rulevalue").prop("disabled", false);
702 jQuery("#rulevaluehelp").removeClass("unvisible");
703 }
704 jQuery("#rulevalue").attr("placeholder", (jQuery("#filtertype option:selected").attr("data-placeholder")));
705 ';
706 /*$noparam = array();
707 foreach ($arrayoftypes as $key => $value)
708 {
709 if ($value['noparam']) $noparam[] = $key;
710 }*/
711 print '})';
712 print '</script>'."\n";
713
714 print '</td><td class="nowraponall">';
715 print '<div class="nowraponall">';
716 print '<input type="text" name="rulevalue" id="rulevalue" class="inline-block valignmiddle">';
717 print '<div class="inline-block valignmiddle unvisible" id="rulevaluehelp">';
718 print img_warning($langs->trans("FilterSearchImapHelp"), '', 'pictowarning classfortooltip');
719 print '</div>';
720 print '</div>';
721 print '</td>';
722 print '<td class="right"><input type="submit" name="addfilter" id="addfilter" class="flat button smallpaddingimp" value="'.$langs->trans("Add").'"></td>';
723 print '</tr>';
724 // List filters
725 foreach ($object->filters as $rulefilter) {
726 $rulefilterobj = new EmailCollectorFilter($db);
727 $rulefilterobj->fetch($rulefilter['id']);
728
729 print '<tr class="oddeven">';
730 print '<td title="'.dol_escape_htmltag($langs->trans("Filter").': '.$rulefilter['type']).'">';
731 print $langs->trans($arrayoftypes[$rulefilter['type']]['label']);
732 print '</td>';
733 print '<td>'.$rulefilter['rulevalue'].'</td>';
734 print '<td class="right">';
735 print ' <a href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&action=deletefilter&token='.urlencode(newToken()).'&filterid='.$rulefilter['id'].'">'.img_delete().'</a>';
736 print '</td>';
737 print '</tr>';
738 }
739
740 print '</tr>';
741 print '</table>';
742 print '</div>';
743
744 print '<div class="clearboth"></div><br><br>';
745
746 // Operations
747 print '<div class="div-table-responsive-no-min">';
748 print '<table id="tablelines" class="noborder noshadow">';
749 print '<tr class="liste_titre nodrag nodrop">';
750 print '<td>'.img_picto('', 'technic', 'class="pictofixedwidth"').$form->textwithpicto($langs->trans("EmailcollectorOperations"), $langs->trans("EmailcollectorOperationsDesc")).'</td>';
751 print '<td>';
752 $htmltext = $langs->transnoentitiesnoconv("OperationParamDesc");
753 print $form->textwithpicto($langs->trans("Parameters"), $htmltext, 1, 'help', '', 0, 2, 'operationparamtt');
754 print '</td>';
755 print '<td></td>';
756 print '<td></td>';
757 print '</tr>';
758
759 $arrayoftypes = array(
760 'loadthirdparty' => $langs->trans('LoadThirdPartyFromName', $langs->transnoentities("ThirdPartyName").'/'.$langs->transnoentities("AliasNameShort").'/'.$langs->transnoentities("Email").'/'.$langs->transnoentities("ID")),
761 'loadandcreatethirdparty' => $langs->trans('LoadThirdPartyFromNameOrCreate', $langs->transnoentities("ThirdPartyName").'/'.$langs->transnoentities("AliasNameShort").'/'.$langs->transnoentities("Email").'/'.$langs->transnoentities("ID")),
762 'recordjoinpiece' => 'AttachJoinedDocumentsToObject',
763 'recordevent' => 'RecordEvent'
764 );
765 $arrayoftypesnocondition = $arrayoftypes;
766 if (isModEnabled('project')) {
767 $arrayoftypes['project'] = 'CreateLeadAndThirdParty';
768 }
769 $arrayoftypesnocondition['project'] = 'CreateLeadAndThirdParty';
770 if (isModEnabled('ticket')) {
771 $arrayoftypes['ticket'] = 'CreateTicketAndThirdParty';
772 }
773 $arrayoftypesnocondition['ticket'] = 'CreateTicketAndThirdParty';
774 if (isModEnabled('recruitment')) {
775 $arrayoftypes['candidature'] = 'CreateCandidature';
776 }
777 $arrayoftypesnocondition['candidature'] = 'CreateCandidature';
778
779 // support hook for add action
780 $parameters = array('arrayoftypes' => $arrayoftypes);
781 $res = $hookmanager->executeHooks('addMoreActionsEmailCollector', $parameters, $object, $action);
782
783 if ($res) {
784 $arrayoftypes = $hookmanager->resArray;
785 } else {
786 foreach ($hookmanager->resArray as $k => $desc) {
787 $arrayoftypes[$k] = $desc;
788 }
789 }
790
791 // Add operation
792 print '<tr class="oddeven nodrag nodrop">';
793 print '<td>';
794 print $form->selectarray('operationtype', $arrayoftypes, '', 1, 0, 0, '', 1, 0, 0, '', 'minwidth150 maxwidth250', 1);
795 print '</td><td>';
796 print '<textarea class="centpercent" name="operationparam" rows="3"></textarea>';
797 print '</td>';
798 print '<td>';
799 print '</td>';
800 print '<td class="right"><input type="submit" name="addoperation" id="addoperation" class="flat button smallpaddingimp" value="'.$langs->trans("Add").'"></td>';
801 print '</tr>';
802 // List operations
803 $nboflines = count($object->actions);
804 $table_element_line = 'emailcollector_emailcollectoraction';
805 $fk_element = 'position';
806 $i = 0;
807 foreach ($object->actions as $ruleaction) {
808 $ruleactionobj = new EmailCollectorAction($db);
809 $ruleactionobj->fetch($ruleaction['id']);
810
811 print '<tr class="drag drop oddeven" id="row-'.$ruleaction['id'].'">';
812 print '<td title="'.dol_escape_htmltag($langs->trans("Operation").': '.$ruleaction['type']).'">';
813 print '<!-- type of action: '.$ruleaction['type'].' -->';
814 if (array_key_exists($ruleaction['type'], $arrayoftypes)) {
815 print $langs->trans($arrayoftypes[$ruleaction['type']]);
816 } else {
817 if (array_key_exists($ruleaction['type'], $arrayoftypesnocondition)) {
818 print '<span class="opacitymedium">'.$langs->trans($arrayoftypesnocondition[$ruleaction['type']]).' - '.$langs->trans("Disabled").'</span>';
819 }
820 }
821
822 if (in_array($ruleaction['type'], array('recordevent'))) {
823 print $form->textwithpicto('', $langs->transnoentitiesnoconv('IfTrackingIDFoundEventWillBeLinked'));
824 } elseif (in_array($ruleaction['type'], array('loadthirdparty', 'loadandcreatethirdparty'))) {
825 print $form->textwithpicto('', $langs->transnoentitiesnoconv('EmailCollectorLoadThirdPartyHelp'));
826 }
827 print '</td>';
828 print '<td class="wordbreak minwidth300 small">';
829 if ($action == 'editoperation' && $ruleaction['id'] == $operationid) {
830 //print '<input type="text" class="quatrevingtquinzepercent" name="operationparam2" value="'.dol_escape_htmltag($ruleaction['actionparam']).'"><br>';
831 print '<textarea class="centpercent" name="operationparam2" rows="3">';
832 print dol_escape_htmltag($ruleaction['actionparam'], 0, 1);
833 print '</textarea>';
834 print '<input type="hidden" name="rowidoperation2" value="'.$ruleaction['id'].'">';
835 print '<input type="submit" class="button small button-save" name="saveoperation2" value="'.$langs->trans("Save").'">';
836 print '<input type="submit" class="button small button-cancel" name="cancel" value="'.$langs->trans("Cancel").'">';
837 } else {
838 print dol_nl2br(dol_escape_htmltag($ruleaction['actionparam'], 0, 1));
839 }
840 print '</td>';
841 // Move up/down
842 print '<td class="center linecolmove tdlineupdown">';
843 if ($i > 0) {
844 print '<a class="lineupdown" href="'.dolBuildUrl($_SERVER['PHP_SELF'], ['action' => 'up', 'rowid' => $ruleaction['id']], true).'">'.img_up('default', 0, 'imgupforline').'</a>';
845 }
846 if ($i < count($object->actions) - 1) {
847 print '<a class="lineupdown" href="'.dolBuildUrl($_SERVER['PHP_SELF'], ['action' => 'down', 'rowid' => $ruleaction['id']], true).'">'.img_down('default', 0, 'imgdownforline').'</a>';
848 }
849 print '</td>';
850 // Delete
851 print '<td class="right nowraponall">';
852 print '<a class="editfielda marginrightonly" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&action=editoperation&token='.newToken().'&operationid='.$ruleaction['id'].'">'.img_edit().'</a>';
853 print ' <a href="'.dolBuildUrl($_SERVER["PHP_SELF"], ['id' => $object->id, 'action' => 'deleteoperation', 'operationid' => $ruleaction['id']], true).'">'.img_delete().'</a>';
854 print '</td>';
855 print '</tr>';
856 $i++;
857 }
858
859 print '</tr>';
860 print '</table>';
861 print '</div>';
862
863 if (!empty($conf->use_javascript_ajax)) {
864 $urltorefreshaftermove = DOL_URL_ROOT.'/admin/emailcollector_card.php?id='.$id;
865 include DOL_DOCUMENT_ROOT.'/core/tpl/ajaxrow.tpl.php';
866 }
867
868 print '</form>';
869
870 print '</div>';
871 print '</div>'; // End <div class="fichecenter">
872
873
874 print '<div class="clearboth"></div><br>';
875
876 print dol_get_fiche_end();
877
878 // Buttons for actions
879 if ($action != 'presend' && $action != 'editline') {
880 print '<div class="tabsAction">'."\n";
881 $parameters = array();
882 $reshook = $hookmanager->executeHooks('addMoreActionsButtons', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
883 if ($reshook < 0) {
884 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
885 }
886
887 if (empty($reshook)) {
888 // Edit
889 print '<div class="inline-block divButAction"><a class="butAction" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&action=edit&token='.newToken().'">'.$langs->trans("Edit").'</a></div>';
890
891 // Clone
892 print '<div class="inline-block divButAction"><a class="butAction butActionClone" href="'.$_SERVER['PHP_SELF'].'?id='.$object->id.'&action=clone&token='.newToken().'&object=order">'.$langs->trans("ToClone").'</a></div>';
893
894 // Collect now
895 print '<div class="inline-block divButAction"><a class="butAction reposition" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&action=collecttest&token='.newToken().'">'.$langs->trans("TestCollectNow").'</a></div>';
896
897 if (count($object->actions) > 0) {
898 print '<div class="inline-block divButAction"><a class="butAction" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&action=collect&token='.newToken().'">'.$langs->trans("CollectNow").'</a></div>';
899 } else {
900 print '<div class="inline-block divButAction"><a class="butActionRefused" href="#" title="'.dol_escape_htmltag($langs->trans("NoOperations")).'">'.$langs->trans("CollectNow").'</a></div>';
901 }
902
903 print '<div class="inline-block divButAction"><a class="butActionDelete" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&action=delete&token='.urlencode(newToken()).'">'.$langs->trans('Delete').'</a></div>';
904 }
905 print '</div>'."\n";
906 }
907
908 if (!empty($debuginfo)) {
909 print info_admin($debuginfo);
910 }
911}
912
913// End of page
914llxFooter();
915$db->close();
$id
Support class for third parties, contacts, members, users or resources.
Definition account.php:47
if(! $sortfield) if(! $sortorder) $object
Definition account.php:100
llxFooter($comment='', $zone='private', $disabledoutputofmessages=0)
Empty footer.
Definition wrapper.php:91
if(!defined('NOREQUIRESOC')) if(!defined( 'NOREQUIRETRAN')) if(!defined('NOTOKENRENEWAL')) if(!defined( 'NOREQUIREMENU')) if(!defined('NOREQUIREHTML')) if(!defined( 'NOREQUIREAJAX')) llxHeader($head='', $title='', $help_url='', $target='', $disablejs=0, $disablehead=0, $arrayofjs='', $arrayofcss='', $morequerystring='', $morecssonbody='', $replacemainareaby='', $disablenofollow=0, $disablenoindex=0)
Empty header.
Definition wrapper.php:73
Class for EmailCollectorAction.
Class for EmailCollectorFilter.
Class for EmailCollector.
Class to offer components to list and upload files.
Class to manage generation of HTML components Only common components must be here.
emailcollectorPrepareHead($object)
Prepare array of tabs for EmailCollector.
if(!isModEnabled('ai')||!getDolGlobalString('AI_ASSISTANT_ENABLED')) global $conf
The main.inc.php has been included so the following variable are now defined:
if(!isModEnabled('ai')||!getDolGlobalString('AI_ASSISTANT_ENABLED')) global $db
API class for accounts.
setEventMessages($mesg, $mesgs, $style='mesgs', $messagekey='', $noduplicate=0, $attop=0)
Set event messages in dol_events session object.
img_picto($titlealt, $picto, $moreatt='', $pictoisfullpath=0, $srconly=0, $notitle=0, $alt='', $morecss='', $marginleftonlyshort=2, $allowothertags=array())
Show picto whatever it's its name (generic function)
img_warning($titlealt='default', $moreatt='', $morecss='pictowarning')
Show warning logo.
info_admin($text, $infoonimgalt=0, $nodiv=0, $admin='1', $morecss='hideonsmartphone', $textfordropdown='', $picto='', $textonpictotooltip='')
Show information in HTML for admin users or standard users.
img_delete($titlealt='default', $other='class="pictodelete"', $morecss='')
Show delete logo.
GETPOSTINT($paramname, $method=0)
Return the value of a $_GET or $_POST supervariable, converted into integer.
dol_get_fiche_head($links=array(), $active='', $title='', $notab=0, $picto='', $pictoisfullpath=0, $morehtmlright='', $morecss='', $limittoshow=0, $moretabssuffix='', $dragdropfile=0, $morecssdiv='')
Show tabs of a record.
dol_get_fiche_end($notab=0)
Return tab footer of a card.
dol_nl2br($stringtoencode, $nl2brmode=0, $forxml=false)
Replace CRLF in string with a HTML BR tag.
img_down($titlealt='default', $selected=0, $moreclass='')
Show down arrow logo.
getDolGlobalInt($key, $default=0)
Return a Dolibarr global constant int value.
if(!function_exists( 'dol_getprefix')) dol_include_once($relpath, $classname='')
Make an include_once using default root and alternate root if it fails.
GETPOST($paramname, $check='alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0)
Return value of a param into GET or POST supervariable.
load_fiche_titre($title, $morehtmlright='', $picto='generic', $pictoisfullpath=0, $id='', $morecssontable='', $morehtmlcenter='', $morecssonpicto='widthpictotitle')
Load a title with picto.
getDolGlobalString($key, $default='')
Return a Dolibarr global constant string value.
isModEnabled($module)
Is Dolibarr module enabled.
img_edit($titlealt='default', $float=0, $other='')
Show logo edit/modify fiche.
img_up($titlealt='default', $selected=0, $moreclass='')
Show top arrow logo.
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='', $logcontext=null)
Write log message into outputs.
dol_escape_htmltag($stringtoescape, $keepb=0, $keepn=0, $noescapetags='', $escapeonlyhtmltags=0, $cleanalsojavascript=0)
Returns text escaped for inclusion in HTML alt or title or value tags, or into values of HTML input f...
getSupportedOauth2Array()
Return array of tabs to use on pages to setup cron module.
accessforbidden($message='', $printheader=1, $printfooter=1, $showonlymessage=0, $params=null)
Show a message to say access is forbidden and stop program.