dolibarr  13.0.2
emailcollector.class.php
Go to the documentation of this file.
1 <?php
2 /* Copyright (C) 2017 Laurent Destailleur <eldy@users.sourceforge.net>
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 3 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program. If not, see <https://www.gnu.org/licenses/>.
16  */
17 
24 // Put here all includes required by your class file
25 require_once DOL_DOCUMENT_ROOT.'/core/class/commonobject.class.php';
26 require_once DOL_DOCUMENT_ROOT.'/contact/class/contact.class.php';
27 require_once DOL_DOCUMENT_ROOT.'/societe/class/societe.class.php';
28 require_once DOL_DOCUMENT_ROOT.'/projet/class/project.class.php';
29 require_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php';
30 require_once DOL_DOCUMENT_ROOT.'/ticket/class/ticket.class.php';
31 require_once DOL_DOCUMENT_ROOT.'/recruitment/class/recruitmentcandidature.class.php';
32 
33 
38 {
42  public $element = 'emailcollector';
46  public $table_element = 'emailcollector_emailcollector';
50  public $ismultientitymanaged = 1;
54  public $isextrafieldmanaged = 0;
55 
59  public $picto = 'email';
60 
64  public $fk_element = 'fk_emailcollector';
65 
69  protected $childtables = array();
73  protected $childtablesoncascade = array('emailcollector_emailcollectorfilter', 'emailcollector_emailcollectoraction');
74 
75 
95  // BEGIN MODULEBUILDER PROPERTIES
99  public $fields = array(
100  'rowid' => array('type'=>'integer', 'label'=>'TechnicalID', 'visible'=>2, 'enabled'=>1, 'position'=>1, 'notnull'=>1, 'index'=>1),
101  'entity' => array('type'=>'integer', 'label'=>'Entity', 'enabled'=>1, 'visible'=>0, 'default'=>1, 'notnull'=>1, 'index'=>1, 'position'=>20),
102  'ref' => array('type'=>'varchar(128)', 'label'=>'Ref', 'enabled'=>1, 'visible'=>1, 'notnull'=>1, 'showoncombobox'=>1, 'index'=>1, 'position'=>10, 'searchall'=>1, 'help'=>'Example: MyCollector1'),
103  'label' => array('type'=>'varchar(255)', 'label'=>'Label', 'visible'=>1, 'enabled'=>1, 'position'=>30, 'notnull'=>-1, 'searchall'=>1, 'help'=>'Example: My Email collector'),
104  'description' => array('type'=>'text', 'label'=>'Description', 'visible'=>-1, 'enabled'=>1, 'position'=>60, 'notnull'=>-1),
105  'host' => array('type'=>'varchar(255)', 'label'=>'EMailHost', 'visible'=>1, 'enabled'=>1, 'position'=>90, 'notnull'=>1, 'searchall'=>1, 'comment'=>"IMAP server", 'help'=>'Example: imap.gmail.com'),
106  'hostcharset' => array('type'=>'varchar(16)', 'label'=>'HostCharset', 'visible'=>-1, 'enabled'=>1, 'position'=>91, 'notnull'=>0, 'searchall'=>0, 'comment'=>"IMAP server charset", 'help'=>'Example: "UTF-8" (May be "US-ASCII" with some Office365)'),
107  'login' => array('type'=>'varchar(128)', 'label'=>'Login', 'visible'=>1, 'enabled'=>1, 'position'=>101, 'notnull'=>-1, 'index'=>1, 'comment'=>"IMAP login", 'help'=>'Example: myaccount@gmail.com'),
108  'password' => array('type'=>'password', 'label'=>'Password', 'visible'=>-1, 'enabled'=>1, 'position'=>102, 'notnull'=>-1, 'comment'=>"IMAP password", 'help'=>'WithGMailYouCanCreateADedicatedPassword'),
109  'source_directory' => array('type'=>'varchar(255)', 'label'=>'MailboxSourceDirectory', 'visible'=>-1, 'enabled'=>1, 'position'=>103, 'notnull'=>1, 'default' => 'Inbox', 'help'=>'Example: INBOX'),
110  //'filter' => array('type'=>'text', 'label'=>'Filter', 'visible'=>1, 'enabled'=>1, 'position'=>105),
111  //'actiontodo' => array('type'=>'varchar(255)', 'label'=>'ActionToDo', 'visible'=>1, 'enabled'=>1, 'position'=>106),
112  'target_directory' => array('type'=>'varchar(255)', 'label'=>'MailboxTargetDirectory', 'visible'=>1, 'enabled'=>1, 'position'=>110, 'notnull'=>0, 'help'=>"EmailCollectorTargetDir"),
113  'maxemailpercollect' => array('type'=>'integer', 'label'=>'MaxEmailCollectPerCollect', 'visible'=>-1, 'enabled'=>1, 'position'=>111, 'default'=>100),
114  'datelastresult' => array('type'=>'datetime', 'label'=>'DateLastCollectResult', 'visible'=>1, 'enabled'=>'$action != "create" && $action != "edit"', 'position'=>121, 'notnull'=>-1,),
115  'codelastresult' => array('type'=>'varchar(16)', 'label'=>'CodeLastResult', 'visible'=>1, 'enabled'=>'$action != "create" && $action != "edit"', 'position'=>122, 'notnull'=>-1,),
116  'lastresult' => array('type'=>'varchar(255)', 'label'=>'LastResult', 'visible'=>1, 'enabled'=>'$action != "create" && $action != "edit"', 'position'=>123, 'notnull'=>-1,),
117  'datelastok' => array('type'=>'datetime', 'label'=>'DateLastcollectResultOk', 'visible'=>1, 'enabled'=>'$action != "create"', 'position'=>125, 'notnull'=>-1,),
118  'note_public' => array('type'=>'html', 'label'=>'NotePublic', 'visible'=>0, 'enabled'=>1, 'position'=>61, 'notnull'=>-1,),
119  'note_private' => array('type'=>'html', 'label'=>'NotePrivate', 'visible'=>0, 'enabled'=>1, 'position'=>62, 'notnull'=>-1,),
120  'date_creation' => array('type'=>'datetime', 'label'=>'DateCreation', 'visible'=>-2, 'enabled'=>1, 'position'=>500, 'notnull'=>1,),
121  'tms' => array('type'=>'timestamp', 'label'=>'DateModification', 'visible'=>-2, 'enabled'=>1, 'position'=>501, 'notnull'=>1,),
122  //'date_validation' => array('type'=>'datetime', 'label'=>'DateCreation', 'enabled'=>1, 'visible'=>-2, 'position'=>502),
123  'fk_user_creat' => array('type'=>'integer:User:user/class/user.class.php', 'label'=>'UserAuthor', 'visible'=>-2, 'enabled'=>1, 'position'=>510, 'notnull'=>1,),
124  'fk_user_modif' => array('type'=>'integer:User:user/class/user.class.php', 'label'=>'UserModif', 'visible'=>-2, 'enabled'=>1, 'position'=>511, 'notnull'=>-1,),
125  //'fk_user_valid' =>array('type'=>'integer', 'label'=>'UserValidation', 'enabled'=>1, 'visible'=>-1, 'position'=>512),
126  'import_key' => array('type'=>'varchar(14)', 'label'=>'ImportId', 'visible'=>-2, 'enabled'=>1, 'position'=>1000, 'notnull'=>-1,),
127  'status' => array('type'=>'integer', 'label'=>'Status', 'visible'=>1, 'enabled'=>1, 'position'=>1000, 'notnull'=>1, 'index'=>1, 'arrayofkeyval'=>array('0'=>'Inactive', '1'=>'Active'))
128  );
129 
130 
134  public $rowid;
135 
139  public $ref;
140 
144  public $entity;
145 
149  public $label;
150 
151 
155  public $status;
156 
160  public $date_creation;
161 
165  public $tms;
166 
170  public $fk_user_creat;
171 
175  public $fk_user_modif;
176 
180  public $import_key;
181 
182 
183  public $host;
184  public $hostcharset;
185  public $login;
186  public $password;
187  public $source_directory;
188  public $target_directory;
189  public $maxemailpercollect;
190 
194  public $datelastresult;
195 
196 
197  public $lastresult;
198  // END MODULEBUILDER PROPERTIES
199 
200  public $filters;
201  public $actions;
202 
203  public $debuginfo;
204 
205  const STATUS_DISABLED = 0;
206  const STATUS_ENABLED = 1;
207 
208 
214  public function __construct(DoliDB $db)
215  {
216  global $conf, $langs;
217 
218  $this->db = $db;
219 
220  if (empty($conf->global->MAIN_SHOW_TECHNICAL_ID) && isset($this->fields['rowid'])) $this->fields['rowid']['visible'] = 0;
221  if (empty($conf->multicompany->enabled) && isset($this->fields['entity'])) $this->fields['entity']['enabled'] = 0;
222 
223  // Unset fields that are disabled
224  foreach ($this->fields as $key => $val)
225  {
226  if (isset($val['enabled']) && empty($val['enabled']))
227  {
228  unset($this->fields[$key]);
229  }
230  }
231 
232  // Translate some data of arrayofkeyval
233  foreach ($this->fields as $key => $val)
234  {
235  if (!empty($val['arrayofkeyval']) && is_array($val['arrayofkeyval']))
236  {
237  foreach ($val['arrayofkeyval'] as $key2 => $val2)
238  {
239  $this->fields[$key]['arrayofkeyval'][$key2] = $langs->trans($val2);
240  }
241  }
242  }
243  }
244 
252  public function create(User $user, $notrigger = false)
253  {
254  $id = $this->createCommon($user, $notrigger);
255 
256  if (is_array($this->filters) && count($this->filters)) {
257  $emailcollectorfilter = new EmailCollectorFilter($this->db);
258 
259  foreach ($this->filters as $filter) {
260  $emailcollectorfilter->type = $filter['type'];
261  $emailcollectorfilter->rulevalue = $filter['rulevalue'];
262  $emailcollectorfilter->fk_emailcollector = $this->id;
263  $emailcollectorfilter->status = $filter['status'];
264 
265  $emailcollectorfilter->create($user);
266  }
267  }
268 
269  if (is_array($this->filters) && count($this->filters)) {
270  $emailcollectoroperation = new EmailCollectorAction($this->db);
271 
272  foreach ($this->actions as $operation) {
273  $emailcollectoroperation->type = $operation['type'];
274  $emailcollectoroperation->actionparam = $operation['actionparam'];
275  $emailcollectoroperation->fk_emailcollector = $this->id;
276  $emailcollectoroperation->status = $operation['status'];
277  $emailcollectoroperation->position = $operation['position'];
278 
279  $emailcollectoroperation->create($user);
280  }
281  }
282 
283  return $id;
284  }
285 
293  public function createFromClone(User $user, $fromid)
294  {
295  global $langs, $extrafields;
296  $error = 0;
297 
298  dol_syslog(__METHOD__, LOG_DEBUG);
299 
300  $object = new self($this->db);
301 
302  $this->db->begin();
303 
304  // Load source object
305  $object->fetchCommon($fromid);
306 
307  $object->fetchFilters(); // Rules
308  $object->fetchActions(); // Operations
309 
310  // Reset some properties
311  unset($object->id);
312  unset($object->fk_user_creat);
313  unset($object->import_key);
314 
315  // Clear fields
316  $object->ref = "copy_of_".$object->ref;
317  $object->title = $langs->trans("CopyOf")." ".$object->title;
318  // ...
319  // Clear extrafields that are unique
320  if (is_array($object->array_options) && count($object->array_options) > 0)
321  {
322  $extrafields->fetch_name_optionals_label($this->table_element);
323  foreach ($object->array_options as $key => $option)
324  {
325  $shortkey = preg_replace('/options_/', '', $key);
326  if (!empty($extrafields->attributes[$this->element]['unique'][$shortkey]))
327  {
328  //var_dump($key); var_dump($clonedObj->array_options[$key]); exit;
329  unset($object->array_options[$key]);
330  }
331  }
332  }
333 
334  // Create clone
335  $object->context['createfromclone'] = 'createfromclone';
336  $result = $object->create($user);
337  if ($result < 0) {
338  $error++;
339  $this->error = $object->error;
340  $this->errors = $object->errors;
341  }
342 
343  unset($object->context['createfromclone']);
344 
345  // End
346  if (!$error) {
347  $this->db->commit();
348  return $object;
349  } else {
350  $this->db->rollback();
351  return -1;
352  }
353  }
354 
362  public function fetch($id, $ref = null)
363  {
364  $result = $this->fetchCommon($id, $ref);
365  //if ($result > 0 && ! empty($this->table_element_line)) $this->fetchLines();
366  return $result;
367  }
368 
374  /*
375  public function fetchLines()
376  {
377  $this->lines=array();
378 
379  // Load lines with object EmailCollectorLine
380 
381  return count($this->lines)?1:0;
382  }
383  */
384 
396  public function fetchAll(User $user, $activeOnly = 0, $sortfield = 's.rowid', $sortorder = 'ASC', $limit = 100, $page = 0)
397  {
398  global $langs;
399 
400  $obj_ret = array();
401 
402  $sql = "SELECT s.rowid";
403  $sql .= " FROM ".MAIN_DB_PREFIX."emailcollector_emailcollector as s";
404  $sql .= ' WHERE s.entity IN ('.getEntity('emailcollector').')';
405  if ($activeOnly) {
406  $sql .= " AND s.status = 1";
407  }
408  $sql .= $this->db->order($sortfield, $sortorder);
409  if ($limit) {
410  if ($page < 0) {
411  $page = 0;
412  }
413  $offset = $limit * $page;
414 
415  $sql .= $this->db->plimit($limit + 1, $offset);
416  }
417 
418  $result = $this->db->query($sql);
419  if ($result) {
420  $num = $this->db->num_rows($result);
421  $i = 0;
422  while ($i < $num)
423  {
424  $obj = $this->db->fetch_object($result);
425  $emailcollector_static = new EmailCollector($this->db);
426  if ($emailcollector_static->fetch($obj->rowid)) {
427  $obj_ret[] = $emailcollector_static;
428  }
429  $i++;
430  }
431  } else {
432  $this->errors[] = 'EmailCollector::fetchAll Error when retrieve emailcollector list';
433  dol_syslog('EmailCollector::fetchAll Error when retrieve emailcollector list', LOG_ERR);
434  $ret = -1;
435  }
436  if (!count($obj_ret)) {
437  dol_syslog('EmailCollector::fetchAll No emailcollector found', LOG_DEBUG);
438  }
439 
440  return $obj_ret;
441  }
442 
450  public function update(User $user, $notrigger = false)
451  {
452  return $this->updateCommon($user, $notrigger);
453  }
454 
462  public function delete(User $user, $notrigger = false)
463  {
464  return $this->deleteCommon($user, $notrigger, 1);
465  }
466 
477  public function getNomUrl($withpicto = 0, $option = '', $notooltip = 0, $morecss = '', $save_lastsearch_value = -1)
478  {
479  global $conf, $langs, $hookmanager;
480 
481  if (!empty($conf->dol_no_mouse_hover)) $notooltip = 1; // Force disable tooltips
482 
483  $result = '';
484 
485  $label = '<u>'.$langs->trans("EmailCollector").'</u>';
486  $label .= '<br>';
487  $label .= '<b>'.$langs->trans('Ref').':</b> '.$this->ref;
488 
489  $url = dol_buildpath('/admin/emailcollector_card.php', 1).'?id='.$this->id;
490 
491  if ($option != 'nolink')
492  {
493  // Add param to save lastsearch_values or not
494  $add_save_lastsearch_values = ($save_lastsearch_value == 1 ? 1 : 0);
495  if ($save_lastsearch_value == -1 && preg_match('/list\.php/', $_SERVER["PHP_SELF"])) {
496  $add_save_lastsearch_values = 1;
497  }
498  if ($add_save_lastsearch_values) {
499  $url .= '&save_lastsearch_values=1';
500  }
501  }
502 
503  $linkclose = '';
504  if (empty($notooltip))
505  {
506  if (!empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER))
507  {
508  $label = $langs->trans("ShowEmailCollector");
509  $linkclose .= ' alt="'.dol_escape_htmltag($label, 1).'"';
510  }
511  $linkclose .= ' title="'.dol_escape_htmltag($label, 1).'"';
512  $linkclose .= ' class="classfortooltip'.($morecss ? ' '.$morecss : '').'"';
513 
514  /*
515  $hookmanager->initHooks(array('myobjectdao'));
516  $parameters=array('id'=>$this->id);
517  $reshook=$hookmanager->executeHooks('getnomurltooltip',$parameters,$this,$action); // Note that $action and $object may have been modified by some hooks
518  if ($reshook > 0) $linkclose = $hookmanager->resPrint;
519  */
520  } else $linkclose = ($morecss ? ' class="'.$morecss.'"' : '');
521 
522  $linkstart = '<a href="'.$url.'"';
523  $linkstart .= $linkclose.'>';
524  $linkend = '</a>';
525 
526  $result .= $linkstart;
527  if ($withpicto) $result .= img_object(($notooltip ? '' : $label), ($this->picto ? $this->picto : 'generic'), ($notooltip ? (($withpicto != 2) ? 'class="paddingright"' : '') : 'class="'.(($withpicto != 2) ? 'paddingright ' : '').'classfortooltip"'), 0, 0, $notooltip ? 0 : 1);
528  if ($withpicto != 2) $result .= $this->ref;
529  $result .= $linkend;
530  //if ($withpicto != 2) $result.=(($addlabel && $this->label) ? $sep . dol_trunc($this->label, ($addlabel > 1 ? $addlabel : 0)) : '');
531 
532  global $action, $hookmanager;
533  $hookmanager->initHooks(array('emailcollectordao'));
534  $parameters = array('id'=>$this->id, 'getnomurl'=>$result);
535  $reshook = $hookmanager->executeHooks('getNomUrl', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
536  if ($reshook > 0) $result = $hookmanager->resPrint;
537  else $result .= $hookmanager->resPrint;
538 
539  return $result;
540  }
541 
548  public function getLibStatut($mode = 0)
549  {
550  return $this->LibStatut($this->status, $mode);
551  }
552 
553  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
561  public function LibStatut($status, $mode = 0)
562  {
563  // phpcs:enable
564  if (empty($this->labelStatus) || empty($this->labelStatusShort))
565  {
566  global $langs;
567  //$langs->load("mymodule");
568  $this->labelStatus[self::STATUS_ENABLED] = $langs->trans('Enabled');
569  $this->labelStatus[self::STATUS_DISABLED] = $langs->trans('Disabled');
570  $this->labelStatusShort[self::STATUS_ENABLED] = $langs->trans('Enabled');
571  $this->labelStatusShort[self::STATUS_DISABLED] = $langs->trans('Disabled');
572  }
573 
574  $statusType = 'status5';
575  if ($status == self::STATUS_ENABLED) $statusType = 'status4';
576 
577  return dolGetStatus($this->labelStatus[$status], $this->labelStatusShort[$status], '', $statusType, $mode);
578  }
579 
586  public function info($id)
587  {
588  $sql = 'SELECT rowid, date_creation as datec, tms as datem,';
589  $sql .= ' fk_user_creat, fk_user_modif';
590  $sql .= ' FROM '.MAIN_DB_PREFIX.$this->table_element.' as t';
591  $sql .= ' WHERE t.rowid = '.$id;
592  $result = $this->db->query($sql);
593  if ($result)
594  {
595  if ($this->db->num_rows($result))
596  {
597  $obj = $this->db->fetch_object($result);
598  $this->id = $obj->rowid;
599  if ($obj->fk_user_author)
600  {
601  $cuser = new User($this->db);
602  $cuser->fetch($obj->fk_user_author);
603  $this->user_creation = $cuser;
604  }
605 
606  if ($obj->fk_user_valid)
607  {
608  $vuser = new User($this->db);
609  $vuser->fetch($obj->fk_user_valid);
610  $this->user_validation = $vuser;
611  }
612 
613  if ($obj->fk_user_cloture)
614  {
615  $cluser = new User($this->db);
616  $cluser->fetch($obj->fk_user_cloture);
617  $this->user_cloture = $cluser;
618  }
619 
620  $this->date_creation = $this->db->jdate($obj->datec);
621  $this->date_modification = $this->db->jdate($obj->datem);
622  $this->date_validation = $this->db->jdate($obj->datev);
623  }
624 
625  $this->db->free($result);
626  } else {
627  dol_print_error($this->db);
628  }
629  }
630 
637  public function initAsSpecimen()
638  {
639  $this->initAsSpecimenCommon();
640  }
641 
648  public function fetchFilters()
649  {
650  $this->filters = array();
651 
652  $sql = 'SELECT rowid, type, rulevalue, status';
653  $sql .= ' FROM '.MAIN_DB_PREFIX.'emailcollector_emailcollectorfilter';
654  $sql .= ' WHERE fk_emailcollector = '.$this->id;
655  //$sql.= ' ORDER BY position';
656 
657  $resql = $this->db->query($sql);
658  if ($resql)
659  {
660  $num = $this->db->num_rows($resql);
661  $i = 0;
662  while ($i < $num)
663  {
664  $obj = $this->db->fetch_object($resql);
665  $this->filters[$obj->rowid] = array('id'=>$obj->rowid, 'type'=>$obj->type, 'rulevalue'=>$obj->rulevalue, 'status'=>$obj->status);
666  $i++;
667  }
668  $this->db->free($resql);
669  } else dol_print_error($this->db);
670 
671  return 1;
672  }
673 
680  public function fetchActions()
681  {
682  $this->actions = array();
683 
684  $sql = 'SELECT rowid, type, actionparam, status';
685  $sql .= ' FROM '.MAIN_DB_PREFIX.'emailcollector_emailcollectoraction';
686  $sql .= ' WHERE fk_emailcollector = '.$this->id;
687  $sql .= ' ORDER BY position';
688 
689  $resql = $this->db->query($sql);
690  if ($resql)
691  {
692  $num = $this->db->num_rows($resql);
693  $i = 0;
694  while ($i < $num)
695  {
696  $obj = $this->db->fetch_object($resql);
697  $this->actions[$obj->rowid] = array('id'=>$obj->rowid, 'type'=>$obj->type, 'actionparam'=>$obj->actionparam, 'status'=>$obj->status);
698  $i++;
699  }
700  $this->db->free($resql);
701  } else dol_print_error($this->db);
702  }
703 
704 
712  public function getConnectStringIMAP($ssl = 1, $norsh = 0)
713  {
714  global $conf;
715 
716  // Connect to IMAP
717  $flags = '/service=imap'; // IMAP
718  if (!empty($conf->global->IMAP_FORCE_TLS)) {
719  $flags .= '/tls';
720  } elseif (empty($conf->global->IMAP_FORCE_NOSSL)) {
721  if ($ssl) $flags .= '/ssl';
722  }
723  $flags .= '/novalidate-cert';
724  //$flags.='/readonly';
725  //$flags.='/debug';
726  if ($norsh || !empty($conf->global->IMAP_FORCE_NORSH)) $flags .= '/norsh';
727 
728  $connectstringserver = '{'.$this->host.':993'.$flags.'}';
729 
730  return $connectstringserver;
731  }
732 
739  public function getEncodedUtf7($str)
740  {
741  if (function_exists('mb_convert_encoding')) {
742  // change spaces by entropy because mb_convert fail with spaces
743  $str = preg_replace("/ /", "xyxy", $str);
744  // if mb_convert work
745  if ($str = mb_convert_encoding($str, "UTF-7")) {
746  // change characters
747  $str = preg_replace("/\+A/", "&A", $str);
748  // change to spaces again
749  $str = preg_replace("/xyxy/", " ", $str);
750  return $str;
751  } else {
752  // print error and return false
753  $this->error = "error: is not possible to encode this string '".$str."'";
754  return false;
755  }
756  } else {
757  return $str;
758  }
759  }
760 
767  public function doCollect()
768  {
769  global $user;
770 
771  $nberror = 0;
772 
773  $arrayofcollectors = $this->fetchAll($user, 1);
774 
775  // Loop on each collector
776  foreach ($arrayofcollectors as $emailcollector)
777  {
778  $result = $emailcollector->doCollectOneCollector();
779  dol_syslog("doCollect result = ".$result." for emailcollector->id = ".$emailcollector->id);
780 
781  $this->error .= 'EmailCollector ID '.$emailcollector->id.':'.$emailcollector->error.'<br>';
782  if (!empty($emailcollector->errors)) $this->error .= join('<br>', $emailcollector->errors);
783  $this->output .= 'EmailCollector ID '.$emailcollector->id.': '.$emailcollector->lastresult.'<br>';
784  }
785 
786  return $nberror;
787  }
788 
799  private function overwritePropertiesOfObject(&$object, $actionparam, $messagetext, $subject, $header)
800  {
801  $errorforthisaction = 0;
802 
803  // Overwrite values with values extracted from source email
804  // $this->actionparam = 'opportunity_status=123;abc=EXTRACT:BODY:....'
805  $arrayvaluetouse = dolExplodeIntoArray($actionparam, ';', '=');
806  foreach ($arrayvaluetouse as $propertytooverwrite => $valueforproperty)
807  {
808  $tmpclass = ''; $tmpproperty = '';
809  $tmparray = explode('.', $propertytooverwrite);
810  if (count($tmparray) == 2)
811  {
812  $tmpclass = $tmparray[0];
813  $tmpproperty = $tmparray[1];
814  } else {
815  $tmpproperty = $tmparray[0];
816  }
817  if ($tmpclass && ($tmpclass != $object->element)) continue; // Property is for another type of object
818 
819  //if (property_exists($object, $tmpproperty) || preg_match('/^options_/', $tmpproperty))
820  if ($tmpproperty)
821  {
822  $sourcestring = '';
823  $sourcefield = '';
824  $regexstring = '';
825  //$transformationstring='';
826  $regforregex = array();
827  if (preg_match('/^EXTRACT:([a-zA-Z0-9]+):(.*):([^:])$/', $valueforproperty, $regforregex))
828  {
829  $sourcefield = $regforregex[1];
830  $regexstring = $regforregex[2];
831  //$transofrmationstring=$regforregex[3];
832  } elseif (preg_match('/^EXTRACT:([a-zA-Z0-9]+):(.*)$/', $valueforproperty, $regforregex))
833  {
834  $sourcefield = $regforregex[1];
835  $regexstring = $regforregex[2];
836  }
837  if (!empty($sourcefield) && !empty($regexstring))
838  {
839  if (strtolower($sourcefield) == 'body') $sourcestring = $messagetext;
840  elseif (strtolower($sourcefield) == 'subject') $sourcestring = $subject;
841  elseif (strtolower($sourcefield) == 'header') $sourcestring = $header;
842 
843  if ($sourcestring)
844  {
845  $regforval = array();
846  $regexoptions = '';
847  if (strtolower($sourcefield) == 'body') $regexoptions = 'ms'; // The m means ^ and $ char is valid at each new line. The s means the char '.' is valid for new lines char too
848  if (strtolower($sourcefield) == 'header') $regexoptions = 'm'; // The m means ^ and $ char is valid at each new line.
849 
850  //var_dump($tmpproperty.' - '.$regexstring.' - '.$regexoptions.' - '.$sourcestring);
851  if (preg_match('/'.$regexstring.'/'.$regexoptions, $sourcestring, $regforval))
852  {
853  //var_dump($regforval[count($regforval)-1]);exit;
854  // Overwrite param $tmpproperty
855  $valueextracted = isset($regforval[count($regforval) - 1]) ?trim($regforval[count($regforval) - 1]) : null;
856  if (strtolower($sourcefield) == 'header') {
857  $object->$tmpproperty = $this->decodeSMTPSubject($valueextracted);
858  } else {
859  $object->$tmpproperty = $valueextracted;
860  }
861  } else {
862  // Regex not found
863  $object->$tmpproperty = null;
864  }
865  } else {
866  // Nothing can be done for this param
867  $errorforthisaction++;
868  $this->error = 'The extract rule to use has on an unknown source (must be HEADER, SUBJECT or BODY)';
869  $this->errors[] = $this->error;
870  }
871  } elseif (preg_match('/^(SET|SETIFEMPTY):(.*)$/', $valueforproperty, $regforregex))
872  {
873  $valuecurrent = '';
874  if (preg_match('/^options_/', $tmpproperty)) $valuecurrent = $object->array_options[preg_replace('/^options_/', '', $tmpproperty)];
875  else $valuecurrent = $object->$tmpproperty;
876 
877  if ($regforregex[1] == 'SET' || empty($valuecurrent))
878  {
879  $valuetouse = $regforregex[2];
880  $substitutionarray = array();
881  $matcharray = array();
882  preg_match_all('/__([a-z0-9]+(?:_[a-z0-9]+)?)__/i', $valuetouse, $matcharray);
883  //var_dump($tmpproperty.' - '.$object->$tmpproperty.' - '.$valuetouse); var_dump($matcharray);
884  if (is_array($matcharray[1])) // $matcharray[1] is array with list of substitution key found without the __
885  {
886  foreach ($matcharray[1] as $keytoreplace)
887  {
888  if ($keytoreplace && isset($object->$keytoreplace))
889  {
890  $substitutionarray['__'.$keytoreplace.'__'] = $object->$keytoreplace;
891  }
892  }
893  }
894  //var_dump($substitutionarray);
895  dol_syslog(var_export($substitutionarray, true));
896  //var_dump($substitutionarray);
897  $valuetouse = make_substitutions($valuetouse, $substitutionarray);
898  if (preg_match('/^options_/', $tmpproperty)) $object->array_options[preg_replace('/^options_/', '', $tmpproperty)] = $valuetouse;
899  else $object->$tmpproperty = $valuetouse;
900  }
901  } else {
902  $errorforthisaction++;
903  $this->error = 'Bad syntax for description of action parameters: '.$actionparam;
904  $this->errors[] = $this->error;
905  }
906  }
907  }
908 
909  return $errorforthisaction;
910  }
911 
917  public function doCollectOneCollector()
918  {
919  global $conf, $langs, $user;
920 
921  //$conf->global->SYSLOG_FILE = 'DOL_DATA_ROOT/dolibarr_mydedicatedlofile.log';
922 
923  require_once DOL_DOCUMENT_ROOT.'/comm/action/class/actioncomm.class.php';
924 
925  dol_syslog("EmailCollector::doCollectOneCollector start", LOG_DEBUG);
926 
927  $langs->loadLangs(array("project", "companies", "mails", "errors", "ticket", "agenda"));
928 
929  $error = 0;
930  $this->output = '';
931  $this->error = '';
932 
933  $now = dol_now();
934 
935  if (empty($this->host))
936  {
937  $this->error = $langs->trans('ErrorFieldRequired', $langs->transnoentitiesnoconv('EMailHost'));
938  return -1;
939  }
940  if (empty($this->login))
941  {
942  $this->error = $langs->trans('ErrorFieldRequired', $langs->transnoentitiesnoconv('Login'));
943  return -1;
944  }
945  if (empty($this->source_directory))
946  {
947  $this->error = $langs->trans('ErrorFieldRequired', $langs->transnoentitiesnoconv('MailboxSourceDirectory'));
948  return -1;
949  }
950  if (!function_exists('imap_open'))
951  {
952  $this->error = 'IMAP function not enabled on your PHP';
953  return -2;
954  }
955 
956  $this->fetchFilters();
957  $this->fetchActions();
958 
959  $sourcedir = $this->source_directory;
960  $targetdir = ($this->target_directory ? $this->target_directory : ''); // Can be '[Gmail]/Trash' or 'mytag'
961 
962  $connectstringserver = $this->getConnectStringIMAP();
963  $connectstringsource = $connectstringserver.imap_utf7_encode($sourcedir);
964  $connectstringtarget = $connectstringserver.imap_utf7_encode($targetdir);
965 
966  $connection = imap_open($connectstringsource, $this->login, $this->password);
967  if (!$connection)
968  {
969  $this->error = 'Failed to open IMAP connection '.$connectstringsource;
970  return -3;
971  }
972  imap_errors(); // Clear stack of errors.
973 
974  $host = dol_getprefix('email');
975  //$host = '123456';
976 
977  // Define the IMAP search string
978  // See https://tools.ietf.org/html/rfc3501#section-6.4.4 for IMAPv4 (PHP not yet compatible)
979  // See https://tools.ietf.org/html/rfc1064 page 13 for IMAPv2
980  //$search='ALL';
981  $search = 'UNDELETED'; // Seems not supported by some servers
982  $searchhead = '';
983  $searchfilterdoltrackid = 0;
984  $searchfilternodoltrackid = 0;
985  $searchfilterisanswer = 0;
986  $searchfilterisnotanswer = 0;
987  foreach ($this->filters as $rule)
988  {
989  if (empty($rule['status'])) continue;
990 
991  if ($rule['type'] == 'to') {
992  $tmprulevaluearray = explode('*', $rule['rulevalue']);
993  if (count($tmprulevaluearray) >= 2) {
994  foreach ($tmprulevaluearray as $tmprulevalue) {
995  $search .= ($search ? ' ' : '').'TO "'.str_replace('"', '', $tmprulevalue).'"';
996  }
997  } else {
998  $search .= ($search ? ' ' : '').'TO "'.str_replace('"', '', $rule['rulevalue']).'"';
999  }
1000  }
1001  if ($rule['type'] == 'bcc') $search .= ($search ? ' ' : '').'BCC';
1002  if ($rule['type'] == 'cc') $search .= ($search ? ' ' : '').'CC';
1003  if ($rule['type'] == 'from') $search .= ($search ? ' ' : '').'FROM "'.str_replace('"', '', $rule['rulevalue']).'"';
1004  if ($rule['type'] == 'subject') $search .= ($search ? ' ' : '').'SUBJECT "'.str_replace('"', '', $rule['rulevalue']).'"';
1005  if ($rule['type'] == 'body') $search .= ($search ? ' ' : '').'BODY "'.str_replace('"', '', $rule['rulevalue']).'"';
1006  if ($rule['type'] == 'header') $search .= ($search ? ' ' : '').'HEADER '.$rule['rulevalue'];
1007 
1008  if ($rule['type'] == 'notinsubject') $search .= ($search ? ' ' : '').'SUBJECT NOT "'.str_replace('"', '', $rule['rulevalue']).'"';
1009  if ($rule['type'] == 'notinbody') $search .= ($search ? ' ' : '').'BODY NOT "'.str_replace('"', '', $rule['rulevalue']).'"';
1010 
1011  if ($rule['type'] == 'seen') $search .= ($search ? ' ' : '').'SEEN';
1012  if ($rule['type'] == 'unseen') $search .= ($search ? ' ' : '').'UNSEEN';
1013  if ($rule['type'] == 'unanswered') $search .= ($search ? ' ' : '').'UNANSWERED';
1014  if ($rule['type'] == 'answered') $search .= ($search ? ' ' : '').'ANSWERED';
1015  if ($rule['type'] == 'smaller') $search .= ($search ? ' ' : '').'SMALLER "'.str_replace('"', '', $rule['rulevalue']).'"';
1016  if ($rule['type'] == 'larger') $search .= ($search ? ' ' : '').'LARGER "'.str_replace('"', '', $rule['rulevalue']).'"';
1017 
1018  if ($rule['type'] == 'withtrackingidinmsgid') { $searchfilterdoltrackid++; $searchhead .= '/Message-ID.*@'.preg_quote($host, '/').'/'; }
1019  if ($rule['type'] == 'withouttrackingidinmsgid') { $searchfilterdoltrackid++; $searchhead .= '/Message-ID.*@'.preg_quote($host, '/').'/'; }
1020  if ($rule['type'] == 'withtrackingid') { $searchfilterdoltrackid++; $searchhead .= '/References.*@'.preg_quote($host, '/').'/'; }
1021  if ($rule['type'] == 'withouttrackingid') { $searchfilternodoltrackid++; $searchhead .= '! /References.*@'.preg_quote($host, '/').'/'; }
1022 
1023  if ($rule['type'] == 'isanswer') { $searchfilterisanswer++; $searchhead .= '/References.*@.*/'; }
1024  if ($rule['type'] == 'isnotanswer') { $searchfilterisnotanswer++; $searchhead .= '! /References.*@.*/'; }
1025  }
1026 
1027  if (empty($targetdir)) // Use last date as filter if there is no targetdir defined.
1028  {
1029  $fromdate = 0;
1030  if ($this->datelastok) $fromdate = $this->datelastok;
1031  if ($fromdate > 0) $search .= ($search ? ' ' : '').'SINCE '.date('j-M-Y', $fromdate - 1); // SENTSINCE not supported. Date must be X-Abc-9999 (X on 1 digit if < 10)
1032  //$search.=($search?' ':'').'SINCE 8-Apr-2018';
1033  }
1034  dol_syslog("IMAP search string = ".$search);
1035  //var_dump($search);
1036 
1037  $nbemailprocessed = 0;
1038  $nbemailok = 0;
1039  $nbactiondone = 0;
1040  $charset = ($this->hostcharset ? $this->hostcharset : "UTF-8");
1041 
1042  // Scan IMAP inbox
1043  $arrayofemail = imap_search($connection, $search, null, $charset);
1044  if ($arrayofemail === false)
1045  {
1046  // Nothing found or search string not understood
1047  $mapoferrrors = imap_errors();
1048  if ($mapoferrrors !== false)
1049  {
1050  $error++;
1051  $this->error = "Search string not understood - ".join(',', $mapoferrrors);
1052  $this->errors[] = $this->error;
1053  }
1054  }
1055 
1056  // Loop on each email found
1057  if (!$error && !empty($arrayofemail) && count($arrayofemail) > 0)
1058  {
1059  // Loop to get part html and plain
1060  /*
1061  0 multipart/mixed
1062  1 multipart/alternative
1063  1.1 text/plain
1064  1.2 text/html
1065  2 message/rfc822
1066  2 multipart/mixed
1067  2.1 multipart/alternative
1068  2.1.1 text/plain
1069  2.1.2 text/html
1070  2.2 message/rfc822
1071  2.2 multipart/alternative
1072  2.2.1 text/plain
1073  2.2.2 text/html
1074  */
1082  /*function createPartArray($structure, $prefix = "")
1083  {
1084  //print_r($structure);
1085  $part_array=array();
1086  if (count($structure->parts) > 0) { // There some sub parts
1087  foreach ($structure->parts as $count => $part) {
1088  addPartToArray($part, $prefix.($count+1), $part_array);
1089  }
1090  }else{ // Email does not have a seperate mime attachment for text
1091  $part_array[] = array('part_number' => $prefix.'1', 'part_object' => $structure);
1092  }
1093  return $part_array;
1094  }*/
1095 
1104  /*function addPartToArray($obj, $partno, &$part_array)
1105  {
1106  $part_array[] = array('part_number' => $partno, 'part_object' => $obj);
1107  if ($obj->type == 2) { // Check to see if the part is an attached email message, as in the RFC-822 type
1108  //print_r($obj);
1109  if (array_key_exists('parts', $obj)) { // Check to see if the email has parts
1110  foreach ($obj->parts as $count => $part) {
1111  // Iterate here again to compensate for the broken way that imap_fetchbody() handles attachments
1112  if (count($part->parts) > 0) {
1113  foreach ($part->parts as $count2 => $part2) {
1114  addPartToArray($part2, $partno.".".($count2+1), $part_array);
1115  }
1116  }else{ // Attached email does not have a seperate mime attachment for text
1117  $part_array[] = array('part_number' => $partno.'.'.($count+1), 'part_object' => $obj);
1118  }
1119  }
1120  }else{ // Not sure if this is possible
1121  $part_array[] = array('part_number' => $partno.'.1', 'part_object' => $obj);
1122  }
1123  }else{ // If there are more sub-parts, expand them out.
1124  if (array_key_exists('parts', $obj)) {
1125  foreach ($obj->parts as $count => $p) {
1126  addPartToArray($p, $partno.".".($count+1), $part_array);
1127  }
1128  }
1129  }
1130  }*/
1131 
1132  dol_syslog("Start of loop on email", LOG_INFO, 1);
1133 
1134  $iforemailloop = 0;
1135  foreach ($arrayofemail as $imapemail)
1136  {
1137  if ($nbemailprocessed > 1000)
1138  {
1139  break; // Do not process more than 1000 email per launch (this is a different protection than maxnbcollectedpercollect
1140  }
1141 
1142  $iforemailloop++;
1143 
1144  $header = imap_fetchheader($connection, $imapemail, 0);
1145  $header = preg_replace('/\r\n\s+/m', ' ', $header); // When a header line is on several lines, merge lines
1146  /*print $header;
1147  print $header;*/
1148 
1149  $matches = array();
1150  preg_match_all('/([^: ]+): (.+?(?:\r\n\s(?:.+?))*)\r\n/m', $header, $matches);
1151  $headers = array_combine($matches[1], $matches[2]);
1152 
1153  if (!empty($headers['in-reply-to']) && empty($headers['In-Reply-To'])) { $headers['In-Reply-To'] = $headers['in-reply-to']; }
1154  if (!empty($headers['references']) && empty($headers['References'])) { $headers['References'] = $headers['references']; }
1155  if (!empty($headers['message-id']) && empty($headers['Message-ID'])) { $headers['Message-ID'] = $headers['message-id']; }
1156 
1157  $headers['Subject'] = $this->decodeSMTPSubject($headers['Subject']);
1158 
1159 
1160  dol_syslog("** Process email ".$iforemailloop." References: ".$headers['References']);
1161  //print "Process mail ".$iforemailloop." Subject: ".dol_escape_htmltag($headers['Subject'])." References: ".dol_escape_htmltag($headers['References'])." In-Reply-To: ".dol_escape_htmltag($headers['In-Reply-To'])."<br>\n";
1162 
1163  // If there is a filter on trackid
1164  if ($searchfilterdoltrackid > 0)
1165  {
1166  if (empty($headers['References']) || !preg_match('/@'.preg_quote($host, '/').'/', $headers['References']))
1167  {
1168  $nbemailprocessed++;
1169  continue; // Exclude email
1170  }
1171  }
1172  if ($searchfilternodoltrackid > 0)
1173  {
1174  if (!empty($headers['References']) && preg_match('/@'.preg_quote($host, '/').'/', $headers['References']))
1175  {
1176  $nbemailprocessed++;
1177  continue; // Exclude email
1178  }
1179  }
1180 
1181  if ($searchfilterisanswer > 0) {
1182  if (empty($headers['In-Reply-To']))
1183  {
1184  $nbemailprocessed++;
1185  continue; // Exclude email
1186  }
1187  // Note: we can have
1188  // Message-ID=A, In-Reply-To=B, References=B and message can BE an answer or NOT (a transfer rewriten)
1189  $isanswer = 0;
1190  if (preg_match('/Re\s*:\s+/i', $headers['Subject'])) $isanswer = 1;
1191  //if ($headers['In-Reply-To'] != $headers['Message-ID'] && empty($headers['References'])) $isanswer = 1; // If in-reply-to differs of message-id, this is a reply
1192  //if ($headers['In-Reply-To'] != $headers['Message-ID'] && !empty($headers['References']) && strpos($headers['References'], $headers['Message-ID']) !== false) $isanswer = 1;
1193 
1194  if (!$isanswer) {
1195  $nbemailprocessed++;
1196  continue; // Exclude email
1197  }
1198  }
1199  if ($searchfilterisnotanswer > 0) {
1200  if (!empty($headers['In-Reply-To']))
1201  {
1202  // Note: we can have
1203  // Message-ID=A, In-Reply-To=B, References=B and message can BE an answer or NOT (a transfer rewriten)
1204  $isanswer = 0;
1205  if (preg_match('/Re\s*:\s+/i', $headers['Subject'])) $isanswer = 1;
1206  //if ($headers['In-Reply-To'] != $headers['Message-ID'] && empty($headers['References'])) $isanswer = 1; // If in-reply-to differs of message-id, this is a reply
1207  //if ($headers['In-Reply-To'] != $headers['Message-ID'] && !empty($headers['References']) && strpos($headers['References'], $headers['Message-ID']) !== false) $isanswer = 1;
1208  if ($isanswer) {
1209  $nbemailprocessed++;
1210  continue; // Exclude email
1211  }
1212  }
1213  }
1214 
1215  //print "Process mail ".$iforemailloop." Subject: ".dol_escape_htmltag($headers['Subject'])." selected<br>\n";
1216 
1217  $thirdpartystatic = new Societe($this->db);
1218  $contactstatic = new Contact($this->db);
1219  $projectstatic = new Project($this->db);
1220 
1221  $nbactiondoneforemail = 0;
1222  $errorforemail = 0;
1223  $errorforactions = 0;
1224  $thirdpartyfoundby = '';
1225  $contactfoundby = '';
1226  $projectfoundby = '';
1227  $ticketfoundby = '';
1228  $candidaturefoundby = '';
1229 
1230  $this->db->begin();
1231 
1232 
1233  // GET Email meta datas
1234  $overview = imap_fetch_overview($connection, $imapemail, 0);
1235 
1236  dol_syslog("msgid=".$overview[0]->message_id." date=".dol_print_date($overview[0]->udate, 'dayrfc', 'gmt')." from=".$overview[0]->from." to=".$overview[0]->to." subject=".$overview[0]->subject);
1237 
1238  $overview[0]->subject = $this->decodeSMTPSubject($overview[0]->subject);
1239 
1240  $overview[0]->from = $this->decodeSMTPSubject($overview[0]->from);
1241 
1242  // Removed emojis
1243  $overview[0]->subject = preg_replace('/[\x{10000}-\x{10FFFF}]/u', "\xEF\xBF\xBD", $overview[0]->subject);
1244 
1245  // Parse IMAP email structure
1246  global $htmlmsg, $plainmsg, $charset, $attachments;
1247  $this->getmsg($connection, $imapemail);
1248 
1249  //$htmlmsg,$plainmsg,$charset,$attachments
1250  $messagetext = $plainmsg ? $plainmsg : dol_string_nohtmltag($htmlmsg, 0);
1251  // Removed emojis
1252  $messagetext = preg_replace('/[\x{10000}-\x{10FFFF}]/u', "\xEF\xBF\xBD", $messagetext);
1253 
1254  /*var_dump($plainmsg);
1255  var_dump($htmlmsg);
1256  var_dump($messagetext);*/
1257  /*var_dump($charset);
1258  var_dump($attachments);
1259  exit;*/
1260 
1261  // Parse IMAP email structure
1262  /*
1263  $structure = imap_fetchstructure($connection, $imapemail, 0);
1264 
1265  $partplain = $parthtml = -1;
1266  $encodingplain = $encodinghtml = '';
1267 
1268  $result = createPartArray($structure, '');
1269 
1270  foreach($result as $part)
1271  {
1272  // $part['part_object']->type seems 0 for content
1273  // $part['part_object']->type seems 5 for attachment
1274  if (empty($part['part_object'])) continue;
1275  if ($part['part_object']->subtype == 'HTML')
1276  {
1277  $parthtml=$part['part_number'];
1278  if ($part['part_object']->encoding == 4)
1279  {
1280  $encodinghtml = 'aaa';
1281  }
1282  }
1283  if ($part['part_object']->subtype == 'PLAIN')
1284  {
1285  $partplain=$part['part_number'];
1286  if ($part['part_object']->encoding == 4)
1287  {
1288  $encodingplain = 'rr';
1289  }
1290  }
1291  }
1292  //var_dump($result); var_dump($partplain); var_dump($parthtml);
1293 
1294  var_dump($structure);
1295  var_dump($parthtml);
1296  var_dump($partplain);
1297 
1298  $messagetext = imap_fetchbody($connection, $imapemail, ($parthtml != '-1' ? $parthtml : ($partplain != '-1' ? $partplain : 1)), FT_PEEK);
1299  */
1300 
1301  //var_dump($messagetext);
1302  //var_dump($structure->parts[0]->parts);
1303  //print $header;
1304  //print $messagetext;
1305  //exit;
1306 
1307  $fromstring = $overview[0]->from;
1308 
1309  $sender = $overview[0]->sender;
1310  $to = $overview[0]->to;
1311  $sendtocc = $overview[0]->cc;
1312  $sendtobcc = $overview[0]->bcc;
1313  $date = $overview[0]->udate;
1314  $msgid = str_replace(array('<', '>'), '', $overview[0]->message_id);
1315  $subject = $overview[0]->subject;
1316  //var_dump($msgid);exit;
1317 
1318  $reg = array();
1319  if (preg_match('/^(.*)<(.*)>$/', $fromstring, $reg))
1320  {
1321  $from = $reg[2];
1322  $fromtext = $reg[1];
1323  } else {
1324  $from = $fromstring;
1325  $fromtext = '';
1326  }
1327  $fk_element_id = 0; $fk_element_type = '';
1328 
1329 
1330  $contactid = 0; $thirdpartyid = 0; $projectid = 0; $ticketid = 0;
1331 
1332  // Analyze TrackId in field References. For example:
1333  // References: <1542377954.SMTPs-dolibarr-thi649@8f6014fde11ec6cdec9a822234fc557e>
1334  // References: <1542377954.SMTPs-dolibarr-tic649@8f6014fde11ec6cdec9a822234fc557e>
1335  // References: <1542377954.SMTPs-dolibarr-abc649@8f6014fde11ec6cdec9a822234fc557e>
1336  $trackid = '';
1337  $objectid = 0;
1338  $objectemail = null;
1339 
1340  $reg = array();
1341  if (!empty($headers['References']))
1342  {
1343  $arrayofreferences = preg_split('/(,|\s+)/', $headers['References']);
1344  //var_dump($headers['References']);
1345  //var_dump($arrayofreferences);
1346 
1347  foreach ($arrayofreferences as $reference) {
1348  //print "Process mail ".$iforemailloop." email_msgid ".$msgid.", date ".dol_print_date($date, 'dayhour').", subject ".$subject.", reference ".dol_escape_htmltag($reference)."<br>\n";
1349  if (preg_match('/dolibarr-([a-z]+)([0-9]+)@'.preg_quote($host, '/').'/', $reference, $reg)) {
1350  // This is a Dolibarr reference
1351  $trackid = $reg[1].$reg[2];
1352 
1353  $objectid = $reg[2];
1354  // See also list into interface_50_modAgenda_ActionsAuto
1355  if ($reg[1] == 'thi')
1356  {
1357  $objectemail = new Societe($this->db);
1358  }
1359  if ($reg[1] == 'ctc')
1360  {
1361  $objectemail = new Contact($this->db);
1362  }
1363  if ($reg[1] == 'inv')
1364  {
1365  $objectemail = new Facture($this->db);
1366  }
1367  if ($reg[1] == 'proj')
1368  {
1369  $objectemail = new Project($this->db);
1370  }
1371  if ($reg[1] == 'tas')
1372  {
1373  $objectemail = new Task($this->db);
1374  }
1375  if ($reg[1] == 'con')
1376  {
1377  $objectemail = new Contact($this->db);
1378  }
1379  if ($reg[1] == 'use')
1380  {
1381  $objectemail = new User($this->db);
1382  }
1383  if ($reg[1] == 'tic')
1384  {
1385  $objectemail = new Ticket($this->db);
1386  }
1387  if ($reg[1] == 'recruitmentcandidature')
1388  {
1389  $objectemail = new RecruitmentCandidature($this->db);
1390  }
1391  if ($reg[1] == 'mem')
1392  {
1393  $objectemail = new Adherent($this->db);
1394  }
1395  } elseif (preg_match('/<(.*@.*)>/', $reference, $reg)) {
1396  // This is an external reference, we check if we have it in our database
1397  if (!is_object($objectemail)) {
1398  $sql = "SELECT rowid FROM ".MAIN_DB_PREFIX."ticket where email_msgid = '".$this->db->escape($reg[1])."'";
1399  $resql = $this->db->query($sql);
1400  if ($resql) {
1401  $obj = $this->db->fetch_object($resql);
1402  if ($obj) {
1403  $objectid = $obj->rowid;
1404  $objectemail = new Ticket($this->db);
1405  $ticketfoundby = $langs->transnoentitiesnoconv("EmailMsgID").' ('.$reg[1].')';
1406  }
1407  } else {
1408  $errorforemail++;
1409  }
1410  }
1411 
1412  if (!is_object($objectemail)) {
1413  $sql = "SELECT rowid FROM ".MAIN_DB_PREFIX."projet where email_msgid = '".$this->db->escape($reg[1])."'";
1414  $resql = $this->db->query($sql);
1415  if ($resql) {
1416  $obj = $this->db->fetch_object($resql);
1417  if ($obj) {
1418  $objectid = $obj->rowid;
1419  $objectemail = new Project($this->db);
1420  $projectfoundby = $langs->transnoentitiesnoconv("EmailMsgID").' ('.$reg[1].')';
1421  }
1422  } else {
1423  $errorforemail++;
1424  }
1425  }
1426 
1427  if (!is_object($objectemail)) {
1428  $sql = "SELECT rowid FROM ".MAIN_DB_PREFIX."recruitment_recruitmentcandidature where email_msgid = '".$this->db->escape($reg[1])."'";
1429  $resql = $this->db->query($sql);
1430  if ($resql) {
1431  $obj = $this->db->fetch_object($resql);
1432  if ($obj) {
1433  $objectid = $obj->rowid;
1434  $objectemail = new RecruitmentCandidature($this->db);
1435  $candidaturefoundby = $langs->transnoentitiesnoconv("EmailMsgID").' ('.$reg[1].')';
1436  }
1437  } else {
1438  $errorforemail++;
1439  }
1440  }
1441  }
1442 
1443  // Load object linked to email
1444  if (is_object($objectemail))
1445  {
1446  $result = $objectemail->fetch($objectid);
1447  if ($result > 0)
1448  {
1449  $fk_element_id = $objectemail->id;
1450  $fk_element_type = $objectemail->element;
1451  // Fix fk_element_type
1452  if ($fk_element_type == 'facture') $fk_element_type = 'invoice';
1453 
1454  if (get_class($objectemail) != 'Societe') $thirdpartyid = $objectemail->fk_soc;
1455  else $thirdpartyid = $objectemail->id;
1456 
1457  if (get_class($objectemail) != 'Contact') $contactid = $objectemail->fk_socpeople;
1458  else $contactid = $objectemail->id;
1459 
1460  if (get_class($objectemail) != 'Project') $projectid = isset($objectemail->fk_project) ? $objectemail->fk_project : $objectemail->fk_projet;
1461  else $projectid = $objectemail->id;
1462  }
1463  }
1464 
1465  // Project
1466  if ($projectid > 0)
1467  {
1468  $result = $projectstatic->fetch($projectid);
1469  if ($result <= 0) $projectstatic->id = 0;
1470  else {
1471  $projectid = $projectstatic->id;
1472  if ($trackid) $projectfoundby = 'trackid ('.$trackid.')';
1473  if (empty($contactid)) $contactid = $projectstatic->fk_contact;
1474  if (empty($thirdpartyid)) $thirdpartyid = $projectstatic->fk_soc;
1475  }
1476  }
1477  // Contact
1478  if ($contactid > 0)
1479  {
1480  $result = $contactstatic->fetch($contactid);
1481  if ($result <= 0) $contactstatic->id = 0;
1482  else {
1483  $contactid = $contactstatic->id;
1484  if ($trackid) $contactfoundby = 'trackid ('.$trackid.')';
1485  if (empty($thirdpartyid)) $thirdpartyid = $contactstatic->fk_soc;
1486  }
1487  }
1488  // Thirdparty
1489  if ($thirdpartyid > 0)
1490  {
1491  $result = $thirdpartystatic->fetch($thirdpartyid);
1492  if ($result <= 0) $thirdpartystatic->id = 0;
1493  else {
1494  $thirdpartyid = $thirdpartystatic->id;
1495  if ($trackid) $thirdpartyfoundby = 'trackid ('.$trackid.')';
1496  }
1497  }
1498 
1499  if (is_object($objectemail))
1500  {
1501  break; // Exit loop of references. We already found an accurate reference
1502  }
1503  }
1504  }
1505 
1506  if (empty($contactid)) // Try to find contact using email
1507  {
1508  $result = $contactstatic->fetch(0, null, '', $from);
1509 
1510  if ($result > 0)
1511  {
1512  $contactid = $contactstatic->id;
1513  $contactfoundby = 'email of contact ('.$from.')';
1514  if (empty($thirdpartyid) && $contactstatic->socid > 0)
1515  {
1516  $result = $thirdpartystatic->fetch($contactstatic->socid);
1517  if ($result > 0)
1518  {
1519  $thirdpartyid = $thirdpartystatic->id;
1520  $thirdpartyfoundby = 'email of contact ('.$from.')';
1521  }
1522  }
1523  }
1524  }
1525 
1526  if (empty($thirdpartyid)) // Try to find thirdparty using email
1527  {
1528  $result = $thirdpartystatic->fetch(0, '', '', '', '', '', '', '', '', '', $from);
1529  if ($result > 0) $thirdpartyfoundby = 'email ('.$from.')';
1530  }
1531 
1532  // Do operations
1533  foreach ($this->actions as $operation)
1534  {
1535  $errorforthisaction = 0;
1536 
1537  if ($errorforactions) break;
1538  if (empty($operation['status'])) continue;
1539 
1540  // Make Operation
1541  dol_syslog("Execute action ".$operation['type']." actionparam=".$operation['actionparam'].' thirdpartystatic->id='.$thirdpartystatic->id.' contactstatic->id='.$contactstatic->id.' projectstatic->id='.$projectstatic->id);
1542  dol_syslog("Execute action fk_element_id=".$fk_element_id." fk_element_type=".$fk_element_type);
1543 
1544  $actioncode = 'EMAIL_IN';
1545  // If we scan the Sent box, we use the code for out email
1546  if ($this->source_directory == 'Sent') $actioncode = 'EMAIL_OUT';
1547 
1548  $description = $descriptiontitle = $descriptionmeta = $descriptionfull = '';
1549 
1550  $descriptiontitle = $langs->trans("RecordCreatedByEmailCollector", $this->ref, $msgid);
1551 
1552  $descriptionmeta = dol_concatdesc($descriptionmeta, $langs->trans("MailTopic").' : '.dol_escape_htmltag($subject));
1553  $descriptionmeta = dol_concatdesc($descriptionmeta, $langs->trans("MailFrom").($langs->trans("MailFrom") != 'From' ? ' (From)' : '').' : '.dol_escape_htmltag($fromstring));
1554  if ($sender) $descriptionmeta = dol_concatdesc($descriptionmeta, $langs->trans("Sender").($langs->trans("Sender") != 'Sender' ? ' (Sender)' : '').' : '.dol_escape_htmltag($sender));
1555  $descriptionmeta = dol_concatdesc($descriptionmeta, $langs->trans("MailTo").($langs->trans("MailTo") != 'To' ? ' (To)' : '').' : '.dol_escape_htmltag($to));
1556  if ($sendtocc) $descriptionmeta = dol_concatdesc($descriptionmeta, $langs->trans("MailCC").($langs->trans("MailCC") != 'CC' ? ' (CC)' : '').' : '.dol_escape_htmltag($sendtocc));
1557 
1558  // Search and create thirdparty
1559  if ($operation['type'] == 'loadthirdparty' || $operation['type'] == 'loadandcreatethirdparty')
1560  {
1561  if (empty($operation['actionparam'])) {
1562  $errorforactions++;
1563  $this->error = "Action loadthirdparty or loadandcreatethirdparty has empty parameter. Must be a rule like 'SET:xxx' or 'EXTRACT:(body|subject):regex' to define how to set or extract data";
1564  $this->errors[] = $this->error;
1565  } else {
1566  $actionparam = $operation['actionparam'];
1567  $nametouseforthirdparty = '';
1568 
1569  // $this->actionparam = 'SET:aaa' or 'EXTRACT:BODY:....'
1570  $arrayvaluetouse = dolExplodeIntoArray($actionparam, ';', '=');
1571  foreach ($arrayvaluetouse as $propertytooverwrite => $valueforproperty)
1572  {
1573  $sourcestring = '';
1574  $sourcefield = '';
1575  $regexstring = '';
1576  $regforregex = array();
1577 
1578  if (preg_match('/^EXTRACT:([a-zA-Z0-9]+):(.*)$/', $valueforproperty, $regforregex))
1579  {
1580  $sourcefield = $regforregex[1];
1581  $regexstring = $regforregex[2];
1582  }
1583 
1584  if (!empty($sourcefield) && !empty($regexstring))
1585  {
1586  if (strtolower($sourcefield) == 'body') $sourcestring = $messagetext;
1587  elseif (strtolower($sourcefield) == 'subject') $sourcestring = $subject;
1588  elseif (strtolower($sourcefield) == 'header') $sourcestring = $header;
1589 
1590  if ($sourcestring)
1591  {
1592  $regforval = array();
1593  //var_dump($regexstring);var_dump($sourcestring);
1594  if (preg_match('/'.$regexstring.'/ms', $sourcestring, $regforval))
1595  {
1596  //var_dump($regforval[count($regforval)-1]);exit;
1597  // Overwrite param $tmpproperty
1598  $nametouseforthirdparty = isset($regforval[count($regforval) - 1]) ? trim($regforval[count($regforval) - 1]) : null;
1599  } else {
1600  // Regex not found
1601  $nametouseforthirdparty = null;
1602  }
1603  //var_dump($object->$tmpproperty);exit;
1604  } else {
1605  // Nothing can be done for this param
1606  $errorforactions++;
1607  $this->error = 'The extract rule to use to load thirdparty has on an unknown source (must be HEADER, SUBJECT or BODY)';
1608  $this->errors[] = $this->error;
1609  }
1610  } elseif (preg_match('/^(SET|SETIFEMPTY):(.*)$/', $valueforproperty, $reg))
1611  {
1612  //if (preg_match('/^options_/', $tmpproperty)) $object->array_options[preg_replace('/^options_/', '', $tmpproperty)] = $reg[1];
1613  //else $object->$tmpproperty = $reg[1];
1614  $nametouseforthirdparty = $reg[2];
1615  } else {
1616  $errorforactions++;
1617  $this->error = 'Bad syntax for description of action parameters: '.$actionparam;
1618  $this->errors[] = $this->error;
1619  break;
1620  }
1621  }
1622 
1623  if (!$errorforactions && $nametouseforthirdparty)
1624  {
1625  $result = $thirdpartystatic->fetch(0, $nametouseforthirdparty);
1626  if ($result < 0)
1627  {
1628  $errorforactions++;
1629  $this->error = 'Error when getting thirdparty with name '.$nametouseforthirdparty.' (may be 2 record exists with same name ?)';
1630  $this->errors[] = $this->error;
1631  break;
1632  } elseif ($result == 0)
1633  {
1634  if ($operation['type'] == 'loadthirdparty')
1635  {
1636  dol_syslog("Third party with name ".$nametouseforthirdparty." was not found");
1637 
1638  $errorforactions++;
1639  $this->error = 'ErrorFailedToLoadThirdParty';
1640  $this->errors[] = 'ErrorFailedToLoadThirdParty';
1641  } elseif ($operation['type'] == 'loadandcreatethirdparty')
1642  {
1643  dol_syslog("Third party with name ".$nametouseforthirdparty." was not found. We try to create it.");
1644 
1645  // Create thirdparty
1646  $thirdpartystatic->name = $nametouseforthirdparty;
1647  if ($fromtext != $nametouseforthirdparty) $thirdpartystatic->name_alias = $fromtext;
1648  $thirdpartystatic->email = $from;
1649 
1650  // Overwrite values with values extracted from source email
1651  $errorforthisaction = $this->overwritePropertiesOfObject($thirdpartystatic, $operation['actionparam'], $messagetext, $subject, $header);
1652 
1653  if ($errorforthisaction)
1654  {
1655  $errorforactions++;
1656  } else {
1657  $result = $thirdpartystatic->create($user);
1658  if ($result <= 0)
1659  {
1660  $errorforactions++;
1661  $this->error = $thirdpartystatic->error;
1662  $this->errors = $thirdpartystatic->errors;
1663  }
1664  }
1665  }
1666  }
1667  }
1668  }
1669  }
1670  // Create event
1671  elseif ($operation['type'] == 'recordevent')
1672  {
1673  $actioncomm = new ActionComm($this->db);
1674 
1675  $alreadycreated = $actioncomm->fetch(0, '', '', $msgid);
1676  if ($alreadycreated == 0)
1677  {
1678  if ($projectstatic->id > 0)
1679  {
1680  if ($projectfoundby) $descriptionmeta = dol_concatdesc($descriptionmeta, 'Project found from '.$projectfoundby);
1681  }
1682  if ($thirdpartystatic->id > 0)
1683  {
1684  if ($thirdpartyfoundby) $descriptionmeta = dol_concatdesc($descriptionmeta, 'Third party found from '.$thirdpartyfoundby);
1685  }
1686  if ($contactstatic->id > 0)
1687  {
1688  if ($contactfoundby) $descriptionmeta = dol_concatdesc($descriptionmeta, 'Contact/address found from '.$contactfoundby);
1689  }
1690 
1691  $description = $descriptiontitle;
1692  $description = dol_concatdesc($description, "-----");
1693  $description = dol_concatdesc($description, $descriptionmeta);
1694  $description = dol_concatdesc($description, "-----");
1695  $description = dol_concatdesc($description, $messagetext);
1696 
1697  $descriptionfull = $description;
1698  if (empty($conf->global->MAIN_EMAILCOLLECTOR_MAIL_WITHOUT_HEADER)) {
1699  $descriptionfull = dol_concatdesc($descriptionfull, "----- Header");
1700  $descriptionfull = dol_concatdesc($descriptionfull, $header);
1701  }
1702 
1703  // Insert record of emails sent
1704  $actioncomm->type_code = 'AC_OTH_AUTO'; // Type of event ('AC_OTH', 'AC_OTH_AUTO', 'AC_XXX'...)
1705  $actioncomm->code = 'AC_'.$actioncode;
1706  $actioncomm->label = $langs->trans("ActionAC_".$actioncode).' - '.$langs->trans("MailFrom").' '.$from;
1707  $actioncomm->note_private = $descriptionfull;
1708  $actioncomm->fk_project = $projectstatic->id;
1709  $actioncomm->datep = $date;
1710  $actioncomm->datef = $date;
1711  $actioncomm->percentage = -1; // Not applicable
1712  $actioncomm->socid = $thirdpartystatic->id;
1713  $actioncomm->contact_id = $contactstatic->id;
1714  $actioncomm->socpeopleassigned = (!empty($contactstatic->id) ? array($contactstatic->id => '') : array());
1715  $actioncomm->authorid = $user->id; // User saving action
1716  $actioncomm->userownerid = $user->id; // Owner of action
1717  // Fields when action is an email (content should be added into note)
1718  $actioncomm->email_msgid = $msgid;
1719  $actioncomm->email_from = $fromstring;
1720  $actioncomm->email_sender = $sender;
1721  $actioncomm->email_to = $to;
1722  $actioncomm->email_tocc = $sendtocc;
1723  $actioncomm->email_tobcc = $sendtobcc;
1724  $actioncomm->email_subject = $subject;
1725  $actioncomm->errors_to = '';
1726 
1727  if (!in_array($fk_element_type, array('societe', 'contact', 'project', 'user')))
1728  {
1729  $actioncomm->fk_element = $fk_element_id;
1730  $actioncomm->elementid = $fk_element_id;
1731  $actioncomm->elementtype = $fk_element_type;
1732  if (is_object($objectemail) && $objectemail->module) {
1733  $actioncomm->elementtype .= '@'.$objectemail->module;
1734  }
1735  }
1736 
1737  //$actioncomm->extraparams = $extraparams;
1738 
1739  // Overwrite values with values extracted from source email
1740  $errorforthisaction = $this->overwritePropertiesOfObject($actioncomm, $operation['actionparam'], $messagetext, $subject, $header);
1741 
1742  /*var_dump($fk_element_id);
1743  var_dump($fk_element_type);
1744  var_dump($alreadycreated);
1745  var_dump($operation['type']);
1746  var_dump($actioncomm);
1747  exit;*/
1748 
1749  if ($errorforthisaction)
1750  {
1751  $errorforactions++;
1752  } else {
1753  $result = $actioncomm->create($user);
1754  if ($result <= 0)
1755  {
1756  $errorforactions++;
1757  $this->errors = $actioncomm->errors;
1758  }
1759  }
1760  }
1761  }
1762  // Create project / lead
1763  elseif ($operation['type'] == 'project')
1764  {
1765  $projecttocreate = new Project($this->db);
1766 
1767  $alreadycreated = $projecttocreate->fetch(0, '', '', $msgid);
1768  if ($alreadycreated == 0)
1769  {
1770  if ($thirdpartystatic->id > 0)
1771  {
1772  $projecttocreate->socid = $thirdpartystatic->id;
1773  if ($thirdpartyfoundby) $descriptionmeta = dol_concatdesc($descriptionmeta, 'Third party found from '.$thirdpartyfoundby);
1774  }
1775  if ($contactstatic->id > 0)
1776  {
1777  $projecttocreate->contact_id = $contactstatic->id;
1778  if ($contactfoundby) $descriptionmeta = dol_concatdesc($descriptionmeta, 'Contact/address found from '.$contactfoundby);
1779  }
1780 
1781  $description = $descriptiontitle;
1782  $description = dol_concatdesc($description, "-----");
1783  $description = dol_concatdesc($description, $descriptionmeta);
1784  $description = dol_concatdesc($description, "-----");
1785  $description = dol_concatdesc($description, $messagetext);
1786 
1787  $descriptionfull = $description;
1788  if (empty($conf->global->MAIN_EMAILCOLLECTOR_MAIL_WITHOUT_HEADER)) {
1789  $descriptionfull = dol_concatdesc($descriptionfull, "----- Header");
1790  $descriptionfull = dol_concatdesc($descriptionfull, $header);
1791  }
1792 
1793  $id_opp_status = dol_getIdFromCode($this->db, 'PROSP', 'c_lead_status', 'code', 'rowid');
1794  $percent_opp_status = dol_getIdFromCode($this->db, 'PROSP', 'c_lead_status', 'code', 'percent');
1795 
1796  $projecttocreate->title = $subject;
1797  $projecttocreate->date_start = $date;
1798  $projecttocreate->date_end = '';
1799  $projecttocreate->opp_status = $id_opp_status;
1800  $projecttocreate->opp_percent = $percent_opp_status;
1801  $projecttocreate->description = dol_concatdesc(dolGetFirstLineOfText(dol_string_nohtmltag($description, 2), 10), '...'.$langs->transnoentities("SeePrivateNote").'...');
1802  $projecttocreate->note_private = $descriptionfull;
1803  $projecttocreate->entity = $conf->entity;
1804  $projecttocreate->email_msgid = $msgid;
1805 
1806  $savesocid = $projecttocreate->socid;
1807 
1808  // Overwrite values with values extracted from source email.
1809  // This may overwrite any $projecttocreate->xxx properties.
1810  $errorforthisaction = $this->overwritePropertiesOfObject($projecttocreate, $operation['actionparam'], $messagetext, $subject, $header);
1811 
1812  // Set project ref if not yet defined
1813  if (empty($projecttocreate->ref))
1814  {
1815  // Get next Ref
1816  $defaultref = '';
1817  $modele = empty($conf->global->PROJECT_ADDON) ? 'mod_project_simple' : $conf->global->PROJECT_ADDON;
1818 
1819  // Search template files
1820  $file = ''; $classname = ''; $filefound = 0; $reldir = '';
1821  $dirmodels = array_merge(array('/'), (array) $conf->modules_parts['models']);
1822  foreach ($dirmodels as $reldir)
1823  {
1824  $file = dol_buildpath($reldir."core/modules/project/".$modele.'.php', 0);
1825  if (file_exists($file))
1826  {
1827  $filefound = 1;
1828  $classname = $modele;
1829  break;
1830  }
1831  }
1832 
1833  if ($filefound)
1834  {
1835  if ($savesocid > 0)
1836  {
1837  if ($savesocid != $projecttocreate->socid)
1838  {
1839  $errorforactions++;
1840  setEventMessages('You loaded a thirdparty (id='.$savesocid.') and you force another thirdparty id (id='.$projecttocreate->socid.') by setting socid in operation with a different value', null, 'errors');
1841  }
1842  } else {
1843  if ($projecttocreate->socid > 0)
1844  {
1845  $thirdpartystatic->fetch($projecttocreate->socid);
1846  }
1847  }
1848 
1849  $result = dol_include_once($reldir."core/modules/project/".$modele.'.php');
1850  $modModuleToUseForNextValue = new $classname;
1851  $defaultref = $modModuleToUseForNextValue->getNextValue(($thirdpartystatic->id > 0 ? $thirdpartystatic : null), $projecttocreate);
1852  }
1853  $projecttocreate->ref = $defaultref;
1854  }
1855 
1856  if ($errorforthisaction)
1857  {
1858  $errorforactions++;
1859  } else {
1860  if (empty($projecttocreate->ref) || (is_numeric($projecttocreate->ref) && $projecttocreate->ref <= 0))
1861  {
1862  $errorforactions++;
1863  $this->error = 'Failed to create project: Can\'t get a valid value for the field ref with numbering template = '.$modele.', thirdparty id = '.$thirdpartystatic->id;
1864  } else {
1865  // Create project
1866  $result = $projecttocreate->create($user);
1867  if ($result <= 0)
1868  {
1869  $errorforactions++;
1870  $this->error = 'Failed to create project: '.$langs->trans($projecttocreate->error);
1871  $this->errors = $projecttocreate->errors;
1872  }
1873  }
1874  }
1875  }
1876  }
1877  // Create ticket
1878  elseif ($operation['type'] == 'ticket')
1879  {
1880  $tickettocreate = new Ticket($this->db);
1881 
1882  $alreadycreated = $tickettocreate->fetch(0, '', '', $msgid);
1883  if ($alreadycreated == 0)
1884  {
1885  if ($thirdpartystatic->id > 0)
1886  {
1887  $tickettocreate->socid = $thirdpartystatic->id;
1888  $tickettocreate->fk_soc = $thirdpartystatic->id;
1889  if ($thirdpartyfoundby) $descriptionmeta = dol_concatdesc($descriptionmeta, 'Third party found from '.$thirdpartyfoundby);
1890  }
1891  if ($contactstatic->id > 0)
1892  {
1893  $tickettocreate->contact_id = $contactstatic->id;
1894  if ($contactfoundby) $descriptionmeta = dol_concatdesc($descriptionmeta, 'Contact/address found from '.$contactfoundby);
1895  }
1896 
1897  $description = $descriptiontitle;
1898  $description = dol_concatdesc($description, "-----");
1899  $description = dol_concatdesc($description, $descriptionmeta);
1900  $description = dol_concatdesc($description, "-----");
1901  $description = dol_concatdesc($description, $messagetext);
1902 
1903  $descriptionfull = $description;
1904  if (empty($conf->global->MAIN_EMAILCOLLECTOR_MAIL_WITHOUT_HEADER)) {
1905  $descriptionfull = dol_concatdesc($descriptionfull, "----- Header");
1906  $descriptionfull = dol_concatdesc($descriptionfull, $header);
1907  }
1908 
1909  $tickettocreate->subject = $subject;
1910  $tickettocreate->message = $description;
1911  $tickettocreate->type_code = (!empty($conf->global->MAIN_EMAILCOLLECTOR_TICKET_TYPE_CODE) ? $conf->global->MAIN_EMAILCOLLECTOR_TICKET_TYPE_CODE : dol_getIdFromCode($this->db, 1, 'c_ticket_type', 'use_default', 'code', 1));
1912  $tickettocreate->category_code = (!empty($conf->global->MAIN_EMAILCOLLECTOR_TICKET_CATEGORY_CODE) ? $conf->global->MAIN_EMAILCOLLECTOR_TICKET_CATEGORY_CODE : dol_getIdFromCode($this->db, 1, 'c_ticket_category', 'use_default', 'code', 1));
1913  $tickettocreate->severity_code = (!empty($conf->global->MAIN_EMAILCOLLECTOR_TICKET_SEVERITY_CODE) ? $conf->global->MAIN_EMAILCOLLECTOR_TICKET_SEVERITY_CODE : dol_getIdFromCode($this->db, 1, 'c_ticket_severity', 'use_default', 'code', 1));
1914  $tickettocreate->origin_email = $from;
1915  $tickettocreate->fk_user_create = $user->id;
1916  $tickettocreate->datec = $date;
1917  $tickettocreate->fk_project = $projectstatic->id;
1918  $tickettocreate->notify_tiers_at_create = 0;
1919  $tickettocreate->note_private = $descriptionfull;
1920  $tickettocreate->entity = $conf->entity;
1921  $tickettocreate->email_msgid = $msgid;
1922  //$tickettocreate->fk_contact = $contactstatic->id;
1923 
1924  $savesocid = $tickettocreate->socid;
1925 
1926  // Overwrite values with values extracted from source email.
1927  // This may overwrite any $projecttocreate->xxx properties.
1928  $errorforthisaction = $this->overwritePropertiesOfObject($tickettocreate, $operation['actionparam'], $messagetext, $subject, $header);
1929 
1930  // Set ticket ref if not yet defined
1931  if (empty($tickettocreate->ref))
1932  {
1933  // Get next Ref
1934  $defaultref = '';
1935  $modele = empty($conf->global->TICKET_ADDON) ? 'mod_ticket_simple' : $conf->global->TICKET_ADDON;
1936 
1937  // Search template files
1938  $file = ''; $classname = ''; $filefound = 0; $reldir = '';
1939  $dirmodels = array_merge(array('/'), (array) $conf->modules_parts['models']);
1940  foreach ($dirmodels as $reldir)
1941  {
1942  $file = dol_buildpath($reldir."core/modules/ticket/".$modele.'.php', 0);
1943  if (file_exists($file))
1944  {
1945  $filefound = 1;
1946  $classname = $modele;
1947  break;
1948  }
1949  }
1950 
1951  if ($filefound)
1952  {
1953  if ($savesocid > 0)
1954  {
1955  if ($savesocid != $tickettocreate->socid)
1956  {
1957  $errorforactions++;
1958  setEventMessages('You loaded a thirdparty (id='.$savesocid.') and you force another thirdparty id (id='.$tickettocreate->socid.') by setting socid in operation with a different value', null, 'errors');
1959  }
1960  } else {
1961  if ($tickettocreate->socid > 0)
1962  {
1963  $thirdpartystatic->fetch($tickettocreate->socid);
1964  }
1965  }
1966 
1967  $result = dol_include_once($reldir."core/modules/ticket/".$modele.'.php');
1968  $modModuleToUseForNextValue = new $classname;
1969  $defaultref = $modModuleToUseForNextValue->getNextValue(($thirdpartystatic->id > 0 ? $thirdpartystatic : null), $tickettocreate);
1970  }
1971  $tickettocreate->ref = $defaultref;
1972  }
1973 
1974  if ($errorforthisaction)
1975  {
1976  $errorforactions++;
1977  } else {
1978  if (is_numeric($tickettocreate->ref) && $tickettocreate->ref <= 0)
1979  {
1980  $errorforactions++;
1981  $this->error = 'Failed to create ticket: Can\'t get a valid value for the field ref with numbering template = '.$modele.', thirdparty id = '.$thirdpartystatic->id;
1982  } else {
1983  // Create project
1984  $result = $tickettocreate->create($user);
1985  if ($result <= 0)
1986  {
1987  $errorforactions++;
1988  $this->error = 'Failed to create ticket: '.$langs->trans($tickettocreate->error);
1989  $this->errors = $tickettocreate->errors;
1990  }
1991  }
1992  }
1993  }
1994  }
1995  // Create candidature
1996  elseif ($operation['type'] == 'candidature')
1997  {
1998  $candidaturetocreate = new RecruitmentCandidature($this->db);
1999 
2000  $alreadycreated = $candidaturetocreate->fetch(0, '', $msgid);
2001  if ($alreadycreated == 0)
2002  {
2003  $description = $descriptiontitle;
2004  $description = dol_concatdesc($description, "-----");
2005  $description = dol_concatdesc($description, $descriptionmeta);
2006  $description = dol_concatdesc($description, "-----");
2007  $description = dol_concatdesc($description, $messagetext);
2008 
2009  $descriptionfull = $description;
2010  $descriptionfull = dol_concatdesc($descriptionfull, "----- Header");
2011  $descriptionfull = dol_concatdesc($descriptionfull, $header);
2012 
2013  $candidaturetocreate->subject = $subject;
2014  $candidaturetocreate->message = $description;
2015  $candidaturetocreate->type_code = 0;
2016  $candidaturetocreate->category_code = null;
2017  $candidaturetocreate->severity_code = null;
2018  $candidaturetocreate->email = $from;
2019  //$candidaturetocreate->lastname = $langs->trans("Anonymous").' - '.$from;
2020  $candidaturetocreate->fk_user_creat = $user->id;
2021  $candidaturetocreate->date_creation = $date;
2022  $candidaturetocreate->fk_project = $projectstatic->id;
2023  $candidaturetocreate->description = $description;
2024  $candidaturetocreate->note_private = $descriptionfull;
2025  $candidaturetocreate->entity = $conf->entity;
2026  $candidaturetocreate->email_msgid = $msgid;
2027  $candidaturetocreate->status = $candidaturetocreate::STATUS_DRAFT;
2028  //$candidaturetocreate->fk_contact = $contactstatic->id;
2029 
2030  // Overwrite values with values extracted from source email.
2031  // This may overwrite any $projecttocreate->xxx properties.
2032  $errorforthisaction = $this->overwritePropertiesOfObject($candidaturetocreate, $operation['actionparam'], $messagetext, $subject, $header);
2033 
2034  // Set candidature ref if not yet defined
2035  /*if (empty($candidaturetocreate->ref)) We do not need this because we create object in draft status
2036  {
2037  // Get next Ref
2038  $defaultref = '';
2039  $modele = empty($conf->global->CANDIDATURE_ADDON) ? 'mod_candidature_simple' : $conf->global->CANDIDATURE_ADDON;
2040 
2041  // Search template files
2042  $file = ''; $classname = ''; $filefound = 0; $reldir = '';
2043  $dirmodels = array_merge(array('/'), (array) $conf->modules_parts['models']);
2044  foreach ($dirmodels as $reldir)
2045  {
2046  $file = dol_buildpath($reldir."core/modules/ticket/".$modele.'.php', 0);
2047  if (file_exists($file))
2048  {
2049  $filefound = 1;
2050  $classname = $modele;
2051  break;
2052  }
2053  }
2054 
2055  if ($filefound)
2056  {
2057  if ($savesocid > 0)
2058  {
2059  if ($savesocid != $candidaturetocreate->socid)
2060  {
2061  $errorforactions++;
2062  setEventMessages('You loaded a thirdparty (id='.$savesocid.') and you force another thirdparty id (id='.$candidaturetocreate->socid.') by setting socid in operation with a different value', null, 'errors');
2063  }
2064  } else {
2065  if ($candidaturetocreate->socid > 0)
2066  {
2067  $thirdpartystatic->fetch($candidaturetocreate->socid);
2068  }
2069  }
2070 
2071  $result = dol_include_once($reldir."core/modules/ticket/".$modele.'.php');
2072  $modModuleToUseForNextValue = new $classname;
2073  $defaultref = $modModuleToUseForNextValue->getNextValue(($thirdpartystatic->id > 0 ? $thirdpartystatic : null), $tickettocreate);
2074  }
2075  $candidaturetocreate->ref = $defaultref;
2076  }*/
2077 
2078  if ($errorforthisaction)
2079  {
2080  $errorforactions++;
2081  } else {
2082  // Create project
2083  $result = $candidaturetocreate->create($user);
2084  if ($result <= 0)
2085  {
2086  $errorforactions++;
2087  $this->error = 'Failed to create ticket: '.join(', ', $candidaturetocreate->errors);
2088  $this->errors = $candidaturetocreate->errors;
2089  }
2090  }
2091  }
2092  }
2093  // Create event specific on hook
2094  // this code action is hook..... for support this call
2095  elseif (substr($operation['type'], 0, 4) == 'hook') {
2096  global $hookmanager;
2097 
2098  if (!is_object($hookmanager)) {
2099  $hookmanager->initHooks(array('emailcollectorcard'));
2100  }
2101 
2102  $parameters = array(
2103  'connection'=> $connection,
2104  'imapemail'=>$imapemail,
2105  'overview'=>$overview,
2106 
2107  'from' => $from,
2108  'fromtext' => $fromtext,
2109 
2110  'actionparam'=> $operation['actionparam'],
2111 
2112  'thirdpartyid' => $thirdpartyid,
2113  'objectid'=> $objectid,
2114  'objectemail'=> $objectemail,
2115 
2116  'messagetext'=>$messagetext,
2117  'subject'=>$subject,
2118  'header'=>$header,
2119  );
2120  $res = $hookmanager->executeHooks('doCollectOneCollector', $parameters, $this, $operation['type']);
2121 
2122  if ($res < 0) {
2123  $errorforthisaction++;
2124  $this->error = $hookmanager->resPrint;
2125  }
2126  if ($errorforthisaction)
2127  {
2128  $errorforactions++;
2129  }
2130  }
2131 
2132  if (!$errorforactions)
2133  {
2134  $nbactiondoneforemail++;
2135  }
2136  }
2137 
2138  // Error for email or not ?
2139  if (!$errorforactions)
2140  {
2141  if ($targetdir)
2142  {
2143  dol_syslog("EmailCollector::doCollectOneCollector move message ".$imapemail." to ".$connectstringtarget, LOG_DEBUG);
2144  $res = imap_mail_move($connection, $imapemail, $targetdir, 0);
2145  if ($res == false) {
2146  $errorforemail++;
2147  $this->error = imap_last_error();
2148  $this->errors[] = $this->error;
2149  dol_syslog(imap_last_error());
2150  }
2151  } else {
2152  dol_syslog("EmailCollector::doCollectOneCollector message ".$imapemail." to ".$connectstringtarget." was set to read", LOG_DEBUG);
2153  }
2154  } else {
2155  $errorforemail++;
2156  }
2157 
2158  unset($objectemail);
2159  unset($projectstatic);
2160  unset($thirdpartystatic);
2161  unset($contactstatic);
2162 
2163  $nbemailprocessed++;
2164 
2165  if (!$errorforemail)
2166  {
2167  $nbactiondone += $nbactiondoneforemail;
2168  $nbemailok++;
2169 
2170  $this->db->commit();
2171 
2172  // Stop the loop to process email if we reach maximum collected per collect
2173  if ($this->maxemailpercollect > 0 && $nbemailok >= $this->maxemailpercollect)
2174  {
2175  dol_syslog("EmailCollect::doCollectOneCollector We reach maximum of ".$nbemailok." collected with success, so we stop this collector now.");
2176  break;
2177  }
2178  } else {
2179  $error++;
2180 
2181  $this->db->rollback();
2182  }
2183  }
2184 
2185  $output = $langs->trans('XEmailsDoneYActionsDone', $nbemailprocessed, $nbemailok, $nbactiondone);
2186 
2187  dol_syslog("End of loop on emails", LOG_INFO, -1);
2188  } else {
2189  $output = $langs->trans('NoNewEmailToProcess');
2190  }
2191 
2192  imap_expunge($connection); // To validate any move
2193 
2194  imap_close($connection);
2195 
2196  $this->datelastresult = $now;
2197  $this->lastresult = $output;
2198  $this->debuginfo = 'IMAP search string used : '.$search;
2199  if ($searchhead) $this->debuginfo .= '<br>Then search string into email header : '.$searchhead;
2200 
2201  if (!$error) $this->datelastok = $now;
2202 
2203  if (!empty($this->errors)) $this->lastresult .= " - ".join(" - ", $this->errors);
2204  $this->codelastresult = ($error ? 'KO' : 'OK');
2205  $this->update($user);
2206 
2207  dol_syslog("EmailCollector::doCollectOneCollector end", LOG_DEBUG);
2208 
2209  return $error ?-1 : 1;
2210  }
2211 
2212 
2213 
2214  // Loop to get part html and plain. Code found on PHP imap_fetchstructure documentation
2215 
2223  private function getmsg($mbox, $mid)
2224  {
2225  // input $mbox = IMAP stream, $mid = message id
2226  // output all the following:
2227  global $charset, $htmlmsg, $plainmsg, $attachments;
2228  $htmlmsg = $plainmsg = $charset = '';
2229  $attachments = array();
2230 
2231  // HEADER
2232  //$h = imap_header($mbox,$mid);
2233  // add code here to get date, from, to, cc, subject...
2234 
2235  // BODY
2236  $s = imap_fetchstructure($mbox, $mid);
2237 
2238  if (!$s->parts) {
2239  // simple
2240  $this->getpart($mbox, $mid, $s, 0); // pass 0 as part-number
2241  } else {
2242  // multipart: cycle through each part
2243  foreach ($s->parts as $partno0 => $p) {
2244  $this->getpart($mbox, $mid, $p, $partno0 + 1);
2245  }
2246  }
2247  }
2248 
2249  /* partno string
2250  0 multipart/mixed
2251  1 multipart/alternative
2252  1.1 text/plain
2253  1.2 text/html
2254  2 message/rfc822
2255  2 multipart/mixed
2256  2.1 multipart/alternative
2257  2.1.1 text/plain
2258  2.1.2 text/html
2259  2.2 message/rfc822
2260  2.2 multipart/alternative
2261  2.2.1 text/plain
2262  2.2.2 text/html
2263  */
2273  private function getpart($mbox, $mid, $p, $partno)
2274  {
2275  // $partno = '1', '2', '2.1', '2.1.3', etc for multipart, 0 if simple
2276  global $htmlmsg, $plainmsg, $charset, $attachments;
2277 
2278  // DECODE DATA
2279  $data = ($partno) ?
2280  imap_fetchbody($mbox, $mid, $partno) : // multipart
2281  imap_body($mbox, $mid); // simple
2282  // Any part may be encoded, even plain text messages, so check everything.
2283  if ($p->encoding == 4)
2284  $data = quoted_printable_decode($data);
2285  elseif ($p->encoding == 3)
2286  $data = base64_decode($data);
2287 
2288  // PARAMETERS
2289  // get all parameters, like charset, filenames of attachments, etc.
2290  $params = array();
2291  if ($p->parameters)
2292  {
2293  foreach ($p->parameters as $x)
2294  {
2295  $params[strtolower($x->attribute)] = $x->value;
2296  }
2297  }
2298  if ($p->dparameters)
2299  {
2300  foreach ($p->dparameters as $x)
2301  {
2302  $params[strtolower($x->attribute)] = $x->value;
2303  }
2304  }
2305 
2306  // ATTACHMENT
2307  // Any part with a filename is an attachment,
2308  // so an attached text file (type 0) is not mistaken as the message.
2309  if ($params['filename'] || $params['name']) {
2310  // filename may be given as 'Filename' or 'Name' or both
2311  $filename = ($params['filename']) ? $params['filename'] : $params['name'];
2312  // filename may be encoded, so see imap_mime_header_decode()
2313  $attachments[$filename] = $data; // this is a problem if two files have same name
2314  }
2315 
2316  // TEXT
2317  if ($p->type == 0 && $data) {
2318  if (!empty($params['charset'])) {
2319  $data = $this->convertStringEncoding($data, $params['charset']);
2320  }
2321  // Messages may be split in different parts because of inline attachments,
2322  // so append parts together with blank row.
2323  if (strtolower($p->subtype) == 'plain')
2324  $plainmsg .= trim($data)."\n\n";
2325  else $htmlmsg .= $data."<br><br>";
2326  $charset = $params['charset']; // assume all parts are same charset
2327  }
2328 
2329  // EMBEDDED MESSAGE
2330  // Many bounce notifications embed the original message as type 2,
2331  // but AOL uses type 1 (multipart), which is not handled here.
2332  // There are no PHP functions to parse embedded messages,
2333  // so this just appends the raw source to the main message.
2334  elseif ($p->type == 2 && $data) {
2335  if (!empty($params['charset'])) {
2336  $data = $this->convertStringEncoding($data, $params['charset']);
2337  }
2338  $plainmsg .= $data."\n\n";
2339  }
2340 
2341  // SUBPART RECURSION
2342  if ($p->parts) {
2343  foreach ($p->parts as $partno0=>$p2)
2344  {
2345  $this->getpart($mbox, $mid, $p2, $partno.'.'.($partno0 + 1)); // 1.2, 1.2.1, etc.
2346  }
2347  }
2348  }
2349 
2359  protected function convertStringEncoding($string, $fromEncoding, $toEncoding = 'UTF-8')
2360  {
2361  if (!$string || $fromEncoding == $toEncoding) {
2362  return $string;
2363  }
2364  $convertedString = function_exists('iconv') ? @iconv($fromEncoding, $toEncoding.'//IGNORE', $string) : null;
2365  if (!$convertedString && extension_loaded('mbstring')) {
2366  $convertedString = @mb_convert_encoding($string, $toEncoding, $fromEncoding);
2367  }
2368  if (!$convertedString) {
2369  throw new Exception('Mime string encoding conversion failed');
2370  }
2371  return $convertedString;
2372  }
2373 
2384  protected function decodeSMTPSubject($subject)
2385  {
2386  // Decode $overview[0]->subject according to RFC2047
2387  // Can use also imap_mime_header_decode($str)
2388  // Can use also mb_decode_mimeheader($str)
2389  // Can use also iconv_mime_decode($str, ICONV_MIME_DECODE_CONTINUE_ON_ERROR, 'UTF-8')
2390  if (function_exists('imap_mime_header_decode') && function_exists('iconv_mime_decode')) {
2391  $elements = imap_mime_header_decode($subject);
2392  $newstring = '';
2393  if (!empty($elements)) {
2394  $num = count($elements);
2395  for ($i = 0; $i < $num; $i++) {
2396  $stringinutf8 = (in_array(strtoupper($elements[$i]->charset), array('DEFAULT', 'UTF-8')) ? $elements[$i]->text : iconv_mime_decode($elements[$i]->text, ICONV_MIME_DECODE_CONTINUE_ON_ERROR, $elements[$i]->charset));
2397  $newstring .= $stringinutf8;
2398  }
2399  $subject = $newstring;
2400  }
2401  } elseif (!function_exists('mb_decode_mimeheader')) {
2402  $subject = mb_decode_mimeheader($subject);
2403  } elseif (function_exists('iconv_mime_decode')) {
2404  $subject = iconv_mime_decode($subject, ICONV_MIME_DECODE_CONTINUE_ON_ERROR, 'UTF-8');
2405  }
2406 
2407  return $subject;
2408  }
2409 }
if(!function_exists('dol_getprefix')) dol_include_once($relpath, $classname= '')
Make an include_once using default root and alternate root if it fails.
deleteCommon(User $user, $notrigger=false, $forcechilddeletion=0)
Delete object in database.
dol_string_nohtmltag($stringtoclean, $removelinefeed=1, $pagecodeto= 'UTF-8', $strip_tags=0, $removedoublespaces=1)
Clean a string from all HTML tags and entities.
fetchFilters()
Fetch filters.
fetch($id, $ref=null)
Load object in memory from the database.
Class to manage agenda events (actions)
Class to manage contact/addresses.
doCollectOneCollector()
Execute collect for current collector loaded previously with fetch.
foreach($object->fields as $key=> $val) if(is_array($extrafields->attributes[$object->table_element]['label'])&&count($extrafields->attributes[$object->table_element]['label']) > 0) $object fields
initAsSpecimen()
Initialise object with example values Id must be 0 if object instance is a specimen.
dol_now($mode= 'auto')
Return date for now.
convertStringEncoding($string, $fromEncoding, $toEncoding= 'UTF-8')
Converts a string from one encoding to another.
Class to manage Dolibarr users.
Definition: user.class.php:44
Class to manage Dolibarr database access.
fetchAll(User $user, $activeOnly=0, $sortfield= 's.rowid', $sortorder= 'ASC', $limit=100, $page=0)
Load object lines in memory from the database.
Class for EmailCollectorAction.
getmsg($mbox, $mid)
getmsg
initAsSpecimenCommon()
Initialise object with example values Id must be 0 if object instance is a specimen.
createCommon(User $user, $notrigger=false)
Create object into database.
getConnectStringIMAP($ssl=1, $norsh=0)
Return the connectstring to use with IMAP connection function.
dol_concatdesc($text1, $text2, $forxml=false, $invert=false)
Concat 2 descriptions with a new line between them (second operand after first one with appropriate n...
getpart($mbox, $mid, $p, $partno)
Sub function for getpart().
dol_buildpath($path, $type=0, $returnemptyifnotfound=0)
Return path of url or filesystem.
$conf db
API class for accounts.
Definition: inc.php:54
Class to manage ticket.
doCollect()
Action executed by scheduler CAN BE A CRON TASK.
__construct(DoliDB $db)
Constructor.
info($id)
Charge les informations d&#39;ordre info dans l&#39;objet commande.
createFromClone(User $user, $fromid)
Clone and object into another one.
setEventMessages($mesg, $mesgs, $style= 'mesgs', $messagekey= '')
Set event messages in dol_events session object.
overwritePropertiesOfObject(&$object, $actionparam, $messagetext, $subject, $header)
overwitePropertiesOfObject
getLibStatut($mode=0)
Return label of the status.
Class to manage third parties objects (customers, suppliers, prospects...)
Class to manage projects.
Class for EmailCollector.
getNomUrl($withpicto=0, $option= '', $notooltip=0, $morecss= '', $save_lastsearch_value=-1)
Return a link to the object card (with optionaly the picto)
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename= '', $restricttologhandler= '', $logcontext=null)
Write log message into outputs.
update(User $user, $notrigger=false)
Update object into database.
Class to manage members of a foundation.
img_object($titlealt, $picto, $moreatt= '', $pictoisfullpath=false, $srconly=0, $notitle=0)
Show a picto called object_picto (generic function)
updateCommon(User $user, $notrigger=false)
Update object into database.
create(User $user, $notrigger=false)
Create object into database.
print $_SERVER["PHP_SELF"]
Edit parameters.
dolExplodeIntoArray($string, $delimiter= ';', $kv= '=')
Split a string with 2 keys into key array.
Class for EmailCollectorFilter.
Class for RecruitmentCandidature.
dolGetFirstLineOfText($text, $nboflines=1, $charset= 'UTF-8')
Return first line of text.
dol_getIdFromCode($db, $key, $tablename, $fieldkey= 'code', $fieldid= 'id', $entityfilter=0)
Return an id or code from a code or id.
Class to manage tasks.
Definition: task.class.php:35
dol_print_date($time, $format= '', $tzoutput= 'auto', $outputlangs= '', $encodetooutput=false)
Output date in a string format according to outputlangs (or langs if not defined).
if(!empty($conf->facture->enabled)&&$user->rights->facture->lire) if((!empty($conf->fournisseur->enabled)&&empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)||!empty($conf->supplier_invoice->enabled))&&$user->rights->fournisseur->facture->lire) if(!empty($conf->don->enabled)&&$user->rights->don->lire) if(!empty($conf->tax->enabled)&&$user->rights->tax->charges->lire) if(!empty($conf->facture->enabled)&&!empty($conf->commande->enabled)&&$user->rights->commande->lire &&empty($conf->global->WORKFLOW_DISABLE_CREATE_INVOICE_FROM_ORDER)) if(!empty($conf->facture->enabled)&&$user->rights->facture->lire) if((!empty($conf->fournisseur->enabled)&&empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)||!empty($conf->supplier_invoice->enabled))&&$user->rights->fournisseur->facture->lire) $resql
Social contributions to pay.
Definition: index.php:1232
dol_print_error($db= '', $error= '', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
getEncodedUtf7($str)
Convert str to UTF-7 imap default mailbox names.
dolGetStatus($statusLabel= '', $statusLabelShort= '', $html= '', $statusType= 'status0', $displayMode=0, $url= '', $params=array())
Output the badge of a status.
make_substitutions($text, $substitutionarray, $outputlangs=null)
Make substitution into a text string, replacing keys with vals from $substitutionarray (oldval=&gt;newva...
Class to manage invoices.
fetchActions()
Fetch actions.
Parent class of all other business classes (invoices, contracts, proposals, orders, ...)
LibStatut($status, $mode=0)
Return the status.
fetchCommon($id, $ref=null, $morewhere= '')
Load object in memory from the database.
dol_escape_htmltag($stringtoescape, $keepb=0, $keepn=0, $keepmoretags= '', $escapeonlyhtmltags=0)
Returns text escaped for inclusion in HTML alt or title tags, or into values of HTML input fields...
decodeSMTPSubject($subject)
Decode a subject string according to RFC2047 Example: &#39;=?Windows-1252?Q?RE=A0:_ABC?=&#39; =&gt; &#39;RE : ABC...&#39; Example: &#39;=?UTF-8?Q?A=C3=A9B?=&#39; =&gt; &#39;AéB&#39; Example: &#39;=?UTF-8?B?2KLYstmF2KfbjNi0?=&#39; =&gt; Example: &#39;=?utf-8?B?UkU6IG1vZHVsZSBkb2xpYmFyciBnZXN0aW9ubmFpcmUgZGUgZmljaGllcnMg?= =?utf-8?B?UsOpZsOpcmVuY2UgZGUgbGEgY29tbWFuZGUgVFVHRURJSklSIOKAkyBwYXNz?= =?utf-8?B?w6llIGxlIDIyLzA0LzIwMjA=?=&#39;.