66 public $element =
'emailcollector';
71 public $table_element =
'emailcollector_emailcollector';
76 public $picto =
'email';
81 public $fk_element =
'fk_emailcollector';
86 protected $childtables = array();
91 protected $childtablesoncascade = array(
'emailcollector_emailcollectorfilter',
'emailcollector_emailcollectoraction');
117 public $fields = array(
118 'rowid' => array(
'type' =>
'integer',
'label' =>
'TechnicalID',
'visible' => -2,
'enabled' => 1,
'position' => 1,
'notnull' => 1,
'index' => 1),
119 'entity' => array(
'type' =>
'integer',
'label' =>
'Entity',
'enabled' => 1,
'visible' => 0,
'default' =>
'1',
'notnull' => 1,
'index' => 1,
'position' => 20),
120 'ref' => array(
'type' =>
'varchar(128)',
'label' =>
'Ref',
'enabled' => 1,
'visible' => 1,
'notnull' => 1,
'showoncombobox' => 1,
'index' => 1,
'position' => 10,
'searchall' => 1,
'help' =>
'Example: MyCollector1',
'csslist' =>
'tdoverflowmax200'),
121 'label' => array(
'type' =>
'varchar(255)',
'label' =>
'Label',
'visible' => 1,
'enabled' => 1,
'position' => 30,
'notnull' => -1,
'searchall' => 1,
'help' =>
'Example: My Email collector',
'csslist' =>
'tdoverflowmax150 small',
'tdcss' =>
'titlefieldmiddle'),
122 'description' => array(
'type' =>
'text',
'label' =>
'Description',
'visible' => -1,
'enabled' => 1,
'position' => 60,
'notnull' => -1,
'cssview' =>
'small',
'csslist' =>
'small tdoverflowmax200'),
123 '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',
'csslist' =>
'tdoverflowmax125'),
124 'port' => array(
'type' =>
'varchar(10)',
'label' =>
'EMailHostPort',
'visible' => 1,
'enabled' => 1,
'position' => 91,
'notnull' => 1,
'searchall' => 0,
'comment' =>
"IMAP server port",
'help' =>
'Example: 993',
'csslist' =>
'tdoverflowmax50',
'default' =>
'993'),
125 'imap_encryption' => array(
'type' =>
'varchar(16)',
'label' =>
'ImapEncryption',
'visible' => -1,
'enabled' => 1,
'position' => 92,
'searchall' => 0,
'comment' =>
"IMAP encryption",
'help' =>
'ImapEncryptionHelp',
'arrayofkeyval' => array(
'ssl' =>
'SSL',
'tls' =>
'TLS',
'notls' =>
'NOTLS'),
'default' =>
'ssl'),
126 'hostcharset' => array(
'type' =>
'varchar(16)',
'label' =>
'HostCharset',
'visible' => -1,
'enabled' => 1,
'position' => 93,
'notnull' => 0,
'searchall' => 0,
'comment' =>
"IMAP server charset",
'help' =>
'Example: "UTF-8" (May be "US-ASCII" with some Office365)',
'default' =>
'UTF-8'),
127 'norsh' => array(
'type' =>
'integer',
'label' =>
'NoRSH',
'visible' => -1,
'enabled' =>
"!getDolGlobalInt('MAIN_IMAP_USE_PHPIMAP')",
'position' => 94,
'searchall' => 0,
'help' =>
'NoRSHHelp',
'arrayofkeyval' => array(0 =>
'No', 1 =>
'Yes'),
'default' =>
'0'),
128 'acces_type' => array(
'type' =>
'integer',
'label' =>
'AuthenticationMethod',
'visible' => -1,
'enabled' =>
"getDolGlobalInt('MAIN_IMAP_USE_PHPIMAP')",
'position' => 101,
'notnull' => 1,
'index' => 1,
'comment' =>
"IMAP login type",
'arrayofkeyval' => array(0 =>
'loginPassword', 1 =>
'oauthToken'),
'default' =>
'0',
'help' =>
''),
129 'login' => array(
'type' =>
'varchar(128)',
'label' =>
'Login',
'visible' => -1,
'enabled' => 1,
'position' => 102,
'notnull' => -1,
'index' => 1,
'comment' =>
"IMAP login",
'help' =>
'Example: myaccount@gmail.com'),
130 'password' => array(
'type' =>
'password',
'label' =>
'Password',
'visible' => -1,
'enabled' =>
"1",
'position' => 103,
'notnull' => -1,
'comment' =>
"IMAP password",
'help' =>
'WithGMailYouCanCreateADedicatedPassword'),
131 'oauth_service' => array(
'type' =>
'varchar(128)',
'label' =>
'oauthService',
'visible' => -1,
'enabled' =>
"getDolGlobalInt('MAIN_IMAP_USE_PHPIMAP')",
'position' => 104,
'notnull' => 0,
'index' => 1,
'comment' =>
"IMAP login oauthService",
'arrayofkeyval' => array(),
'help' =>
'TokenMustHaveBeenCreated'),
132 'source_directory' => array(
'type' =>
'varchar(255)',
'label' =>
'MailboxSourceDirectory',
'visible' => -1,
'enabled' => 1,
'position' => 109,
'notnull' => 1,
'default' =>
'Inbox',
'csslist' =>
'tdoverflowmax100',
'help' =>
'Example: INBOX, [Gmail]/Spam, [Gmail]/Draft, [Gmail]/Brouillons, [Gmail]/Sent Mail, [Gmail]/Messages envoyés, ...'),
133 'target_directory' => array(
'type' =>
'varchar(255)',
'label' =>
'MailboxTargetDirectory',
'visible' => 1,
'enabled' => 1,
'position' => 110,
'notnull' => 0,
'csslist' =>
'tdoverflowmax100',
'help' =>
"EmailCollectorTargetDir"),
134 'maxemailpercollect' => array(
'type' =>
'integer',
'label' =>
'MaxEmailCollectPerCollect',
'visible' => -1,
'enabled' => 1,
'position' => 111,
'default' =>
'50'),
135 'datelastresult' => array(
'type' =>
'datetime',
'label' =>
'DateLastCollectResult',
'visible' => 1,
'enabled' =>
'$action != "create" && $action != "edit"',
'position' => 121,
'notnull' => -1,
'csslist' =>
'nowraponall'),
136 'codelastresult' => array(
'type' =>
'varchar(16)',
'label' =>
'CodeLastResult',
'visible' => 1,
'enabled' =>
'$action != "create" && $action != "edit"',
'position' => 122,
'notnull' => -1,),
137 'lastresult' => array(
'type' =>
'varchar(255)',
'label' =>
'LastResult',
'visible' => 1,
'enabled' =>
'$action != "create" && $action != "edit"',
'position' => 123,
'notnull' => -1,
'cssview' =>
'small',
'csslist' =>
'maxwidth250imp'),
138 'datelastok' => array(
'type' =>
'datetime',
'label' =>
'DateLastcollectResultOk',
'visible' => 1,
'enabled' =>
'$action != "create"',
'position' => 125,
'notnull' => -1,
'csslist' =>
'nowraponall'),
139 'note_public' => array(
'type' =>
'html',
'label' =>
'NotePublic',
'visible' => 0,
'enabled' => 1,
'position' => 61,
'notnull' => -1,),
140 'note_private' => array(
'type' =>
'html',
'label' =>
'NotePrivate',
'visible' => 0,
'enabled' => 1,
'position' => 62,
'notnull' => -1,),
141 'date_creation' => array(
'type' =>
'datetime',
'label' =>
'DateCreation',
'visible' => -2,
'enabled' => 1,
'position' => 500,
'notnull' => 1,),
142 'tms' => array(
'type' =>
'timestamp',
'label' =>
'DateModification',
'visible' => -2,
'enabled' => 1,
'position' => 501,
'notnull' => 1,),
144 'fk_user_creat' => array(
'type' =>
'integer:User:user/class/user.class.php',
'label' =>
'UserAuthor',
'visible' => -2,
'enabled' => 1,
'position' => 510,
'notnull' => 1,),
145 'fk_user_modif' => array(
'type' =>
'integer:User:user/class/user.class.php',
'label' =>
'UserModif',
'visible' => -2,
'enabled' => 1,
'position' => 511,
'notnull' => -1,),
147 'import_key' => array(
'type' =>
'varchar(14)',
'label' =>
'ImportId',
'visible' => -2,
'enabled' => 1,
'position' => 1000,
'notnull' => -1,),
148 'status' => array(
'type' =>
'integer',
'label' =>
'Status',
'visible' => 1,
'enabled' => 1,
'position' => 1000,
'notnull' => 1,
'default' =>
'0',
'index' => 1,
'arrayofkeyval' => array(0 =>
'Inactive', 1 =>
'Active'))
180 public $fk_user_creat;
185 public $fk_user_modif;
219 public $oauth_service;
223 public $imap_encryption;
231 public $source_directory;
235 public $target_directory;
239 public $maxemailpercollect;
244 public $datelastresult;
249 public $codelastresult;
274 const STATUS_DISABLED = 0;
275 const STATUS_ENABLED = 1;
285 global
$conf, $langs;
289 $this->ismultientitymanaged = 1;
290 $this->isextrafieldmanaged = 0;
295 if (!
isModEnabled(
'multicompany') && isset($this->fields[
'entity'])) {
296 $this->fields[
'entity'][
'enabled'] = 0;
300 $oauthservices = array();
302 foreach (
$conf->global as $key => $val) {
303 if (!empty($val) && preg_match(
'/^OAUTH_.*_ID$/', $key)) {
304 $key = preg_replace(
'/^OAUTH_/',
'', $key);
305 $key = preg_replace(
'/_ID$/',
'', $key);
306 if (preg_match(
'/^.*-/', $key)) {
307 $name = preg_replace(
'/^.*-/',
'', $key);
309 $name = $langs->trans(
"NoName");
311 $provider = preg_replace(
'/-.*$/',
'', $key);
312 $provider = ucfirst(strtolower($provider));
314 $oauthservices[$key] = $name.
" (".$provider.
")";
318 $this->fields[
'oauth_service'][
'arrayofkeyval'] = $oauthservices;
321 foreach ($this->fields as $key => $val) {
322 if (isset($val[
'enabled']) && empty($val[
'enabled'])) {
323 unset($this->fields[$key]);
328 foreach ($this->fields as $key => $val) {
329 if (!empty($val[
'arrayofkeyval']) && is_array($val[
'arrayofkeyval'])) {
330 foreach ($val[
'arrayofkeyval'] as $key2 => $val2) {
331 $this->fields[$key][
'arrayofkeyval'][$key2] = $langs->trans($val2);
349 if ($this->host && preg_match(
'/^http:/i', trim($this->host))) {
350 $langs->load(
"errors");
351 $this->error = $langs->trans(
"ErrorHostMustNotStartWithHttp", $this->host);
355 include_once DOL_DOCUMENT_ROOT.
'/core/lib/security.lib.php';
356 $this->password =
dolEncrypt($this->password);
360 $this->password =
dolDecrypt($this->password);
362 if (is_array($this->filters) && count($this->filters)) {
365 foreach ($this->filters as $filter) {
366 $emailcollectorfilter->type = $filter[
'type'];
367 $emailcollectorfilter->rulevalue = $filter[
'rulevalue'];
368 $emailcollectorfilter->fk_emailcollector = $this->id;
369 $emailcollectorfilter->status = $filter[
'status'];
371 $emailcollectorfilter->create($user);
375 if (is_array($this->actions) && count($this->actions)) {
378 foreach ($this->actions as $operation) {
379 $emailcollectoroperation->type = $operation[
'type'];
380 $emailcollectoroperation->actionparam = $operation[
'actionparam'];
381 $emailcollectoroperation->fk_emailcollector = $this->id;
382 $emailcollectoroperation->status = $operation[
'status'];
383 $emailcollectoroperation->position = $operation[
'position'];
385 $emailcollectoroperation->create($user);
401 global $langs, $extrafields;
422 unset(
$object->codelastresult);
423 unset(
$object->datelastresult);
428 $object->ref =
"copy_of_".$object->ref;
431 $object->host =
'imap.example.com';
434 if (is_array(
$object->array_options) && count(
$object->array_options) > 0) {
435 $extrafields->fetch_name_optionals_label($this->table_element);
436 foreach (
$object->array_options as $key => $option) {
437 $shortkey = preg_replace(
'/options_/',
'', $key);
438 if (!empty($extrafields->attributes[$this->element][
'unique'][$shortkey])) {
439 unset(
$object->array_options[$key]);
445 $object->context[
'createfromclone'] =
'createfromclone';
446 $result =
$object->create($user);
452 unset(
$object->context[
'createfromclone']);
459 $this->db->rollback();
471 public function fetch($id, $ref =
null)
475 include_once DOL_DOCUMENT_ROOT.
'/core/lib/security.lib.php';
476 $this->password =
dolDecrypt($this->password);
509 public function fetchAll(
User $user, $activeOnly = 0, $sortfield =
's.rowid', $sortorder =
'ASC', $limit = 100, $page = 0)
513 $sql =
"SELECT s.rowid";
514 $sql .=
" FROM ".MAIN_DB_PREFIX.
"emailcollector_emailcollector as s";
515 $sql .=
' WHERE s.entity IN ('.getEntity(
'emailcollector').
')';
517 $sql .=
" AND s.status = 1";
519 $sql .= $this->db->order($sortfield, $sortorder);
524 $offset = $limit * $page;
526 $sql .= $this->db->plimit($limit + 1, $offset);
529 $result = $this->db->query($sql);
531 $num = $this->db->num_rows($result);
534 $obj = $this->db->fetch_object($result);
536 if ($emailcollector_static->fetch($obj->rowid)) {
537 $obj_ret[] = $emailcollector_static;
542 $this->errors[] =
'EmailCollector::fetchAll Error when retrieve emailcollector list';
543 dol_syslog(
'EmailCollector::fetchAll Error when retrieve emailcollector list', LOG_ERR);
545 if (!count($obj_ret)) {
546 dol_syslog(
'EmailCollector::fetchAll No emailcollector found', LOG_DEBUG);
564 if ($this->host && preg_match(
'/^http:/i', trim($this->host))) {
565 $langs->load(
"errors");
566 $this->error = $langs->trans(
"ErrorHostMustNotStartWithHttp", $this->host);
570 include_once DOL_DOCUMENT_ROOT.
'/core/lib/security.lib.php';
571 $this->password =
dolEncrypt($this->password);
575 $this->password =
dolDecrypt($this->password);
587 public function delete(
User $user, $notrigger = 0)
602 public function getNomUrl($withpicto = 0, $option =
'', $notooltip = 0, $morecss =
'', $save_lastsearch_value = -1)
604 global
$conf, $langs, $action, $hookmanager;
606 if (!empty(
$conf->dol_no_mouse_hover)) {
612 $label =
'<u>'.$langs->trans(
"EmailCollector").
'</u>';
614 $label .=
'<b>'.$langs->trans(
'Ref').
':</b> '.$this->ref;
616 $url = DOL_URL_ROOT.
'/admin/emailcollector_card.php?id='.$this->id;
618 if ($option !=
'nolink') {
620 $add_save_lastsearch_values = ($save_lastsearch_value == 1 ? 1 : 0);
621 if ($save_lastsearch_value == -1 && isset($_SERVER[
"PHP_SELF"]) && preg_match(
'/list\.php/', $_SERVER[
"PHP_SELF"])) {
622 $add_save_lastsearch_values = 1;
624 if ($add_save_lastsearch_values) {
625 $url .=
'&save_lastsearch_values=1';
630 if (empty($notooltip)) {
632 $label = $langs->trans(
"ShowEmailCollector");
633 $linkclose .=
' alt="'.dolPrintHTMLForAttribute($label).
'"';
635 $linkclose .=
' title="'.dolPrintHTMLForAttribute($label).
'"';
636 $linkclose .=
' class="classfortooltip'.($morecss ?
' '.$morecss :
'').
'"';
638 $linkclose = ($morecss ?
' class="'.$morecss.
'"' :
'');
641 $linkstart =
'<a href="'.$url.
'"';
642 $linkstart .= $linkclose.
'>';
645 $result .= $linkstart;
647 $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);
649 if ($withpicto != 2) {
650 $result .= $this->ref;
655 $hookmanager->initHooks(array(
'emailcollectordao'));
656 $parameters = array(
'id' => $this->
id,
'getnomurl' => &$result);
657 $reshook = $hookmanager->executeHooks(
'getNomUrl', $parameters, $this, $action);
659 $result = $hookmanager->resPrint;
661 $result .= $hookmanager->resPrint;
689 if (empty($this->labelStatus) || empty($this->labelStatusShort)) {
692 $this->labelStatus[self::STATUS_ENABLED] = $langs->transnoentitiesnoconv(
'Enabled');
693 $this->labelStatus[self::STATUS_DISABLED] = $langs->transnoentitiesnoconv(
'Disabled');
694 $this->labelStatusShort[self::STATUS_ENABLED] = $langs->transnoentitiesnoconv(
'Enabled');
695 $this->labelStatusShort[self::STATUS_DISABLED] = $langs->transnoentitiesnoconv(
'Disabled');
698 $statusType =
'status5';
699 if ($status == self::STATUS_ENABLED) {
700 $statusType =
'status4';
703 return dolGetStatus($this->labelStatus[$status], $this->labelStatusShort[$status],
'', $statusType, $mode);
714 $sql =
'SELECT rowid, date_creation as datec, tms as datem,';
715 $sql .=
' fk_user_creat, fk_user_modif';
716 $sql .=
' FROM '.MAIN_DB_PREFIX.$this->table_element.
' as t';
717 $sql .=
' WHERE t.rowid = '.((int) $id);
718 $result = $this->db->query($sql);
720 if ($this->db->num_rows($result)) {
721 $obj = $this->db->fetch_object($result);
723 $this->
id = $obj->rowid;
725 $this->user_creation_id = $obj->fk_user_creat;
726 $this->user_modification_id = $obj->fk_user_modif;
727 $this->date_creation = $this->db->jdate($obj->datec);
728 $this->date_modification = empty($obj->datem) ?
'' : $this->db->jdate($obj->datem);
731 $this->db->free($result);
745 $this->host =
'localhost';
746 $this->login =
'alogin';
759 $this->filters = array();
761 $sql =
'SELECT rowid, type, rulevalue, status';
762 $sql .=
' FROM '.MAIN_DB_PREFIX.
'emailcollector_emailcollectorfilter';
763 $sql .=
' WHERE fk_emailcollector = '.((int) $this->
id);
766 $resql = $this->db->query($sql);
768 $num = $this->db->num_rows($resql);
771 $obj = $this->db->fetch_object($resql);
772 $this->filters[$obj->rowid] = array(
'id' => $obj->rowid,
'type' => $obj->type,
'rulevalue' => $obj->rulevalue,
'status' => $obj->status);
775 $this->db->free($resql);
791 $this->actions = array();
793 $sql =
'SELECT rowid, type, actionparam, status';
794 $sql .=
' FROM '.MAIN_DB_PREFIX.
'emailcollector_emailcollectoraction';
795 $sql .=
' WHERE fk_emailcollector = '.((int) $this->
id);
796 $sql .=
' ORDER BY position';
798 $resql = $this->db->query($sql);
800 $num = $this->db->num_rows($resql);
803 $obj = $this->db->fetch_object($resql);
804 $this->actions[$obj->rowid] = array(
'id' => $obj->rowid,
'type' => $obj->type,
'actionparam' => $obj->actionparam,
'status' => $obj->status);
807 $this->db->free($resql);
826 $flags =
'/service=imap';
829 } elseif (empty($this->imap_encryption) || ($this->imap_encryption ==
'ssl' &&
getDolGlobalString(
'IMAP_FORCE_NOSSL'))) {
832 $flags .=
'/' . $this->imap_encryption;
835 $flags .=
'/novalidate-cert';
842 if (!empty($this->login) && strpos($this->login,
'/') !=
false) {
843 $partofauth = explode(
'/', $this->login);
844 $flags .=
'/authuser='.$partofauth[0].
'/user='.$partofauth[1];
847 $connectstringserver =
'{'.$this->host.
':'.$this->port.$flags.
'}';
849 return $connectstringserver;
860 if (function_exists(
'mb_convert_encoding')) {
862 $str = preg_replace(
"/ /",
"xxxSPACExxx", $str);
863 $str = preg_replace(
"/_/",
"xxxUNDERSCORExxx", $str);
864 $str = preg_replace(
"/\[Gmail\]/",
"xxxGMAILxxx", $str);
866 if ($str = mb_convert_encoding($str,
"UTF-7")) {
868 $str = preg_replace(
"/\+A/",
"&A", $str);
869 $str = preg_replace(
"/xxxUNDERSCORExxx/",
"_", $str);
871 $str = preg_replace(
"/xxxSPACExxx/",
" ", $str);
873 $str = preg_replace(
"/xxxGMAILxxx/",
"[Gmail]", $str);
877 $this->error =
"error: is not possible to encode this string '".$str.
"'";
897 $arrayofcollectors = $this->
fetchAll($user, 1);
899 foreach ($arrayofcollectors as $emailcollector) {
900 $result = $emailcollector->doCollectOneCollector(0);
902 dol_syslog(
"doCollect result = ".$result.
" for emailcollector->id = ".$emailcollector->id);
904 $this->error .=
'EmailCollector ID '.$emailcollector->id.
':'.$emailcollector->error.
'<br>';
905 if (!empty($emailcollector->errors)) {
906 $this->error .= implode(
'<br>', $emailcollector->errors);
909 $this->output .=
'EmailCollector ID '.$emailcollector->id.
': '.$emailcollector->lastresult.
'<br>';
932 global
$conf, $langs;
934 $errorforthisaction = 0;
937 $outputlangs = $langs;
940 $newlang =
GETPOST(
'lang_id',
'aZ09');
943 $newlang = !empty(
$object->thirdparty->default_lang) ?
$object->thirdparty->default_lang : $newlang;
945 if (!empty($newlang)) {
947 $outputlangs->setDefaultLang($newlang);
957 foreach ($arrayvaluetouse as $propertytooverwrite => $valueforproperty) {
960 $tmparray = explode(
'.', $propertytooverwrite);
961 if (count($tmparray) == 2) {
962 $tmpclass = $tmparray[0];
963 $tmpproperty = $tmparray[1];
965 $tmpproperty = $tmparray[0];
967 if ($tmpclass && ($tmpclass !=
$object->element)) {
977 $regforregex = array();
978 if (preg_match(
'/^EXTRACT:([a-zA-Z0-9_]+):(.*):([^:])$/', $valueforproperty, $regforregex)) {
979 $sourcefield = $regforregex[1];
980 $regexstring = $regforregex[2];
982 } elseif (preg_match(
'/^EXTRACT:([a-zA-Z0-9_]+):(.*)$/', $valueforproperty, $regforregex)) {
983 $sourcefield = $regforregex[1];
984 $regexstring = $regforregex[2];
987 if (!empty($sourcefield) && !empty($regexstring)) {
988 if (strtolower($sourcefield) ==
'body') {
989 $sourcestring = $messagetext;
990 } elseif (strtolower($sourcefield) ==
'subject') {
991 $sourcestring = $subject;
992 } elseif (strtolower($sourcefield) ==
'header') {
993 $sourcestring = $header;
997 $regforval = array();
999 if (strtolower($sourcefield) ==
'body') {
1000 $regexoptions =
'ms';
1002 if (strtolower($sourcefield) ==
'header') {
1003 $regexoptions =
'm';
1006 if (preg_match(
'/'.$regexstring.
'/'.$regexoptions, $sourcestring, $regforval)) {
1008 $valueextracted = isset($regforval[count($regforval) - 1]) ? trim($regforval[count($regforval) - 1]) :
'';
1009 $valuetoset = (strtolower($sourcefield) ==
'body') ? $valueextracted : $this->
decodeSMTPSubject($valueextracted);
1010 if (preg_match(
'/^options_/', $tmpproperty)) {
1011 $object->array_options[preg_replace(
'/^options_/',
'', $tmpproperty)] = $valuetoset;
1013 if (property_exists(
$object, $tmpproperty)) {
1014 $object->$tmpproperty = $valuetoset;
1016 $tmp[$tmpproperty] = $valuetoset;
1020 if (preg_match(
'/^options_/', $tmpproperty)) {
1023 if (property_exists(
$object, $tmpproperty)) {
1031 if (property_exists(
$object, $tmpproperty)) {
1033 $operationslog .=
'<br>Regex /'.dol_escape_htmltag($regexstring).
'/'.
dol_escape_htmltag($regexoptions).
' into '.strtolower($sourcefield).
' -> not found, so object property '.
dol_escape_htmltag($tmpproperty).
' is set to null.';
1035 $tmp[$tmpproperty] =
null;
1036 $operationslog .=
'<br>Regex /'.dol_escape_htmltag($regexstring).
'/'.
dol_escape_htmltag($regexoptions).
' into '.strtolower($sourcefield).
' -> not found, so var '.
dol_escape_htmltag($tmpproperty).
' is set to null.';
1041 $errorforthisaction++;
1042 $this->error =
'The extract rule to use to overwrite properties has on an unknown source (must be HEADER, SUBJECT or BODY)';
1043 $this->errors[] = $this->error;
1045 $operationslog .=
'<br>'.$this->error;
1047 } elseif (preg_match(
'/^(SET|SETIFEMPTY):(.*)$/', $valueforproperty, $regforregex)) {
1049 if (preg_match(
'/^options_/', $tmpproperty)) {
1050 $valuecurrent =
$object->array_options[preg_replace(
'/^options_/',
'', $tmpproperty)];
1052 if (property_exists(
$object, $tmpproperty)) {
1053 $valuecurrent =
$object->$tmpproperty;
1056 $valuecurrent = $tmp[$tmpproperty];
1060 if ($regforregex[1] ==
'SET' || empty($valuecurrent)) {
1061 $valuetouse = $regforregex[2];
1062 $substitutionarray = getCommonSubstitutionArray($outputlangs, 0,
null,
$object);
1064 $matcharray = array();
1065 preg_match_all(
'/__([a-z0-9]+(?:_[a-z0-9]+)?)__/i', $valuetouse, $matcharray);
1066 if (is_array($matcharray[1])) {
1067 foreach ($matcharray[1] as $keytoreplace) {
1068 if ($keytoreplace) {
1069 if (preg_match(
'/^options_/', $keytoreplace)) {
1070 $substitutionarray[
'__'.$keytoreplace.
'__'] =
$object->array_options[preg_replace(
'/^options_/',
'', $keytoreplace)];
1072 if (property_exists(
$object, $keytoreplace)) {
1073 $substitutionarray[
'__'.$keytoreplace.
'__'] =
$object->$keytoreplace;
1076 $substitutionarray[
'__'.$keytoreplace.
'__'] = $tmp[$keytoreplace];
1085 if (preg_match(
'/^options_/', $tmpproperty)) {
1086 $object->array_options[preg_replace(
'/^options_/',
'', $tmpproperty)] = $valuetouse;
1088 $operationslog .=
'<br>Set value '.dol_escape_htmltag($valuetouse).
' into object->array_options['.
dol_escape_htmltag(preg_replace(
'/^options_/',
'', $tmpproperty)).
']';
1090 if (property_exists(
$object, $tmpproperty)) {
1091 $object->$tmpproperty = $valuetouse;
1093 $tmp[$tmpproperty] = $valuetouse;
1096 $operationslog .=
'<br>Set value '.dol_escape_htmltag($valuetouse).
' into object->'.
dol_escape_htmltag($tmpproperty);
1100 $errorforthisaction++;
1101 $this->error =
'Bad syntax for description of action parameters: '.$actionparam;
1102 $this->errors[] = $this->error;
1107 return $errorforthisaction;
1116 public function doCollectOneCollector($mode = 0)
1118 global $db,
$conf, $langs, $user;
1119 global $hookmanager;
1123 require_once DOL_DOCUMENT_ROOT.
'/comm/action/class/actioncomm.class.php';
1125 require_once DOL_DOCUMENT_ROOT.
'/includes/webklex/php-imap/vendor/autoload.php';
1128 dol_syslog(
"EmailCollector::doCollectOneCollector start for id=".$this->
id.
" - ".$this->
ref, LOG_INFO);
1130 $langs->loadLangs(array(
"project",
"companies",
"mails",
"errors",
"ticket",
"agenda",
"commercial"));
1135 $this->debuginfo =
'';
1139 $searchfilterdoltrackid = 0;
1140 $searchfilternodoltrackid = 0;
1141 $searchfilterisanswer = 0;
1142 $searchfilterisnotanswer = 0;
1143 $searchfilterreplyto = 0;
1144 $searchfilterexcludebodyarray = array();
1145 $searchfilterexcludesubjectarray = array();
1146 $searchfilterexcludeemailarray = array();
1147 $searchfilterexcludedomainarray = array();
1148 $searchfilterexcludeemailmap = array();
1149 $operationslog =
'';
1150 $rulesreplyto = array();
1151 $connectstringsource =
'';
1152 $connectstringtarget =
'';
1153 $connection =
false;
1154 $arrayofemail = array();
1159 if (empty($this->host)) {
1160 $this->error = $langs->trans(
'ErrorFieldRequired', $langs->transnoentitiesnoconv(
'EMailHost'));
1163 if (empty($this->login)) {
1164 $this->error = $langs->trans(
'ErrorFieldRequired', $langs->transnoentitiesnoconv(
'Login'));
1167 if (empty($this->source_directory)) {
1168 $this->error = $langs->trans(
'ErrorFieldRequired', $langs->transnoentitiesnoconv(
'MailboxSourceDirectory'));
1174 $sourcedir = $this->source_directory;
1175 $targetdir = ($this->target_directory ? $this->target_directory :
'');
1180 $sourcedir = $this->source_directory;
1181 $targetdir = ($this->target_directory ? $this->target_directory :
'');
1184 $timeoutconnect = (int)
getDolGlobalInt(
'MAIN_USE_CONNECT_TIMEOUT', 5);
1185 if ($timeoutconnect <= 0) {
1186 $timeoutconnect = 5;
1188 $timeoutread = (int)
getDolGlobalInt(
'MAIN_USE_RESPONSE_TIMEOUT', 20);
1189 if ($timeoutread <= 0) {
1192 if (function_exists(
'imap_timeout')) {
1193 imap_timeout(IMAP_OPENTIMEOUT, $timeoutconnect);
1194 imap_timeout(IMAP_READTIMEOUT, $timeoutread);
1195 imap_timeout(IMAP_WRITETIMEOUT, 5);
1196 imap_timeout(IMAP_CLOSETIMEOUT, 5);
1197 $this->debuginfo .=
'IMAP timeouts: connect='.$timeoutconnect.
's, read='.$timeoutread.
's<br>';
1201 if ($this->acces_type == 1) {
1203 $this->debuginfo .=
'doCollectOneCollector is using method MAIN_IMAP_USE_PHPIMAP=1, access_type=1 (OAUTH2)<br>';
1205 require_once DOL_DOCUMENT_ROOT.
'/core/lib/oauth.lib.php';
1209 $keyforsupportedoauth2array = $this->oauth_service;
1210 if (preg_match(
'/^.*-/', $keyforsupportedoauth2array)) {
1211 $keyforprovider = preg_replace(
'/^.*-/',
'', $keyforsupportedoauth2array);
1213 $keyforprovider =
'';
1215 $keyforsupportedoauth2array = preg_replace(
'/-.*$/',
'', strtoupper($keyforsupportedoauth2array));
1216 $keyforsupportedoauth2array =
'OAUTH_'.$keyforsupportedoauth2array.
'_NAME';
1218 if (!empty($supportedoauth2array)) {
1219 $nameofservice = ucfirst(strtolower(empty($supportedoauth2array[$keyforsupportedoauth2array][
'callbackfile']) ?
'Unknown' : $supportedoauth2array[$keyforsupportedoauth2array][
'callbackfile']));
1220 $nameofservice .= ($keyforprovider ?
'-'.$keyforprovider :
'');
1221 $OAUTH_SERVICENAME = $nameofservice;
1223 $OAUTH_SERVICENAME =
'Unknown';
1226 $keyforparamtenant =
'OAUTH_'.strtoupper(empty($supportedoauth2array[$keyforsupportedoauth2array][
'callbackfile']) ?
'Unknown' : $supportedoauth2array[$keyforsupportedoauth2array][
'callbackfile']).($keyforprovider ?
'-'.$keyforprovider :
'').
'_TENANT';
1228 require_once DOL_DOCUMENT_ROOT.
'/includes/OAuth/bootstrap.php';
1237 $tokenobj = $storage->retrieveAccessToken($OAUTH_SERVICENAME);
1240 if (is_object($tokenobj) && method_exists($tokenobj,
'getEndOfLife')) {
1241 $endOfLife = $tokenobj->getEndOfLife();
1242 if ($endOfLife !== -9002 && $endOfLife !== -9001 && time() > ($endOfLife - 30)) {
1248 if (is_object($tokenobj) && $expire) {
1249 $this->debuginfo .=
'Refresh token '.$OAUTH_SERVICENAME.
'<br>';
1250 $credentials =
new Credentials(
1255 $serviceFactory = new \OAuth\ServiceFactory();
1256 $oauthname = explode(
'-', $OAUTH_SERVICENAME);
1260 if (preg_match(
'/^Microsoft/', $OAUTH_SERVICENAME)) {
1262 $tmp = explode(
'-', $OAUTH_SERVICENAME);
1263 $scopes = explode(
',',
getDolGlobalString(
'OAUTH_'.strtoupper($tmp[0]).(empty($tmp[1]) ?
'' :
'-'.$tmp[1]).
'_SCOPE'));
1266 $apiService = $serviceFactory->createService($oauthname[0], $credentials, $storage, $scopes);
1268 '@phan-var-force OAuth\OAuth2\Service\AbstractService|OAuth\OAuth1\Service\AbstractService $apiService';
1270 $refreshtoken = $tokenobj->getRefreshToken();
1271 $tokenobj = $apiService->refreshAccessToken($tokenobj);
1274 $tokenobj->setRefreshToken($refreshtoken);
1275 $storage->storeAccessToken($OAUTH_SERVICENAME, $tokenobj);
1277 $tokenobj = $storage->retrieveAccessToken($OAUTH_SERVICENAME);
1278 if (is_object($tokenobj)) {
1279 $token = $tokenobj->getAccessToken();
1281 $this->error =
"Token not found";
1286 $this->error = $e->getMessage();
1287 dol_syslog(
"CMailFile::sendfile: mail end error=".$this->error, LOG_ERR);
1291 $cm =
new ClientManager();
1292 $client = $cm->make([
1293 'host' => $this->host,
1294 'port' => $this->port,
1295 'encryption' => !empty($this->imap_encryption) ? $this->imap_encryption : false,
1296 'validate_cert' => true,
1297 'protocol' =>
'imap',
1298 'username' => $this->login,
1299 'password' => $token,
1300 'authentication' =>
"oauth",
1304 $this->debuginfo .=
'doCollectOneCollector is using method MAIN_IMAP_USE_PHPIMAP=1, access_type=0 (LOGIN)<br>';
1306 $cm =
new ClientManager();
1307 $client = $cm->make([
1308 'host' => $this->host,
1309 'port' => $this->port,
1310 'encryption' => !empty($this->imap_encryption) ? $this->imap_encryption : false,
1311 'validate_cert' => true,
1312 'protocol' =>
'imap',
1313 'username' => $this->login,
1314 'password' => $this->password,
1315 'authentication' =>
"login",
1323 }
catch (ConnectionFailedException $e) {
1324 $this->error = $e->getMessage();
1325 $this->errors[] = $this->error;
1326 dol_syslog(
"EmailCollector::doCollectOneCollector ".$this->error, LOG_ERR);
1330 $host = dol_getprefix(
'email');
1333 $this->debuginfo .=
'doCollectOneCollector is using method MAIN_IMAP_USE_PHPIMAP=0 (native PHP imap, LOGIN)<br>';
1335 if (!function_exists(
'imap_open')) {
1336 $this->error =
'IMAP function not enabled on your PHP';
1342 $connectstringsource = $connectstringserver.$this->getEncodedUtf7($sourcedir);
1343 $connectstringtarget = $connectstringserver.$this->getEncodedUtf7($targetdir);
1345 $connectstringsource = $connectstringserver.$sourcedir;
1346 $connectstringtarget = $connectstringserver.$targetdir;
1349 $this->debuginfo .=
'connectstringsource = '.$connectstringsource.
', $connectstringtarget='.$connectstringtarget.
'<br>';
1351 $connection = imap_open($connectstringsource, $this->login, $this->password);
1352 if ($connection ===
false) {
1353 $this->error =
'Failed to open IMAP connection '.$connectstringsource.
' '.imap_last_error();
1356 '@phan-var-force resource|IMAP\Connection $connection';
1359 $host = dol_getprefix(
'email');
1368 $criteria = array();
1371 $criteria = array(array(
'UNDELETED'));
1372 foreach ($this->filters as $rule) {
1373 if (empty($rule[
'status'])) {
1378 if (strpos($rule[
'rulevalue'],
'!') === 0) {
1382 $rule[
'rulevalue'] = substr($rule[
'rulevalue'], 1);
1385 if ($rule[
'type'] ==
'excludeemail') {
1386 $tmpvalues = preg_split(
'/[\\r\\n,;]+/', (
string) $rule[
'rulevalue']);
1387 if (is_array($tmpvalues)) {
1388 foreach ($tmpvalues as $tmpvalue) {
1389 $tmpvalue = trim((
string) $tmpvalue);
1390 if ($tmpvalue ===
'') {
1394 if (preg_match_all(
'/[a-z0-9._%+\\-]+@[a-z0-9.\\-]+\\.[a-z]{2,}/i', $tmpvalue, $tmpmatches)) {
1395 foreach ($tmpmatches[0] as $tmpemail) {
1396 $tmpemail = strtolower(trim($tmpemail));
1397 if ($tmpemail !==
'') {
1398 $searchfilterexcludeemailarray[] = $tmpemail;
1406 if ($rule[
'type'] ==
'excludedomain') {
1407 $tmpvalues = preg_split(
'/[\\r\\n,;]+/', (
string) $rule[
'rulevalue']);
1408 if (is_array($tmpvalues)) {
1409 foreach ($tmpvalues as $tmpvalue) {
1410 $tmpvalue = trim((
string) $tmpvalue);
1411 if ($tmpvalue ===
'') {
1415 if (preg_match_all(
'/[a-z0-9._%+\\-]+@([a-z0-9.\\-]+\\.[a-z]{2,})/i', $tmpvalue, $tmpmatches)) {
1416 foreach ($tmpmatches[1] as $tmpdomain) {
1417 $tmpdomain = strtolower(trim($tmpdomain));
1418 $tmpdomain = trim($tmpdomain,
". \t\n\r\0\x0B");
1419 if ($tmpdomain !==
'') {
1420 $searchfilterexcludedomainarray[] = $tmpdomain;
1426 $tmpdomain = strtolower($tmpvalue);
1427 $tmpdomain = preg_replace(
'/^mailto:/i',
'', $tmpdomain);
1428 $tmpdomain = trim($tmpdomain);
1429 $tmpdomain = trim($tmpdomain,
"<> \t\n\r\0\x0B.,;");
1430 if (strpos($tmpdomain,
'@') === 0) {
1431 $tmpdomain = substr($tmpdomain, 1);
1433 $posat = strrpos($tmpdomain,
'@');
1434 if ($posat !==
false) {
1435 $tmpdomain = substr($tmpdomain, $posat + 1);
1437 $tmpdomain = trim($tmpdomain,
". \t\n\r\0\x0B");
1438 if ($tmpdomain !==
'') {
1439 $searchfilterexcludedomainarray[] = $tmpdomain;
1446 if ($rule[
'type'] ==
'from') {
1447 $tmprulevaluearray = explode(
'*', $rule[
'rulevalue']);
1448 if (count($tmprulevaluearray) >= 2) {
1449 foreach ($tmprulevaluearray as $tmprulevalue) {
1450 array_push($criteria, array($not.
"FROM" => $tmprulevalue));
1453 array_push($criteria, array($not.
"FROM" => $rule[
'rulevalue']));
1456 if ($rule[
'type'] ==
'to') {
1457 $tmprulevaluearray = explode(
'*', $rule[
'rulevalue']);
1458 if (count($tmprulevaluearray) >= 2) {
1459 foreach ($tmprulevaluearray as $tmprulevalue) {
1460 array_push($criteria, array($not.
"TO" => $tmprulevalue));
1463 array_push($criteria, array($not.
"TO" => $rule[
'rulevalue']));
1466 if ($rule[
'type'] ==
'bcc') {
1467 array_push($criteria, array($not.
"BCC" => $rule[
'rulevalue']));
1469 if ($rule[
'type'] ==
'cc') {
1470 array_push($criteria, array($not.
"CC" => $rule[
'rulevalue']));
1472 if ($rule[
'type'] ==
'subject') {
1475 $searchfilterexcludesubjectarray[] = $rule[
'rulevalue'];
1477 array_push($criteria, array(
"SUBJECT" => $rule[
'rulevalue']));
1480 if ($rule[
'type'] ==
'body') {
1483 $searchfilterexcludebodyarray[] = $rule[
'rulevalue'];
1485 array_push($criteria, array(
"BODY" => $rule[
'rulevalue']));
1488 if ($rule[
'type'] ==
'header') {
1489 array_push($criteria, array($not.
"HEADER" => $rule[
'rulevalue']));
1501 if ($rule[
'type'] ==
'seen') {
1502 array_push($criteria, array($not.
"SEEN"));
1504 if ($rule[
'type'] ==
'unseen') {
1505 array_push($criteria, array($not.
"UNSEEN"));
1507 if ($rule[
'type'] ==
'unanswered') {
1508 array_push($criteria, array($not.
"UNANSWERED"));
1510 if ($rule[
'type'] ==
'answered') {
1511 array_push($criteria, array($not.
"ANSWERED"));
1513 if ($rule[
'type'] ==
'smaller') {
1514 array_push($criteria, array($not.
"SMALLER"));
1516 if ($rule[
'type'] ==
'larger') {
1517 array_push($criteria, array($not.
"LARGER"));
1521 if ($rule[
'type'] ==
'withtrackingidinmsgid') {
1522 $searchfilterdoltrackid++;
1523 $searchhead .=
'/Message-ID.*@'.preg_quote($host,
'/').
'/';
1525 if ($rule[
'type'] ==
'withouttrackingidinmsgid') {
1526 $searchfilterdoltrackid++;
1527 $searchhead .=
'/Message-ID.*@'.preg_quote($host,
'/').
'/';
1529 if ($rule[
'type'] ==
'withtrackingid') {
1530 $searchfilterdoltrackid++;
1531 $searchhead .=
'/References.*@'.preg_quote($host,
'/').
'/';
1533 if ($rule[
'type'] ==
'withouttrackingid') {
1534 $searchfilternodoltrackid++;
1535 $searchhead .=
'! /References.*@'.preg_quote($host,
'/').
'/';
1538 if ($rule[
'type'] ==
'isanswer') {
1539 $searchfilterisanswer++;
1540 $searchhead .=
'/References.*@.*/';
1542 if ($rule[
'type'] ==
'isnotanswer') {
1543 $searchfilterisnotanswer++;
1544 $searchhead .=
'! /References.*@.*/';
1547 if ($rule[
'type'] ==
'replyto') {
1548 $searchfilterreplyto++;
1549 $rulesreplyto[] = $rule[
'rulevalue'];
1550 $searchhead .=
'/Reply-To.*'.preg_quote($rule[
'rulevalue'],
'/').
'/';
1554 if (empty($targetdir) || !
getDolGlobalString(
'EMAILCOLLECTOR_NO_FILTER_ON_DATE_IF_THERE_IS_A_TARGETDIR')) {
1556 if ($this->datelastok) {
1557 $fromdate = $this->datelastok;
1559 if ($fromdate > 0) {
1561 array_push($criteria, array(
"SINCE" =>
date(
'j-M-Y', $fromdate - 86400)));
1567 $search = var_export($criteria,
true);
1570 $search =
'UNDELETED';
1571 foreach ($this->filters as $rule) {
1572 if (empty($rule[
'status'])) {
1580 if (!empty($rule[
'rulevalue']) && strpos($rule[
'rulevalue'],
'!') === 0) {
1584 $rule[
'rulevalue'] = substr($rule[
'rulevalue'], 1);
1587 if ($rule[
'type'] ==
'excludeemail') {
1588 $tmpvalues = preg_split(
'/[\\r\\n,;]+/', (
string) $rule[
'rulevalue']);
1589 if (is_array($tmpvalues)) {
1590 foreach ($tmpvalues as $tmpvalue) {
1591 $tmpvalue = trim((
string) $tmpvalue);
1592 if ($tmpvalue ===
'') {
1596 if (preg_match_all(
'/[a-z0-9._%+\\-]+@[a-z0-9.\\-]+\\.[a-z]{2,}/i', $tmpvalue, $tmpmatches)) {
1597 foreach ($tmpmatches[0] as $tmpemail) {
1598 $tmpemail = strtolower(trim($tmpemail));
1599 if ($tmpemail !==
'') {
1600 $searchfilterexcludeemailarray[] = $tmpemail;
1608 if ($rule[
'type'] ==
'excludedomain') {
1609 $tmpvalues = preg_split(
'/[\\r\\n,;]+/', (
string) $rule[
'rulevalue']);
1610 if (is_array($tmpvalues)) {
1611 foreach ($tmpvalues as $tmpvalue) {
1612 $tmpvalue = trim((
string) $tmpvalue);
1613 if ($tmpvalue ===
'') {
1617 if (preg_match_all(
'/[a-z0-9._%+\\-]+@([a-z0-9.\\-]+\\.[a-z]{2,})/i', $tmpvalue, $tmpmatches)) {
1618 foreach ($tmpmatches[1] as $tmpdomain) {
1619 $tmpdomain = strtolower(trim($tmpdomain));
1620 $tmpdomain = trim($tmpdomain,
". \t\n\r\0\x0B");
1621 if ($tmpdomain !==
'') {
1622 $searchfilterexcludedomainarray[] = $tmpdomain;
1628 $tmpdomain = strtolower($tmpvalue);
1629 $tmpdomain = preg_replace(
'/^mailto:/i',
'', $tmpdomain);
1630 $tmpdomain = trim($tmpdomain);
1631 $tmpdomain = trim($tmpdomain,
"<> \t\n\r\0\x0B.,;");
1632 if (strpos($tmpdomain,
'@') === 0) {
1633 $tmpdomain = substr($tmpdomain, 1);
1635 $posat = strrpos($tmpdomain,
'@');
1636 if ($posat !==
false) {
1637 $tmpdomain = substr($tmpdomain, $posat + 1);
1639 $tmpdomain = trim($tmpdomain,
". \t\n\r\0\x0B");
1640 if ($tmpdomain !==
'') {
1641 $searchfilterexcludedomainarray[] = $tmpdomain;
1648 if ($rule[
'type'] ==
'from') {
1649 $tmprulevaluearray = explode(
'*', $rule[
'rulevalue']);
1650 if (count($tmprulevaluearray) >= 2) {
1651 foreach ($tmprulevaluearray as $tmprulevalue) {
1652 $search .= ($search ?
' ' :
'').$not.
'FROM "'.str_replace(
'"',
'', $tmprulevalue).
'"';
1655 $search .= ($search ?
' ' :
'').$not.
'FROM "'.str_replace(
'"',
'', $rule[
'rulevalue']).
'"';
1658 if ($rule[
'type'] ==
'to') {
1659 $tmprulevaluearray = explode(
'*', $rule[
'rulevalue']);
1660 if (count($tmprulevaluearray) >= 2) {
1661 foreach ($tmprulevaluearray as $tmprulevalue) {
1662 $search .= ($search ?
' ' :
'').$not.
'TO "'.str_replace(
'"',
'', $tmprulevalue).
'"';
1665 $search .= ($search ?
' ' :
'').$not.
'TO "'.str_replace(
'"',
'', $rule[
'rulevalue']).
'"';
1668 if ($rule[
'type'] ==
'bcc') {
1669 $search .= ($search ?
' ' :
'').$not.
'BCC';
1671 if ($rule[
'type'] ==
'cc') {
1672 $search .= ($search ?
' ' :
'').$not.
'CC';
1674 if ($rule[
'type'] ==
'subject') {
1677 $searchfilterexcludesubjectarray[] = $rule[
'rulevalue'];
1679 $search .= ($search ?
' ' :
'').
'SUBJECT "'.str_replace(
'"',
'', $rule[
'rulevalue']).
'"';
1682 if ($rule[
'type'] ==
'body') {
1685 $searchfilterexcludebodyarray[] = $rule[
'rulevalue'];
1688 $search .= ($search ?
' ' :
'').
'BODY "'.str_replace(
'"',
'', $rule[
'rulevalue']).
'"';
1691 if ($rule[
'type'] ==
'header') {
1692 $search .= ($search ?
' ' :
'').$not.
'HEADER '.$rule[
'rulevalue'];
1704 if ($rule[
'type'] ==
'seen') {
1705 $search .= ($search ?
' ' :
'').$not.
'SEEN';
1707 if ($rule[
'type'] ==
'unseen') {
1708 $search .= ($search ?
' ' :
'').$not.
'UNSEEN';
1710 if ($rule[
'type'] ==
'unanswered') {
1711 $search .= ($search ?
' ' :
'').$not.
'UNANSWERED';
1713 if ($rule[
'type'] ==
'answered') {
1714 $search .= ($search ?
' ' :
'').$not.
'ANSWERED';
1716 if ($rule[
'type'] ==
'smaller') {
1717 $search .= ($search ?
' ' :
'').$not.
'SMALLER "'.str_replace(
'"',
'', $rule[
'rulevalue']).
'"';
1719 if ($rule[
'type'] ==
'larger') {
1720 $search .= ($search ?
' ' :
'').$not.
'LARGER "'.str_replace(
'"',
'', $rule[
'rulevalue']).
'"';
1724 if ($rule[
'type'] ==
'withtrackingidinmsgid') {
1725 $searchfilterdoltrackid++;
1726 $searchhead .=
'/Message-ID.*@'.preg_quote($host,
'/').
'/';
1728 if ($rule[
'type'] ==
'withouttrackingidinmsgid') {
1729 $searchfilterdoltrackid++;
1730 $searchhead .=
'/Message-ID.*@'.preg_quote($host,
'/').
'/';
1732 if ($rule[
'type'] ==
'withtrackingid') {
1733 $searchfilterdoltrackid++;
1734 $searchhead .=
'/References.*@'.preg_quote($host,
'/').
'/';
1736 if ($rule[
'type'] ==
'withouttrackingid') {
1737 $searchfilternodoltrackid++;
1738 $searchhead .=
'! /References.*@'.preg_quote($host,
'/').
'/';
1741 if ($rule[
'type'] ==
'isanswer') {
1742 $searchfilterisanswer++;
1743 $searchhead .=
'/References.*@.*/';
1745 if ($rule[
'type'] ==
'isnotanswer') {
1746 $searchfilterisnotanswer++;
1747 $searchhead .=
'! /References.*@.*/';
1750 if ($rule[
'type'] ==
'replyto') {
1751 $searchfilterreplyto++;
1752 $rulesreplyto[] = $rule[
'rulevalue'];
1753 $searchhead .=
'/Reply-To.*'.preg_quote($rule[
'rulevalue'],
'/').
'/';
1757 if (empty($targetdir)) {
1759 if ($this->datelastok) {
1760 $fromdate = $this->datelastok;
1762 if ($fromdate > 0) {
1764 $search .= ($search ?
' ' :
'').
'SINCE '.
date(
'j-M-Y', $fromdate - 86400);
1772 if (!empty($searchfilterexcludeemailarray)) {
1773 $searchfilterexcludeemailarray = array_values(array_filter(array_unique($searchfilterexcludeemailarray)));
1774 $searchfilterexcludeemailmap = array_fill_keys($searchfilterexcludeemailarray,
true);
1776 if (!empty($searchfilterexcludedomainarray)) {
1777 $searchfilterexcludedomainarray = array_values(array_filter(array_unique($searchfilterexcludedomainarray)));
1780 $nbemailprocessed = 0;
1783 $charset = ($this->hostcharset ? $this->hostcharset :
"UTF-8");
1784 $arrayofemail = array();
1793 $tmpsourcedir = $sourcedir;
1798 $f = $client->getFolders(
false, $tmpsourcedir);
1805 foreach ($f as $candidate) {
1806 if ($candidate instanceof Webklex\PHPIMAP\Folder && $candidate->full_name === $tmpsourcedir) {
1807 $folder = $candidate;
1811 if ($folder instanceof Webklex\PHPIMAP\Folder) {
1812 $Query = $folder->messages()->where($criteria);
1816 $this->error =
"Failed to execute getfolders";
1817 $this->errors[] = $this->error;
1818 dol_syslog(
"EmailCollector::doCollectOneCollector ".$this->error, LOG_ERR);
1821 }
catch (InvalidWhereQueryCriteriaException $e) {
1822 $this->error = $e->getMessage();
1823 $this->errors[] = $this->error;
1824 dol_syslog(
"EmailCollector::doCollectOneCollector ".$this->error, LOG_ERR);
1827 $this->error = $e->getMessage();
1828 $this->errors[] = $this->error;
1829 dol_syslog(
"EmailCollector::doCollectOneCollector ".$this->error, LOG_ERR);
1834 if (empty($Query)) {
1836 $this->error =
"Source directory ".$sourcedir.
" not found";
1837 $this->errors[] = $this->error;
1838 dol_syslog(
"EmailCollector::doCollectOneCollector ".$this->error, LOG_WARNING);
1842 '@phan-var-force Webklex\PHPIMAP\Query\Query $Query';
1845 $Query->leaveUnread();
1847 $arrayofemail = $Query->limit($this->maxemailpercollect)->setFetchOrder(
"asc")->get();
1848 dol_syslog(
"EmailCollector::doCollectOneCollector nb arrayofemail ".(is_array($arrayofemail) ? count($arrayofemail) :
'Not array'));
1850 $this->error = $e->getMessage();
1851 $this->errors[] = $this->error;
1852 dol_syslog(
"EmailCollector::doCollectOneCollector ".$this->error, LOG_ERR);
1855 } elseif ($connection !==
false) {
1857 $arrayofemail = imap_search($connection, $search, SE_UID, $charset);
1859 if ($arrayofemail ===
false) {
1861 $mapoferrrors = imap_errors();
1862 if ($mapoferrrors !==
false) {
1864 $this->error =
"Search string not understood - ".implode(
',', $mapoferrrors);
1865 $this->errors[] = $this->error;
1870 $arrayofemailtodelete = array();
1873 if (!$error && !empty($arrayofemail) && count($arrayofemail) > 0 && $connection !==
false) {
1890 dol_syslog(
"Start of loop on email", LOG_INFO, 1);
1892 $richarrayofemail = array();
1894 foreach ($arrayofemail as $imapemail) {
1895 if ($nbemailprocessed > 1000) {
1901 '@phan-var-force Webklex\PHPIMAP\Message $imapemail';
1902 $header = $imapemail->getHeader()->raw;
1903 $overview = $imapemail->getAttributes();
1905 $header = imap_fetchheader($connection, $imapemail, FT_UID);
1906 $overview = imap_fetch_overview($connection, $imapemail, FT_UID);
1909 $header = preg_replace(
'/\r\n\s+/m',
' ', $header);
1912 preg_match_all(
'/([^: ]+): (.+?(?:\r\n\s(?:.+?))*)(\r\n|\s$)/m', $header, $matches);
1913 $headers = array_combine($matches[1], $matches[2]);
1916 $richarrayofemail[] = array(
'imapemail' => $imapemail,
'header' => $header,
'headers' => $headers,
'overview' => $overview,
'date' => empty($headers[
'Date']) ?
false : strtotime($headers[
'Date']));
1921 $richarrayofemail =
dol_sort_array($richarrayofemail,
'date',
'asc');
1925 foreach ($richarrayofemail as $tmpval) {
1928 $imapemail = $tmpval[
'imapemail'];
1929 $header = $tmpval[
'header'];
1930 $overview = $tmpval[
'overview'];
1931 $headers = $tmpval[
'headers'];
1933 if (!empty($headers[
'in-reply-to']) && empty($headers[
'In-Reply-To'])) {
1934 $headers[
'In-Reply-To'] = $headers[
'in-reply-to'];
1936 if (!empty($headers[
'references']) && empty($headers[
'References'])) {
1937 $headers[
'References'] = $headers[
'references'];
1939 if (!empty($headers[
'message-id']) && empty($headers[
'Message-ID'])) {
1940 $headers[
'Message-ID'] = $headers[
'message-id'];
1942 if (!empty($headers[
'subject']) && empty($headers[
'Subject'])) {
1943 $headers[
'Subject'] = $headers[
'subject'];
1949 $emailto = (
string) $overview[
'to'];
1954 $operationslog .=
'<br>** Process email #'.dol_escape_htmltag((
string) $iforemailloop);
1958 '@phan-var-force Webklex\PHPIMAP\Message $imapemail';
1960 $msgid = str_replace(array(
'<',
'>'),
'', $overview[
'message_id']);
1962 $operationslog .=
" - ".dol_escape_htmltag((
string) $imapemail);
1963 $msgid = str_replace(array(
'<',
'>'),
'', $overview[0]->message_id);
1965 $operationslog .=
" - MsgId: ".$msgid;
1966 $operationslog .=
" - Date: ".($headers[
'Date'] ?? $langs->transnoentitiesnoconv(
"NotFound"));
1967 $operationslog .=
" - References: ".dol_escape_htmltag($headers[
'References'] ?? $langs->transnoentitiesnoconv(
"NotFound")).
" - Subject: ".
dol_escape_htmltag($headers[
'Subject']);
1969 dol_syslog(
"-- Process email #".$iforemailloop.
", MsgId: ".$msgid.
", Date: ".($headers[
'Date'] ??
'').
", References: ".($headers[
'References'] ??
'').
", Subject: ".$headers[
'Subject']);
1972 $trackidfoundintorecipienttype =
'';
1973 $trackidfoundintorecipientid = 0;
1978 if (preg_match(
'/\+(th[i]|ctc|use|mem|sub|proj|tas|con|tic|pro|ord|inv|spro|sor|sin|leav|stockinv|job|surv|salary)([0-9]+)@/', $emailto, $reg)) {
1979 $trackidfoundintorecipienttype = $reg[1];
1980 $trackidfoundintorecipientid = $reg[2];
1981 } elseif (preg_match(
'/\+emailing-(\w+)@/', $emailto, $reg)) {
1982 $trackidfoundintorecipienttype =
'emailing';
1983 $trackidfoundintorecipientid = $reg[1];
1986 $trackidfoundintomsgidtype =
'';
1987 $trackidfoundintomsgidid = 0;
1992 if (preg_match(
'/(?:[\+\-])(th[i]|ctc|use|mem|sub|proj|tas|con|tic|pro|ord|inv|spro|sor|sin|leav|stockinv|job|surv|salary)([0-9]+)@/', $msgid, $reg)) {
1993 $trackidfoundintomsgidtype = $reg[1];
1994 $trackidfoundintomsgidid = $reg[2];
1995 } elseif (preg_match(
'/(?:[\+\-])emailing-(\w+)@/', $msgid, $reg)) {
1996 $trackidfoundintomsgidtype =
'emailing';
1997 $trackidfoundintomsgidid = $reg[1];
2003 if ($searchfilterdoltrackid > 0) {
2004 $referencesForFilter = $headers[
'References'] ??
'';
2005 if (!empty($headers[
'References']) && !empty($headers[
'In-Reply-To'])) {
2006 $referencesForFilter .=
' ';
2008 $referencesForFilter .= ($headers[
'In-Reply-To'] ??
'');
2010 if (empty($trackidfoundintorecipienttype) && empty($trackidfoundintomsgidtype)) {
2011 if (empty($referencesForFilter) || !preg_match(
'/@'.preg_quote($host,
'/').
'/', $referencesForFilter)) {
2012 $nbemailprocessed++;
2013 dol_syslog(
" Discarded - No suffix in email recipient, and no Header 'References/In-Reply-To' found matching the signature of the application, so with a trackid coming from the application");
2019 if ($searchfilternodoltrackid > 0) {
2020 $referencesForFilter = $headers[
'References'] ??
'';
2021 if (!empty($headers[
'References']) && !empty($headers[
'In-Reply-To'])) {
2022 $referencesForFilter .=
' ';
2024 $referencesForFilter .= ($headers[
'In-Reply-To'] ??
'');
2026 if (!empty($trackidfoundintorecipienttype) || !empty($trackidfoundintomsgidtype) || (!empty($referencesForFilter) && preg_match(
'/@'.preg_quote($host,
'/').
'/', $referencesForFilter))) {
2027 $nbemailprocessed++;
2028 dol_syslog(
" Discarded - Suffix found into email recipient, or Header 'References/In-Reply-To' found and matching signature of application so with a trackid");
2033 if ($searchfilterisanswer > 0) {
2034 $referencesforanswer =
'';
2035 if (!empty($headers[
'References'])) {
2036 $referencesforanswer .= $headers[
'References'].
' ';
2038 if (!empty($headers[
'In-Reply-To'])) {
2039 $referencesforanswer .= $headers[
'In-Reply-To'];
2042 $hasdolibarrreference = 0;
2043 if (!empty($referencesforanswer)) {
2044 if (preg_match(
'/dolibarr-([a-z]+)([0-9]+)@'.preg_quote($host,
'/').
'/', $referencesforanswer)) {
2045 $hasdolibarrreference = 1;
2047 if (preg_match(
'/dolibarr-([a-z]+)([0-9]+)@'.preg_quote(
getDolGlobalString(
'EMAIL_ALTERNATIVE_HOST_SIGNATURE'),
'/').
'/', $referencesforanswer)) {
2048 $hasdolibarrreference = 1;
2054 if (preg_match(
'/^(回复|回覆|SV|Antw|VS|RE|Re|AW|Aw|ΑΠ|השב| תשובה | הועבר|Vá|R|RIF|BLS|Atb|RES|Odp|பதில்|YNT|ATB)\s*:\s+/i', $headers[
'Subject'])) {
2060 if (!empty($headers[
'In-Reply-To'])) {
2064 if ($hasdolibarrreference) {
2071 $nbemailprocessed++;
2072 dol_syslog(
" Discarded - Email is not an answer (no reply marker detected, and test on In-Reply-To not requested because not reliable, or test on In-Reply-To requested but not found)");
2076 if ($searchfilterisnotanswer > 0) {
2080 if (preg_match(
'/^(回复|回覆|SV|Antw|VS|RE|Re|AW|Aw|ΑΠ|השב| תשובה | הועבר|Vá|R|RIF|BLS|Atb|RES|Odp|பதில்|YNT|ATB)\s*:\s+/i', $headers[
'Subject'])) {
2085 if (!$isanswer &&
getDolGlobalInt(
'EMAILCOLLECTOR_ISNOTANSWER_USE_REFERENCES') && !empty($headers[
'References'])) {
2088 if (!$isanswer &&
getDolGlobalString(
'EMAILCOLLECTOR_USE_IN_REPLY_TO_TO_DETECT_ANSWERS')) {
2089 if (!empty($headers[
'In-Reply-To'])) {
2096 $nbemailprocessed++;
2097 dol_syslog(
" Discarded - Email is an answer");
2101 if ($searchfilterreplyto > 0) {
2102 if (!empty($headers[
'Reply-To'])) {
2104 foreach ($rulesreplyto as $key => $rulereplyto) {
2105 if (preg_match(
'/'.preg_quote($rulereplyto,
'/').
'/', $headers[
'Reply-To'])) {
2110 if (!$isreplytook || $isreplytook != count($rulesreplyto)) {
2111 $nbemailprocessed++;
2112 dol_syslog(
" Discarded - Reply-to does not match");
2120 $thirdpartystatic =
new Societe($this->db);
2121 $contactstatic =
new Contact($this->db);
2122 $projectstatic =
new Project($this->db);
2124 $nbactiondoneforemail = 0;
2126 $errorforactions = 0;
2127 $thirdpartyfoundby =
'';
2128 $contactfoundby =
'';
2129 $projectfoundby =
'';
2130 $ticketfoundby =
'';
2131 $candidaturefoundby =
'';
2135 $dateformated =
dol_print_date($overview[
'date'],
'dayrfc',
'gmt');
2136 dol_syslog(
"msgid=".$overview[
'message_id'].
" date=".$dateformated.
" from=".$overview[
'from'].
" to=".$overview[
'to'].
" subject=".$overview[
'subject']);
2141 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);
2151 global $htmlmsg, $plainmsg, $charset, $attachments;
2155 '@phan-var-force Webklex\PHPIMAP\Message $imapemail';
2158 $htmlmsg = $plainmsg =
'';
2159 $attachments = array();
2161 if ($imapemail->hasHTMLBody()) {
2162 $htmlmsg = $imapemail->getHTMLBody();
2164 if ($imapemail->hasTextBody() && $imapemail->getTextBody() !=
"\n") {
2165 $plainmsg = $imapemail->getTextBody();
2167 if ($imapemail->hasAttachments()) {
2168 $attachments = $imapemail->getAttachments()->all();
2170 $attachments = array();
2173 $getMsg = $this->
getmsg($connection, $imapemail);
2175 $this->errors = array_merge($this->errors, [$this->error]);
2179 '@phan-var-force Webklex\PHPIMAP\Attachment[] $attachments';
2189 $operationslog .=
'<br>Discarded - Email body is not valid utf8';
2190 dol_syslog(
" Discarded - Email body is not valid utf8");
2194 if (!empty($searchfilterexcludebodyarray)) {
2195 foreach ($searchfilterexcludebodyarray as $searchfilterexcludebody) {
2196 if (preg_match(
'/'.preg_quote($searchfilterexcludebody,
'/').
'/ms', $messagetext)) {
2197 $nbemailprocessed++;
2198 $operationslog .=
'<br>Discarded - Email body contains string '.$searchfilterexcludebody;
2199 dol_syslog(
" Discarded - Email body contains string ".$searchfilterexcludebody);
2241 $replytostring =
'';
2245 $replytostring = !empty($headers[
'Reply-To']) ? $this->
decodeSMTPSubject($headers[
'Reply-To']) :
'';
2252 $tmpdate = $overview[
'date']->toDate();
2253 $tmptimezone = $tmpdate->getTimezone()->getName();
2256 if (preg_match(
'/^([+\-])(\d\d):(\d\d)/', $tmptimezone, $reg)) {
2257 if ($reg[1] ==
'+' && ($reg[2] !=
'00' || $reg[3] !=
'00')) {
2258 $dateemail -= (3600 * (int) $reg[2]);
2259 $dateemail -= (60 * (int) $reg[3]);
2261 if ($reg[1] ==
'-' && ($reg[2] !=
'00' || $reg[3] !=
'00')) {
2262 $dateemail += (3600 * (int) $reg[2]);
2263 $dateemail += (60 * (int) $reg[3]);
2268 $fromstring = (
string) $overview[0]->from;
2269 $replytostring = (!empty($overview[
'in_reply-to']) ? $overview[
'in_reply-to'] : (!empty($headers[
'Reply-To']) ? $headers[
'Reply-To'] :
"")) ;
2271 $sender = !empty($overview[0]->sender) ? $overview[0]->sender :
'';
2272 $to = $overview[0]->to;
2273 $sendtocc = !empty($overview[0]->cc) ? $overview[0]->cc :
'';
2274 $sendtobcc = !empty($overview[0]->bcc) ? $overview[0]->bcc :
'';
2276 $subject = (
string) $overview[0]->subject;
2279 if (!empty($searchfilterexcludesubjectarray)) {
2280 foreach ($searchfilterexcludesubjectarray as $searchfilterexcludesubject) {
2281 if (preg_match(
'/'.preg_quote($searchfilterexcludesubject,
'/').
'/ms', $subject)) {
2282 $nbemailprocessed++;
2283 $operationslog .=
'<br>Discarded - Email subject contains string '.$searchfilterexcludesubject;
2284 dol_syslog(
" Discarded - Email subject contains string ".$searchfilterexcludesubject);
2291 if (preg_match(
'/^(.*)<(.*)>$/', $fromstring, $reg)) {
2292 $email_from = $reg[2];
2293 $fromtext = $reg[1];
2295 $email_from = $fromstring;
2298 if (preg_match(
'/^(.*)<(.*)>$/', $replytostring, $reg)) {
2300 $replytotext = $reg[1];
2302 $replyto = $replytostring;
2306 if (!empty($searchfilterexcludeemailmap) || !empty($searchfilterexcludedomainarray)) {
2307 $emailsToCheck = array();
2308 $tmpaddressblob = trim($fromstring.
' '.$replytostring);
2309 if ($tmpaddressblob !==
'' && preg_match_all(
'/[a-z0-9._%+\\-]+@[a-z0-9.\\-]+\\.[a-z]{2,}/i', $tmpaddressblob, $tmpmatches)) {
2310 foreach ($tmpmatches[0] as $tmpEmail) {
2311 $tmpEmail = strtolower(trim($tmpEmail));
2312 if ($tmpEmail !==
'') {
2313 $emailsToCheck[$tmpEmail] =
true;
2318 if (empty($emailsToCheck)) {
2319 foreach (array($email_from, $replyto) as $tmpEmail) {
2320 $tmpEmail = strtolower(trim((
string) $tmpEmail));
2321 if ($tmpEmail !==
'' && strpos($tmpEmail,
'@') !==
false) {
2322 $emailsToCheck[$tmpEmail] =
true;
2328 $discardDomain =
'';
2329 $matchedDomainRule =
'';
2331 foreach (array_keys($emailsToCheck) as $tmpEmail) {
2332 if (!empty($searchfilterexcludeemailmap[$tmpEmail])) {
2333 $discardEmail = $tmpEmail;
2337 if (!empty($searchfilterexcludedomainarray)) {
2338 $posat = strrpos($tmpEmail,
'@');
2339 if ($posat ===
false) {
2342 $tmpDomain = strtolower(substr($tmpEmail, $posat + 1));
2343 foreach ($searchfilterexcludedomainarray as $excludedDomain) {
2344 if ($excludedDomain ===
'') {
2347 if ($tmpDomain === $excludedDomain || substr($tmpDomain, -strlen(
'.'.$excludedDomain)) ===
'.'.$excludedDomain) {
2348 $discardDomain = $tmpDomain;
2349 $matchedDomainRule = $excludedDomain;
2356 if ($discardEmail !==
'' || $discardDomain !==
'') {
2357 $nbemailprocessed++;
2358 if ($discardEmail !==
'') {
2359 $operationslog .=
'<br>Discarded - Sender email excluded: '.$discardEmail;
2360 dol_syslog(
" Discarded - Sender email excluded: ".$discardEmail);
2362 $operationslog .=
'<br>Discarded - Sender domain excluded: '.$discardDomain.($matchedDomainRule !==
'' && $matchedDomainRule !== $discardDomain ?
' (matched '.$matchedDomainRule.
')' :
'');
2363 dol_syslog(
" Discarded - Sender domain excluded: ".$discardDomain.($matchedDomainRule !==
'' && $matchedDomainRule !== $discardDomain ?
" (matched ".$matchedDomainRule.
")" :
""));
2370 $fk_element_type =
'';
2387 $objectemail =
null;
2390 $arrayofreferences = array();
2391 if (!empty($headers[
'References'])) {
2392 $arrayofreferences = preg_split(
'/(,|\s+)/', $headers[
'References']);
2394 if (!in_array(
'<'.$msgid.
'>', $arrayofreferences)) {
2395 $arrayofreferences = array_merge($arrayofreferences, array(
'<'.$msgid.
'>'));
2400 foreach ($arrayofreferences as $reference) {
2402 if (!empty($trackidfoundintorecipienttype)) {
2403 $resultsearchtrackid = -1;
2404 $reg[1] = $trackidfoundintorecipienttype;
2405 $reg[2] = $trackidfoundintorecipientid;
2406 } elseif (!empty($trackidfoundintomsgidtype)) {
2407 $resultsearchtrackid = -1;
2408 $reg[1] = $trackidfoundintomsgidtype;
2409 $reg[2] = $trackidfoundintomsgidid;
2411 $resultsearchtrackid = preg_match(
'/dolibarr-([a-z]+)([0-9]+)@'.preg_quote($host,
'/').
'/', $reference, $reg);
2412 if (empty($resultsearchtrackid) &&
getDolGlobalString(
'EMAIL_ALTERNATIVE_HOST_SIGNATURE')) {
2413 $resultsearchtrackid = preg_match(
'/dolibarr-([a-z]+)([0-9]+)@'.preg_quote(
getDolGlobalString(
'EMAIL_ALTERNATIVE_HOST_SIGNATURE'),
'/').
'/', $reference, $reg);
2417 if (!empty($resultsearchtrackid)) {
2419 $trackid = $reg[1].$reg[2];
2421 $objectid = $reg[2];
2423 if ($reg[1] ==
'thi') {
2424 $objectemail =
new Societe($this->db);
2426 if ($reg[1] ==
'ctc') {
2427 $objectemail =
new Contact($this->db);
2429 if ($reg[1] ==
'inv') {
2430 $objectemail =
new Facture($this->db);
2432 if ($reg[1] ==
'sinv') {
2435 if ($reg[1] ==
'pro') {
2436 $objectemail =
new Propal($this->db);
2438 if ($reg[1] ==
'ord') {
2439 $objectemail =
new Commande($this->db);
2441 if ($reg[1] ==
'shi') {
2444 if ($reg[1] ==
'spro') {
2447 if ($reg[1] ==
'sord') {
2450 if ($reg[1] ==
'rec') {
2451 $objectemail =
new Reception($this->db);
2453 if ($reg[1] ==
'proj') {
2454 $objectemail =
new Project($this->db);
2455 $projectfoundby =
'TrackID dolibarr-'.$trackid.
'@...';
2457 if ($reg[1] ==
'tas') {
2458 $objectemail =
new Task($this->db);
2460 if ($reg[1] ==
'con') {
2461 $objectemail =
new Contact($this->db);
2463 if ($reg[1] ==
'use') {
2464 $objectemail =
new User($this->db);
2466 if ($reg[1] ==
'tic') {
2467 $objectemail =
new Ticket($this->db);
2468 $ticketfoundby =
'TrackID dolibarr-'.$trackid.
'@...';
2470 if ($reg[1] ==
'recruitmentcandidature') {
2472 $candidaturefoundby =
'TrackID dolibarr-'.$trackid.
'@...';
2474 if ($reg[1] ==
'mem') {
2475 $objectemail =
new Adherent($this->db);
2483 } elseif (preg_match(
'/<(.*@.*)>/', $reference, $reg)) {
2486 $sql =
"SELECT rowid FROM ".MAIN_DB_PREFIX.
"ticket";
2487 $sql .=
" WHERE email_msgid = '".$this->db->escape($reg[1]).
"' OR origin_references LIKE '%".$this->db->escape($this->db->escapeforlike($reg[1])).
"%'";
2488 $resql = $this->db->query($sql);
2490 $obj = $this->db->fetch_object($resql);
2492 $objectid = $obj->rowid;
2493 $objectemail =
new Ticket($this->db);
2494 $ticketfoundby = $langs->transnoentitiesnoconv(
"EmailMsgID").
' ('.$reg[1].
')';
2501 if (!is_object($objectemail) &&
isModEnabled(
'project')) {
2502 $sql =
"SELECT rowid FROM ".MAIN_DB_PREFIX.
"projet where email_msgid = '".$this->db->escape($reg[1]).
"'";
2503 $resql = $this->db->query($sql);
2505 $obj = $this->db->fetch_object($resql);
2507 $objectid = $obj->rowid;
2508 $objectemail =
new Project($this->db);
2509 $projectfoundby = $langs->transnoentitiesnoconv(
"EmailMsgID").
' ('.$reg[1].
')';
2516 if (!is_object($objectemail) &&
isModEnabled(
'recruitment')) {
2517 $sql =
"SELECT rowid FROM ".MAIN_DB_PREFIX.
"recruitment_recruitmentcandidature where email_msgid = '".$this->db->escape($reg[1]).
"'";
2518 $resql = $this->db->query($sql);
2520 $obj = $this->db->fetch_object($resql);
2522 $objectid = $obj->rowid;
2524 $candidaturefoundby = $langs->transnoentitiesnoconv(
"EmailMsgID").
' ('.$reg[1].
')';
2533 if (is_object($objectemail)) {
2534 $result = $objectemail->fetch($objectid);
2536 $fk_element_id = $objectemail->id;
2537 $fk_element_type = $objectemail->element;
2539 if ($fk_element_type ==
'facture') {
2540 $fk_element_type =
'invoice';
2543 if (get_class($objectemail) !=
'Societe') {
2544 $thirdpartyid = $objectemail->fk_soc ?? $objectemail->socid;
2546 $thirdpartyid = $objectemail->id;
2549 if (get_class($objectemail) !=
'Contact') {
2550 $contactid = $objectemail->fk_socpeople;
2552 $contactid = $objectemail->id;
2555 if (get_class($objectemail) !=
'Project') {
2556 $projectid = isset($objectemail->fk_project) ? $objectemail->fk_project : $objectemail->fk_projet;
2558 $projectid = $objectemail->id;
2561 if ($objectemail instanceof
Ticket) {
2562 $ticketid = $objectemail->id;
2564 $changeonticket_references =
false;
2565 if (empty($trackid)) {
2566 $trackid = $objectemail->track_id;
2568 if (empty($objectemail->origin_references)) {
2569 $objectemail->origin_references = !empty($headers[
'References']) ? $headers[
'References'] :
null;
2570 $changeonticket_references =
true;
2572 foreach ($arrayofreferences as $key => $referencetmp) {
2573 if (!str_contains($objectemail->origin_references, $referencetmp)) {
2574 $objectemail->origin_references .=
" ".$referencetmp;
2575 $changeonticket_references =
true;
2579 if ($changeonticket_references) {
2580 $operationslog .=
'<br>We complete ticket ID='.$ticketid.
' with property origin_references='.$objectemail->origin_references;
2581 $objectemail->update($user, 1);
2588 if ($projectid > 0) {
2589 $result = $projectstatic->fetch($projectid);
2591 $projectstatic->id = 0;
2593 $projectid = $projectstatic->id;
2595 $projectfoundby =
'trackid ('.$trackid.
')';
2597 if (empty($contactid)) {
2598 $contactid = $projectstatic->fk_contact;
2600 if (empty($thirdpartyid)) {
2601 $thirdpartyid = $projectstatic->fk_soc;
2606 if ($contactid > 0) {
2607 $result = $contactstatic->fetch($contactid);
2609 $contactstatic->id = 0;
2611 $contactid = $contactstatic->id;
2613 $contactfoundby =
'trackid ('.$trackid.
')';
2615 if (empty($thirdpartyid)) {
2616 $thirdpartyid = $contactstatic->fk_soc;
2621 if ($thirdpartyid > 0) {
2622 $result = $thirdpartystatic->fetch($thirdpartyid);
2624 $thirdpartystatic->id = 0;
2626 $thirdpartyid = $thirdpartystatic->id;
2628 $thirdpartyfoundby =
'trackid ('.$trackid.
')';
2633 if (is_object($objectemail)) {
2638 if (empty($contactid)) {
2639 $result = $contactstatic->fetch(0,
null,
'', $email_from);
2642 dol_syslog(
"We found a contact with the email ".$email_from);
2643 $contactid = $contactstatic->id;
2644 $contactfoundby =
'email of contact ('.$email_from.
')';
2645 if (empty($thirdpartyid) && $contactstatic->socid > 0) {
2646 $result = $thirdpartystatic->fetch($contactstatic->socid);
2648 $thirdpartyid = $thirdpartystatic->id;
2649 $thirdpartyfoundby =
'email of contact ('.$email_from.
')';
2655 if (empty($thirdpartyid)) {
2656 $result = $thirdpartystatic->fetch(0,
'',
'',
'',
'',
'',
'',
'',
'',
'', $email_from);
2658 dol_syslog(
"We found a thirdparty with the email ".$email_from);
2659 $thirdpartyid = $thirdpartystatic->id;
2660 $thirdpartyfoundby =
'email ('.$email_from.
')';
2695 $savedattachments = array();
2696 $savedattachmentsdir =
'';
2697 $savedattachmentsnote =
'';
2698 if (empty($mode) && !empty($attachments) && $fk_element_id > 0 && $fk_element_type ===
'order_supplier' && $objectemail instanceof
CommandeFournisseur) {
2699 $orderref = isset($objectemail->ref) ? (
string) $objectemail->ref :
'';
2700 if ($orderref !==
'' && !empty(
$conf->fournisseur->commande)) {
2701 $entityforobject = isset($objectemail->entity) ? (int) $objectemail->entity : (int)
$conf->entity;
2702 $basedir = (!empty(
$conf->fournisseur->commande->multidir_output[$entityforobject]) ?
$conf->fournisseur->commande->multidir_output[$entityforobject] :
$conf->fournisseur->commande->dir_output);
2704 $savedattachments = $this->saveEmailCollectorAttachmentsToDir($savedattachmentsdir, $attachments);
2705 if (!empty($savedattachments)) {
2706 $operationslog .=
'<br>Saved '.count($savedattachments).
' attachment(s) into '.
dol_escape_htmltag($savedattachmentsdir);
2710 if (!empty($savedattachments)) {
2712 foreach ($savedattachments as $attmeta) {
2713 if (!is_array($attmeta) || empty($attmeta[
'name'])) {
2716 $names[] = (
string) $attmeta[
'name'];
2718 if (!empty($names)) {
2719 $savedattachmentsnote = $langs->trans(
"NbOfAttachedFiles").
' : '.count($names);
2720 $savedattachmentsnote .=
' ('.implode(
', ', array_slice($names, 0, 10)).(count($names) > 10 ?
'...' :
'').
')';
2727 foreach ($this->actions as $operation) {
2728 $errorforthisaction = 0;
2729 $ticketalreadyexists = 0;
2730 if ($errorforactions) {
2733 if (empty($operation[
'status'])) {
2737 $operationslog .=
'<br>* Process operation '.$operation[
'type'];
2740 dol_syslog(
"Execute action ".$operation[
'type'].
" actionparam=".$operation[
'actionparam'].
' thirdpartystatic->id='.$thirdpartystatic->id.
' contactstatic->id='.$contactstatic->id.
' projectstatic->id='.$projectstatic->id);
2741 dol_syslog(
"Execute action fk_element_id=".$fk_element_id.
" fk_element_type=".$fk_element_type);
2744 $actioncode =
'EMAIL_IN';
2746 if (preg_match(
'/Sent$/', $sourcedir) || preg_match(
'/envoyés$/i', $sourcedir)) {
2747 $actioncode =
'EMAIL';
2750 $arrayofemailtoconsidersender = array_filter(array_map(
'trim', explode(
',',
getDolGlobalString(
'MAIL_FROM_EMAILS_TO_CONSIDER_SENDING'))));
2751 foreach ($arrayofemailtoconsidersender as $emailtoconsidersender) {
2752 if ($emailtoconsidersender ===
'') {
2755 if (preg_match(
'/'.preg_quote($emailtoconsidersender,
'/').
'/', $fromstring)) {
2756 $actioncode =
'EMAIL';
2759 $operationslog .=
'<br>Email will have actioncode='.$actioncode;
2761 $description = $descriptiontitle = $descriptionmeta = $descriptionfull =
'';
2763 $descriptiontitle = $langs->transnoentitiesnoconv(
"RecordCreatedByEmailCollector", $this->
ref);
2768 $descriptionmeta =
dol_concatdesc($descriptionmeta, $langs->trans(
"MailFrom").($langs->trans(
"MailFrom") !=
'From' ?
' (From)' :
'').
' : '.
dol_escape_htmltag($fromstring));
2770 $descriptionmeta =
dol_concatdesc($descriptionmeta, $langs->trans(
"Sender").($langs->trans(
"Sender") !=
'Sender' ?
' (Sender)' :
'').
' : '.
dol_escape_htmltag($sender));
2772 $descriptionmeta =
dol_concatdesc($descriptionmeta, $langs->trans(
"MailTo").($langs->trans(
"MailTo") !=
'To' ?
' (To)' :
'').
' : '.
dol_escape_htmltag($to));
2774 $descriptionmeta =
dol_concatdesc($descriptionmeta, $langs->trans(
"MailReply").($langs->trans(
"MailReply") !=
'Reply to' ?
' (Reply to)' :
'').
' : '.
dol_escape_htmltag($replyto));
2777 $descriptionmeta =
dol_concatdesc($descriptionmeta, $langs->trans(
"MailCC").($langs->trans(
"MailCC") !=
'CC' ?
' (CC)' :
'').
' : '.
dol_escape_htmltag($sendtocc));
2779 if ($savedattachmentsnote) {
2780 $descriptionmeta =
dol_concatdesc($descriptionmeta, $savedattachmentsnote);
2783 if ($operation[
'type'] ==
'ticket') {
2785 $tickettocreate =
new Ticket($this->db);
2786 $errorfetchticket = 0;
2787 $alreadycreated = 0;
2788 if (!empty($objectid) && $objectemail instanceof
Ticket) {
2789 $alreadycreated = $tickettocreate->fetch((
int) $objectid);
2791 if ($alreadycreated == 0 && $ticketid > 0) {
2792 $alreadycreated = $tickettocreate->fetch($ticketid);
2794 if ($alreadycreated == 0 && !empty($trackid)) {
2795 $alreadycreated = $tickettocreate->fetch(0,
'', $trackid);
2797 if ($alreadycreated == 0 && !empty($msgid)) {
2798 $alreadycreated = $tickettocreate->fetch(0,
'',
'', $msgid);
2800 if ($alreadycreated < 0) {
2801 $errorfetchticket++;
2803 if (empty($errorfetchticket)) {
2804 if ($alreadycreated == 0) {
2805 $operationslog .=
'<br>Ticket not found using trackid='.$trackid.
' or msgid='.$msgid;
2806 $ticketalreadyexists = 0;
2808 $operationslog .=
'<br>Ticket already found using trackid='.$trackid.
' or msgid='.$msgid.
", we replace operation 'ticket' with 'recordevent' to add a new message";
2809 $ticketalreadyexists = 1;
2810 $operation[
'type'] =
'recordevent';
2813 $ticketalreadyexists = -1;
2820 if ($operation[
'type'] ==
'loadthirdparty' || $operation[
'type'] ==
'loadandcreatethirdparty') {
2821 if ($thirdpartyid > 0) {
2823 $idtouseforthirdparty = $thirdpartyid;
2824 $operationslog .=
'<br>We already have found a related thirdparty id, so we bypass the action loadthirdparty and use idtouseforthirdparty='.$idtouseforthirdparty;
2825 } elseif (empty($operation[
'actionparam'])) {
2827 $this->error =
"Action loadthirdparty or loadandcreatethirdparty has empty parameter. Must be a rule like 'name=HEADER:^From:(.*);' or 'name=SET:xxx' or 'name=EXTRACT:(body|subject):regex where 'name' can be replaced with 'id' or 'email' to define how to set or extract data. More properties can also be set, for example client=SET:2;";
2828 $this->errors[] = $this->error;
2830 $actionparam = $operation[
'actionparam'];
2831 $idtouseforthirdparty =
'';
2832 $nametouseforthirdparty =
'';
2833 $emailtouseforthirdparty =
'';
2834 $namealiastouseforthirdparty =
'';
2836 $operationslog .=
'<br>Loop on each property to set into actionparam';
2840 foreach ($arrayvaluetouse as $propertytooverwrite => $valueforproperty) {
2844 $regforregex = array();
2846 if (preg_match(
'/^EXTRACT:([a-zA-Z0-9_]+):(.*)$/', $valueforproperty, $regforregex)) {
2847 $sourcefield = $regforregex[1];
2848 $regexstring = $regforregex[2];
2851 if (!empty($sourcefield) && !empty($regexstring)) {
2852 if (strtolower($sourcefield) ==
'body') {
2853 $sourcestring = $messagetext;
2854 } elseif (strtolower($sourcefield) ==
'subject') {
2855 $sourcestring = $subject;
2856 } elseif (strtolower($sourcefield) ==
'header') {
2857 $sourcestring = $header;
2860 if ($sourcestring) {
2861 $regforval = array();
2862 if (preg_match(
'/'.$regexstring.
'/ms', $sourcestring, $regforval)) {
2864 if ($propertytooverwrite ==
'id') {
2865 $idtouseforthirdparty = isset($regforval[count($regforval) - 1]) ? trim($regforval[count($regforval) - 1]) : null;
2867 $operationslog .=
'<br>propertytooverwrite='.$propertytooverwrite.
' Regex /'.
dol_escape_htmltag($regexstring).
'/ms into '.strtoupper($sourcefield).
' -> Found idtouseforthirdparty='.
dol_escape_htmltag($idtouseforthirdparty);
2868 } elseif ($propertytooverwrite ==
'email') {
2869 $emailtouseforthirdparty = isset($regforval[count($regforval) - 1]) ? trim($regforval[count($regforval) - 1]) : null;
2871 $operationslog .=
'<br>propertytooverwrite='.$propertytooverwrite.
' Regex /'.
dol_escape_htmltag($regexstring).
'/ms into '.strtoupper($sourcefield).
' -> Found emailtouseforthirdparty='.
dol_escape_htmltag($emailtouseforthirdparty);
2872 } elseif ($propertytooverwrite ==
'name') {
2873 $nametouseforthirdparty = isset($regforval[count($regforval) - 1]) ? trim($regforval[count($regforval) - 1]) : null;
2875 $operationslog .=
'<br>propertytooverwrite='.$propertytooverwrite.
' Regex /'.
dol_escape_htmltag($regexstring).
'/ms into '.strtoupper($sourcefield).
' -> Found nametouseforthirdparty='.
dol_escape_htmltag($nametouseforthirdparty);
2876 } elseif ($propertytooverwrite ==
'name_alias') {
2877 $namealiastouseforthirdparty = isset($regforval[count($regforval) - 1]) ? trim($regforval[count($regforval) - 1]) : null;
2879 $operationslog .=
'<br>propertytooverwrite='.$propertytooverwrite.
' Regex /'.
dol_escape_htmltag($regexstring).
'/ms into '.strtoupper($sourcefield).
' -> Found namealiastouseforthirdparty='.
dol_escape_htmltag($namealiastouseforthirdparty);
2881 $operationslog .=
'<br>propertytooverwrite='.$propertytooverwrite.
' Regex /'.
dol_escape_htmltag($regexstring).
'/ms into '.strtoupper($sourcefield).
' -> We discard this, not a field used to search an existing thirdparty';
2885 if (in_array($propertytooverwrite, array(
'id',
'email',
'name',
'name_alias'))) {
2886 $idtouseforthirdparty =
null;
2887 $nametouseforthirdparty =
null;
2888 $emailtouseforthirdparty =
null;
2889 $namealiastouseforthirdparty =
null;
2891 $operationslog .=
'<br>propertytooverwrite='.$propertytooverwrite.
' Regex /'.
dol_escape_htmltag($regexstring).
'/ms into '.strtoupper($sourcefield).
' -> Not found. Property searched is critical so we cancel the search.';
2893 $operationslog .=
'<br>propertytooverwrite='.$propertytooverwrite.
' Regex /'.
dol_escape_htmltag($regexstring).
'/ms into '.strtoupper($sourcefield).
' -> Not found';
2899 $this->error =
'The extract rule to use to load thirdparty for email '.$msgid.
' has an unknown source (must be HEADER, SUBJECT or BODY)';
2900 $this->errors[] = $this->error;
2902 $operationslog .=
'<br>'.$this->error;
2904 } elseif (preg_match(
'/^(SET|SETIFEMPTY):(.*)$/', $valueforproperty, $reg)) {
2908 if ($propertytooverwrite ==
'id') {
2909 $idtouseforthirdparty = $reg[2];
2911 $operationslog .=
'<br>propertytooverwrite='.$propertytooverwrite.
' We set property idtouseforthrdparty='.
dol_escape_htmltag($idtouseforthirdparty);
2912 } elseif ($propertytooverwrite ==
'email') {
2913 $emailtouseforthirdparty = $reg[2];
2915 $operationslog .=
'<br>propertytooverwrite='.$propertytooverwrite.
' We set property emailtouseforthrdparty='.
dol_escape_htmltag($emailtouseforthirdparty);
2916 } elseif ($propertytooverwrite ==
'name') {
2917 $nametouseforthirdparty = $reg[2];
2919 $operationslog .=
'<br>propertytooverwrite='.$propertytooverwrite.
' We set property nametouseforthirdparty='.
dol_escape_htmltag($nametouseforthirdparty);
2920 } elseif ($propertytooverwrite ==
'name_alias') {
2921 $namealiastouseforthirdparty = $reg[2];
2923 $operationslog .=
'<br>propertytooverwrite='.$propertytooverwrite.
' We set property namealiastouseforthirdparty='.
dol_escape_htmltag($namealiastouseforthirdparty);
2927 $this->error =
'Bad syntax for description of action parameters: '.$actionparam;
2928 $this->errors[] = $this->error;
2933 if (!$errorforactions && ($idtouseforthirdparty || $emailtouseforthirdparty || $nametouseforthirdparty || $namealiastouseforthirdparty)) {
2935 $operationslog .=
'<br>We have this initial main data to search thirdparty: id='.$idtouseforthirdparty.
', email='.$emailtouseforthirdparty.
', name='.$nametouseforthirdparty.
', name_alias='.$namealiastouseforthirdparty.
'.';
2938 $tmpobject->element =
'generic';
2939 $tmpobject->id = $idtouseforthirdparty;
2940 $tmpobject->name = $nametouseforthirdparty;
2941 $tmpobject->name_alias = $namealiastouseforthirdparty;
2942 $tmpobject->email = $emailtouseforthirdparty;
2946 $idtouseforthirdparty = $tmpobject->id;
2947 $nametouseforthirdparty = $tmpobject->name;
2948 $namealiastouseforthirdparty = $tmpobject->name_alias;
2949 $emailtouseforthirdparty = $tmpobject->email;
2951 $operationslog .=
'<br>We try to search existing thirdparty with idtouseforthirdparty='.$idtouseforthirdparty.
' emailtouseforthirdparty='.$emailtouseforthirdparty.
' nametouseforthirdparty='.$nametouseforthirdparty.
' namealiastouseforthirdparty='.$namealiastouseforthirdparty;
2954 $result = $thirdpartystatic->findNearest((
int) $idtouseforthirdparty, (
string) $nametouseforthirdparty,
'',
'',
'',
'',
'',
'',
'',
'', (
string) $emailtouseforthirdparty, (
string) $namealiastouseforthirdparty);
2957 if (
getDolGlobalInt(
'EMAILCOLLECTOR_USE_THIS_THIRDPARTY_ID_IF_DUPLICATE') && $result == -2) {
2958 $idtouseforthirdparty =
getDolGlobalInt(
'EMAILCOLLECTOR_USE_THIS_THIRDPARTY_ID_IF_DUPLICATE');
2960 $thirdpartystatic->fetch($idtouseforthirdparty);
2962 dol_syslog(
'Thirdparty found twice (or more) so, according to option EMAILCOLLECTOR_USE_THIS_THIRDPARTY_ID_IF_DUPLICATE, we will use the generic one with id = '.
dol_escape_htmltag((
string) $thirdpartystatic->id).
" and name ".
dol_escape_htmltag($thirdpartystatic->name));
2964 $operationslog .=
'<br>Thirdparty found twice (or more) so, according to option EMAILCOLLECTOR_USE_THIS_THIRDPARTY_ID_IF_DUPLICATE, we will use the generic one with id = '.dol_escape_htmltag((
string) $thirdpartystatic->id).
" and name ".
dol_escape_htmltag($thirdpartystatic->name);
2967 $this->error =
'Error when getting thirdparty with name '.((string) $nametouseforthirdparty).
', alternative name '.((
string) $namealiastouseforthirdparty).
' and email '.$emailtouseforthirdparty.
' (may be 2 record exists with same name ?)';
2968 $this->errors[] = $this->error;
2973 if ($operation[
'type'] ==
'loadthirdparty') {
2974 dol_syslog(
"Third party with id=".$idtouseforthirdparty.
" email=".$emailtouseforthirdparty.
" name=".$nametouseforthirdparty.
" name_alias=".$namealiastouseforthirdparty.
" was not found");
2977 $resultContact = $contactstatic->findNearest(0,
'',
'',
'', (
string) $emailtouseforthirdparty,
'', 0);
2978 if ($resultContact > 0) {
2979 $contactstatic->fetch($resultContact);
2980 $idtouseforthirdparty = $contactstatic->socid;
2981 $result = $thirdpartystatic->fetch($idtouseforthirdparty);
2983 dol_syslog(
"Third party with id=".$idtouseforthirdparty.
" email=".$emailtouseforthirdparty.
" name=".$nametouseforthirdparty.
" name_alias=".$namealiastouseforthirdparty.
" was found thanks to linked contact search");
2986 $langs->load(
"errors");
2987 $this->error = $langs->trans(
'ErrorFailedToLoadThirdParty', (
string) $idtouseforthirdparty, (
string) $emailtouseforthirdparty, (
string) $nametouseforthirdparty, (
string) $namealiastouseforthirdparty);
2988 $this->errors[] = $this->error;
2992 $langs->load(
"errors");
2993 $this->error = $langs->trans(
'ErrorFailedToLoadThirdParty', (
string) $idtouseforthirdparty, (
string) $emailtouseforthirdparty, (
string) $nametouseforthirdparty, (
string) $namealiastouseforthirdparty);
2994 $this->errors[] = $this->error;
2996 } elseif ($operation[
'type'] ==
'loadandcreatethirdparty') {
2997 dol_syslog(
"Third party with id=".$idtouseforthirdparty.
" email=".$emailtouseforthirdparty.
" name=".$nametouseforthirdparty.
" name_alias=".$namealiastouseforthirdparty.
" was not found. We try to create it.");
3000 $thirdpartystatic =
new Societe($db);
3001 $thirdpartystatic->name = (
string) $nametouseforthirdparty;
3002 if (!empty($namealiastouseforthirdparty)) {
3003 if ($namealiastouseforthirdparty != $nametouseforthirdparty) {
3004 $thirdpartystatic->name_alias = $namealiastouseforthirdparty;
3007 $thirdpartystatic->name_alias = (empty($replytostring) ? (empty($fromtext) ?
'' : $fromtext) : $replytostring);
3009 $thirdpartystatic->email = (empty($emailtouseforthirdparty) ? (empty($replyto) ? (empty($email_from) ?
'' : $email_from) : $replyto) : $emailtouseforthirdparty);
3012 $errorforthisaction = $this->
overwritePropertiesOfObject($thirdpartystatic, $operation[
'actionparam'], $messagetext, $subject, $header, $operationslog);
3014 if ($thirdpartystatic->client && empty($thirdpartystatic->code_client)) {
3015 $thirdpartystatic->code_client =
'auto';
3017 if ($thirdpartystatic->fournisseur && empty($thirdpartystatic->code_fournisseur)) {
3018 $thirdpartystatic->code_fournisseur =
'auto';
3021 if ($errorforthisaction) {
3024 $result = $thirdpartystatic->create($user);
3027 $this->error = $thirdpartystatic->error;
3028 $this->errors = $thirdpartystatic->errors;
3030 $operationslog .=
'<br>Thirdparty created -> id = '.dol_escape_htmltag((
string) $thirdpartystatic->id);
3034 } elseif ($result > 0) {
3035 dol_syslog(
"One and only one existing third party has been found");
3037 $thirdpartystatic->fetch($result);
3039 $operationslog .=
'<br>Thirdparty already exists with id = '.dol_escape_htmltag((
string) $thirdpartystatic->id).
" and name ".
dol_escape_htmltag($thirdpartystatic->name);
3043 } elseif ($operation[
'type'] ==
'loadandcreatecontact') {
3044 if (empty($operation[
'actionparam'])) {
3046 $this->error =
"Action loadandcreatecontact has empty parameter. Must be 'SET:xxx' or 'EXTRACT:(body|subject):regex' to define how to extract data";
3047 $this->errors[] = $this->error;
3049 $contact_static =
new Contact($this->db);
3051 $errorforthisaction = $this->
overwritePropertiesOfObject($contact_static, $operation[
'actionparam'], $messagetext, $subject, $header, $operationslog);
3052 if ($errorforthisaction) {
3055 if (!empty($contact_static->email) && $contact_static->email != $email_from) {
3056 $email_from = $contact_static->email;
3058 $email_from = (
string) $email_from;
3060 $email_from = (
string) $email_from;
3062 $result = $contactstatic->fetch(0,
null,
'', $email_from);
3065 $this->error =
'Error when getting contact with email ' . $email_from;
3066 $this->errors[] = $this->error;
3068 } elseif ($result == 0) {
3069 dol_syslog(
"Contact with email " . $email_from .
" was not found. We try to create it.");
3070 $contactstatic =
new Contact($this->db);
3073 $contactstatic->email = $email_from;
3074 $operationslog .=
'<br>We set property email='.dol_escape_htmltag($email_from);
3077 $errorforthisaction = $this->
overwritePropertiesOfObject($contactstatic, $operation[
'actionparam'], $messagetext, $subject, $header, $operationslog);
3079 if ($errorforthisaction) {
3083 if (!empty($contactstatic->country)) {
3084 require_once DOL_DOCUMENT_ROOT .
'/core/lib/company.lib.php';
3085 $result =
getCountry(
'',
'3', $this->db,
null, 1, $contactstatic->country);
3086 if ($result ==
'NotDefined') {
3088 $this->error =
"Error country not found by this name '" . $contactstatic->country .
"'";
3089 } elseif (!($result > 0)) {
3091 $this->error =
"Error when search country by this name '" . $contactstatic->country .
"'";
3092 $this->errors[] = $this->db->lasterror();
3094 $contactstatic->country_id = $result;
3095 $operationslog .=
'<br>We set property country_id='.dol_escape_htmltag($result);
3097 } elseif (!empty($contactstatic->country_code)) {
3098 require_once DOL_DOCUMENT_ROOT .
'/core/lib/company.lib.php';
3099 $result =
getCountry($contactstatic->country_code,
'3', $this->db);
3100 if ($result ==
'NotDefined') {
3102 $this->error =
"Error country not found by this code '" . $contactstatic->country_code .
"'";
3103 } elseif (!($result > 0)) {
3105 $this->error =
"Error when search country by this code '" . $contactstatic->country_code .
"'";
3106 $this->errors[] = $this->db->lasterror();
3108 $contactstatic->country_id = $result;
3109 $operationslog .=
'<br>We set property country_id='.dol_escape_htmltag($result);
3113 if (!$errorforactions) {
3115 if (!empty($contactstatic->state)) {
3116 require_once DOL_DOCUMENT_ROOT .
'/core/lib/functions.lib.php';
3117 $result =
dol_getIdFromCode($this->db, $contactstatic->state,
'c_departements',
'nom',
'rowid');
3118 if (empty($result)) {
3120 $this->error =
"Error state not found by this name '" . $contactstatic->state .
"'";
3121 } elseif (!($result > 0)) {
3123 $this->error =
"Error when search state by this name '" . $contactstatic->state .
"'";
3124 $this->errors[] = $this->db->lasterror();
3126 $contactstatic->state_id = $result;
3127 $operationslog .=
'<br>We set property state_id='.dol_escape_htmltag($result);
3129 } elseif (!empty($contactstatic->state_code)) {
3130 require_once DOL_DOCUMENT_ROOT .
'/core/lib/functions.lib.php';
3131 $result =
dol_getIdFromCode($this->db, $contactstatic->state_code,
'c_departements',
'code_departement',
'rowid');
3132 if (empty($result)) {
3134 $this->error =
"Error state not found by this code '" . $contactstatic->state_code .
"'";
3135 } elseif (!($result > 0)) {
3137 $this->error =
"Error when search state by this code '" . $contactstatic->state_code .
"'";
3138 $this->errors[] = $this->db->lasterror();
3140 $contactstatic->state_id = $result;
3141 $operationslog .=
'<br>We set property state_id='.dol_escape_htmltag($result);
3146 if (!$errorforactions) {
3147 $result = $contactstatic->create($user);
3150 $this->error = $contactstatic->error;
3151 $this->errors = $contactstatic->errors;
3153 $operationslog .=
'<br>Contact created -> id = '.dol_escape_htmltag((
string) $contactstatic->id);
3160 } elseif ($operation[
'type'] ==
'recordevent') {
3164 $alreadycreated = $actioncomm->fetch(0,
'',
'', $msgid);
3165 if ($alreadycreated == 0) {
3166 $operationslog .=
'<br>We did not find existing actioncomm with msgid='.$msgid;
3168 if ($projectstatic->id > 0) {
3169 if ($projectfoundby) {
3170 $descriptionmeta =
dol_concatdesc($descriptionmeta,
'Project found from '.$projectfoundby);
3173 if ($thirdpartystatic->id > 0) {
3174 if ($thirdpartyfoundby) {
3175 $descriptionmeta =
dol_concatdesc($descriptionmeta,
'Third party found from '.$thirdpartyfoundby);
3178 if ($contactstatic->id > 0) {
3179 if ($contactfoundby) {
3180 $descriptionmeta =
dol_concatdesc($descriptionmeta,
'Contact/address found from '.$contactfoundby);
3184 $description = $descriptiontitle;
3190 $descriptionfull = $description;
3192 $descriptionfull =
dol_concatdesc($descriptionfull,
"----- Header");
3197 $actioncomm->type_code =
'AC_OTH_AUTO';
3198 $actioncomm->code =
'AC_'.$actioncode;
3199 $actioncomm->label = $langs->trans(
"ActionAC_".$actioncode).
' - '.$langs->trans(
"MailFrom").
' '.$email_from;
3200 $actioncomm->note_private = $descriptionfull;
3201 $actioncomm->fk_project = $projectstatic->id;
3202 $actioncomm->datep = $dateemail;
3203 $actioncomm->datef = $dateemail;
3204 $actioncomm->percentage = -1;
3205 $actioncomm->socid = $thirdpartystatic->id;
3206 $actioncomm->contact_id = $contactstatic->id;
3207 $actioncomm->socpeopleassigned = (!empty($contactstatic->id) ? array($contactstatic->id) : array());
3208 $actioncomm->authorid = $user->id;
3209 $actioncomm->userownerid = $user->id;
3211 $actioncomm->email_msgid = $msgid;
3212 $actioncomm->email_from = $fromstring;
3213 $actioncomm->email_sender = $sender;
3214 $actioncomm->email_to = $to;
3215 $actioncomm->email_tocc = $sendtocc;
3216 $actioncomm->email_tobcc = $sendtobcc;
3217 $actioncomm->email_subject = $subject;
3218 $actioncomm->errors_to =
'';
3220 if (!in_array($fk_element_type, array(
'societe',
'contact',
'project',
'user'))) {
3221 $actioncomm->fk_element = $fk_element_id;
3222 $actioncomm->elementid = $fk_element_id;
3223 $actioncomm->elementtype = $fk_element_type;
3224 if (is_object($objectemail) && $objectemail->module) {
3225 $actioncomm->elementtype .=
'@'.$objectemail->module;
3232 $errorforthisaction = $this->
overwritePropertiesOfObject($actioncomm, $operation[
'actionparam'], $messagetext, $subject, $header, $operationslog);
3234 if ($errorforthisaction) {
3237 $result = $actioncomm->create($user);
3240 $this->errors = $actioncomm->errors;
3242 if ($fk_element_type ==
"ticket" && is_object($objectemail)) {
3243 if ($objectemail->status == Ticket::STATUS_CLOSED || $objectemail->status == Ticket::STATUS_CANCELED || $objectemail->status == Ticket::STATUS_NEED_MORE_INFO || $objectemail->status == Ticket::STATUS_WAITING) {
3244 if ($objectemail->fk_user_assign !=
null) {
3245 $res = $objectemail->setStatut(Ticket::STATUS_ASSIGNED);
3247 $res = $objectemail->setStatut(Ticket::STATUS_NOT_READ);
3251 $operationslog .=
'<br>Ticket Re-Opened successfully -> ref='.$objectemail->ref;
3254 $this->error =
'Error while changing the ticket status -> ref='.$objectemail->ref;
3255 $this->errors[] = $this->error;
3258 if (!empty($attachments)) {
3260 $ticket =
new Ticket($this->db);
3261 $ticket->fetch($fk_element_id);
3262 $destdir =
$conf->ticket->dir_output.
'/'.$ticket->ref;
3267 foreach ($attachments as $attachment) {
3268 $attachment->save($destdir.
'/');
3271 $this->
getmsg($connection, $imapemail, $destdir);
3276 $operationslog .=
'<br>Event created -> id='.dol_escape_htmltag((
string) $actioncomm->id);
3280 $operationslog .=
'<br>An event in actioncomm table already exists for the msgid = '.$msgid.
' so we bypass this action.';
3282 } elseif ($operation[
'type'] ==
'recordjoinpiece') {
3285 foreach ($attachments as $attachment) {
3286 if ($attachment->getName() ===
'undefined') {
3289 $data[$attachment->getName()] = $attachment->getContent();
3293 foreach ($pj as $key => $val) {
3294 $data[$val[
'filename']] =
getFileData($imapemail, (
string) $val[
'pos'], $val[
'type'], $connection);
3297 if (count($data) > 0) {
3298 $sql =
"SELECT rowid as id FROM ".MAIN_DB_PREFIX.
"user WHERE email LIKE '%".$this->db->escape($email_from).
"%'";
3299 $resql = $this->db->query($sql);
3300 if ($this->db->num_rows($resql) == 0) {
3301 $this->errors[] =
"User Not allowed to add documents ({$email_from})";
3303 $arrayobject = array(
3304 'propale' => array(
'table' =>
'propal',
3305 'fields' => array(
'ref'),
3306 'class' =>
'comm/propal/class/propal.class.php',
3307 'object' =>
'Propal'),
3308 'holiday' => array(
'table' =>
'holiday',
3309 'fields' => array(
'ref'),
3310 'class' =>
'holiday/class/holiday.class.php',
3311 'object' =>
'Holiday'),
3312 'expensereport' => array(
'table' =>
'expensereport',
3313 'fields' => array(
'ref'),
3314 'class' =>
'expensereport/class/expensereport.class.php',
3315 'object' =>
'ExpenseReport'),
3316 'recruitment/recruitmentjobposition' => array(
'table' =>
'recruitment_recruitmentjobposition',
3317 'fields' => array(
'ref'),
3318 'class' =>
'recruitment/class/recruitmentjobposition.class.php',
3319 'object' =>
'RecruitmentJobPosition'),
3320 'recruitment/recruitmentcandidature' => array(
'table' =>
'recruitment_recruitmentcandidature',
3321 'fields' => array(
'ref'),
3322 'class' =>
'recruitment/class/recruitmentcandidature.class.php',
3323 'object' =>
'RecruitmentCandidature'),
3324 'societe' => array(
'table' =>
'societe',
3325 'fields' => array(
'code_client',
'code_fournisseur'),
3326 'class' =>
'societe/class/societe.class.php',
3327 'object' =>
'Societe'),
3328 'commande' => array(
'table' =>
'commande',
3329 'fields' => array(
'ref'),
3330 'class' =>
'commande/class/commande.class.php',
3331 'object' =>
'Commande'),
3332 'expedition' => array(
'table' =>
'expedition',
3333 'fields' => array(
'ref'),
3334 'class' =>
'expedition/class/expedition.class.php',
3335 'object' =>
'Expedition'),
3336 'contract' => array(
'table' =>
'contrat',
3337 'fields' => array(
'ref'),
3338 'class' =>
'contrat/class/contrat.class.php',
3339 'object' =>
'Contrat'),
3340 'fichinter' => array(
'table' =>
'fichinter',
3341 'fields' => array(
'ref'),
3342 'class' =>
'fichinter/class/fichinter.class.php',
3343 'object' =>
'Fichinter'),
3344 'ticket' => array(
'table' =>
'ticket',
3345 'fields' => array(
'ref'),
3346 'class' =>
'ticket/class/ticket.class.php',
3347 'object' =>
'Ticket'),
3348 'knowledgemanagement' => array(
'table' =>
'knowledgemanagement_knowledgerecord',
3349 'fields' => array(
'ref'),
3350 'class' =>
'knowledgemanagement/class/knowledgemanagement.class.php',
3351 'object' =>
'KnowledgeRecord'),
3352 'supplier_proposal' => array(
'table' =>
'supplier_proposal',
3353 'fields' => array(
'ref'),
3354 'class' =>
'supplier_proposal/class/supplier_proposal.class.php',
3355 'object' =>
'SupplierProposal'),
3356 'fournisseur/commande' => array(
'table' =>
'commande_fournisseur',
3357 'fields' => array(
'ref',
'ref_supplier'),
3358 'class' =>
'fourn/class/fournisseur.commande.class.php',
3359 'object' =>
'SupplierProposal'),
3360 'facture' => array(
'table' =>
'facture',
3361 'fields' => array(
'ref'),
3362 'class' =>
'compta/facture/class/facture.class.php',
3363 'object' =>
'Facture'),
3364 'fournisseur/facture' => array(
'table' =>
'facture_fourn',
3365 'fields' => array(
'ref',
'ref_client'),
3366 'class' =>
'fourn/class/fournisseur.facture.class.php',
3367 'object' =>
'FactureFournisseur'),
3368 'produit' => array(
'table' =>
'product',
3369 'fields' => array(
'ref'),
3370 'class' =>
'product/class/product.class.php',
3371 'object' =>
'Product'),
3372 'productlot' => array(
'table' =>
'product_lot',
3373 'fields' => array(
'batch'),
3374 'class' =>
'product/stock/class/productlot.class.php',
3375 'object' =>
'Productlot'),
3376 'projet' => array(
'table' =>
'projet',
3377 'fields' => array(
'ref'),
3378 'class' =>
'projet/class/projet.class.php',
3379 'object' =>
'Project'),
3380 'projet_task' => array(
'table' =>
'projet_task',
3381 'fields' => array(
'ref'),
3382 'class' =>
'projet/class/task.class.php',
3383 'object' =>
'Task'),
3384 'ressource' => array(
'table' =>
'resource',
3385 'fields' => array(
'ref'),
3386 'class' =>
'ressource/class/dolressource.class.php',
3387 'object' =>
'Dolresource'),
3388 'bom' => array(
'table' =>
'bom_bom',
3389 'fields' => array(
'ref'),
3390 'class' =>
'bom/class/bom.class.php',
3392 'mrp' => array(
'table' =>
'mrp_mo',
3393 'fields' => array(
'ref'),
3394 'class' =>
'mrp/class/mo.class.php',
3398 if (!is_object($hookmanager)) {
3399 include_once DOL_DOCUMENT_ROOT.
'/core/class/hookmanager.class.php';
3402 $hookmanager->initHooks(array(
'emailcolector'));
3403 $parameters = array(
'arrayobject' => $arrayobject);
3404 $reshook = $hookmanager->executeHooks(
'addmoduletoeamailcollectorjoinpiece', $parameters);
3406 $arrayobject = $hookmanager->resArray;
3409 $resultobj = array();
3411 foreach ($arrayobject as $key => $objectdesc) {
3412 $sql =
'SELECT DISTINCT t.rowid ';
3413 $sql .=
' FROM ' . MAIN_DB_PREFIX . $this->db->sanitize($objectdesc[
'table']) .
' AS t';
3415 foreach ($objectdesc[
'fields'] as $field) {
3416 $sql .=
"('" .$this->db->escape($subject) .
"' LIKE CONCAT('%', t." . $this->db->sanitize($field) .
", '%') AND t." . $this->db->sanitize($field) .
" <> '') OR ";
3418 $sql = substr($sql, 0, -4);
3420 $ressqlobj = $this->db->query($sql);
3422 while ($obj = $this->db->fetch_object($ressqlobj)) {
3423 $resultobj[$key][] = $obj->rowid;
3428 foreach ($resultobj as $mod => $ids) {
3429 $moddesc = $arrayobject[$mod];
3430 $elementpath = $mod;
3432 $objectmanaged =
new $moddesc[
'object']($this->db);
3433 '@phan-var-force CommonObject $objectmanaged';
3434 foreach ($ids as $val) {
3435 $res = $objectmanaged->fetch($val);
3437 $path = ($objectmanaged->entity > 1 ?
"/" . $objectmanaged->entity :
'');
3438 $dirs[] = DOL_DATA_ROOT . $path .
"/" . $elementpath .
'/' .
dol_sanitizeFileName($objectmanaged->ref) .
'/';
3440 $this->errors[] =
'object not found';
3444 foreach ($dirs as $target) {
3445 $prefix = $this->actions[$this->id][
'actionparam'];
3446 foreach ($data as $filename => $content) {
3447 $resr = $this->
saveAttachment($target, $prefix .
'_' . $filename, $content);
3449 $this->errors[] =
'Doc not saved';
3454 $operationslog .=
'<br>Save attachment files on disk';
3456 $this->errors[] =
'no joined piece';
3458 $operationslog .=
'<br>No joinded files';
3460 } elseif ($operation[
'type'] ==
'project') {
3462 $projecttocreate =
new Project($this->db);
3463 $alreadycreated = $projecttocreate->fetch(0,
'',
'', $msgid);
3464 if ($alreadycreated == 0) {
3465 if ($thirdpartystatic->id > 0) {
3466 $projecttocreate->socid = $thirdpartystatic->id;
3467 if ($thirdpartyfoundby) {
3468 $descriptionmeta =
dol_concatdesc($descriptionmeta,
'Third party found from '.$thirdpartyfoundby);
3471 if ($contactstatic->id > 0) {
3472 $projecttocreate->contact_id = $contactstatic->id;
3473 if ($contactfoundby) {
3474 $descriptionmeta =
dol_concatdesc($descriptionmeta,
'Contact/address found from '.$contactfoundby);
3478 $description = $descriptiontitle;
3484 $descriptionfull = $description;
3486 $descriptionfull =
dol_concatdesc($descriptionfull,
"----- Header");
3490 $id_opp_status =
dol_getIdFromCode($this->db,
'PROSP',
'c_lead_status',
'code',
'rowid');
3491 $percent_opp_status =
dol_getIdFromCode($this->db,
'PROSP',
'c_lead_status',
'code',
'percent');
3493 $projecttocreate->title = $subject;
3494 $projecttocreate->date_start = $dateemail;
3495 $projecttocreate->date_end = 0;
3496 $projecttocreate->opp_status = $id_opp_status;
3497 $projecttocreate->opp_percent = $percent_opp_status;
3499 $projecttocreate->note_private = $descriptionfull;
3500 $projecttocreate->entity =
$conf->entity;
3502 $projecttocreate->email_date = $dateemail;
3503 $projecttocreate->email_msgid = $msgid;
3504 $projecttocreate->email_from = $fromstring;
3505 $projecttocreate->email_sender = $sender;
3506 $projecttocreate->email_to = $to;
3507 $projecttocreate->email_tocc = $sendtocc;
3508 $projecttocreate->email_tobcc = $sendtobcc;
3509 $projecttocreate->email_subject = $subject;
3510 $projecttocreate->errors_to =
'';
3512 $savesocid = $projecttocreate->socid;
3516 $errorforthisaction = $this->
overwritePropertiesOfObject($projecttocreate, $operation[
'actionparam'], $messagetext, $subject, $header, $operationslog);
3520 if (empty($projecttocreate->ref)) {
3529 $dirmodels = array_merge(array(
'/'), (array)
$conf->modules_parts[
'models']);
3530 foreach ($dirmodels as $reldir) {
3531 $file =
dol_buildpath($reldir.
"core/modules/project/".$modele.
'.php', 0);
3532 if (file_exists($file)) {
3533 $classname = $modele;
3538 if ($classname !==
'') {
3539 if ($savesocid > 0) {
3540 if ($savesocid != $projecttocreate->socid) {
3542 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');
3545 if ($projecttocreate->socid > 0) {
3546 $thirdpartystatic->fetch($projecttocreate->socid);
3550 $result =
dol_include_once($reldir.
"core/modules/project/".$modele.
'.php');
3551 $modModuleToUseForNextValue =
new $classname();
3552 '@phan-var-force ModeleNumRefProjects $modModuleToUseForNextValue';
3553 $defaultref = $modModuleToUseForNextValue->getNextValue(($thirdpartystatic->id > 0 ? $thirdpartystatic : null), $projecttocreate);
3555 $projecttocreate->ref = $defaultref;
3559 if ($errorforthisaction) {
3562 if (empty($projecttocreate->ref) || (is_numeric($projecttocreate->ref) && $projecttocreate->ref <= 0)) {
3564 $this->error =
'Failed to create project: Can\'t get a valid value for the field ref with numbering template = '.$modele.
', thirdparty id = '.$thirdpartystatic->id;
3566 $operationslog .=
'<br>'.$this->error;
3569 $result = $projecttocreate->create($user);
3572 $this->error =
'Failed to create project: '.$langs->trans($projecttocreate->error);
3573 $this->errors = $projecttocreate->errors;
3575 $operationslog .=
'<br>'.$this->error;
3578 $destdir =
$conf->project->dir_output.
'/'.$projecttocreate->ref;
3583 foreach ($attachments as $attachment) {
3585 $typeattachment = (
string) $attachment->getDisposition();
3586 $filename = $attachment->getFilename();
3587 $content = $attachment->getContent();
3591 $getMsg = $this->
getmsg($connection, $imapemail, $destdir);
3593 $this->errors = array_merge($this->errors, [$this->error]);
3598 $operationslog .=
'<br>Project created with attachments -> id='.dol_escape_htmltag((
string) $projecttocreate->id);
3600 $operationslog .=
'<br>Project created without attachments -> id='.dol_escape_htmltag((
string) $projecttocreate->id);
3608 $operationslog .=
'<br>Project already exists for msgid ='.dol_escape_htmltag($msgid);
3610 } elseif ($operation[
'type'] ==
'ticket') {
3612 $tickettocreate =
new Ticket($this->db);
3613 if ($ticketalreadyexists == 0) {
3614 if ($thirdpartystatic->id > 0) {
3615 $tickettocreate->socid = $thirdpartystatic->id;
3616 $tickettocreate->fk_soc = $thirdpartystatic->id;
3617 if ($thirdpartyfoundby) {
3618 $descriptionmeta =
dol_concatdesc($descriptionmeta,
'Third party found from '.$thirdpartyfoundby);
3621 if ($contactstatic->id > 0) {
3622 $tickettocreate->contact_id = $contactstatic->id;
3623 if ($contactfoundby) {
3624 $descriptionmeta =
dol_concatdesc($descriptionmeta,
'Contact/address found from '.$contactfoundby);
3628 $description = $descriptiontitle;
3634 $descriptionfull = $description;
3636 $descriptionfull =
dol_concatdesc($descriptionfull,
"----- Header");
3640 $tickettocreate->subject = $subject;
3641 $tickettocreate->message = $description;
3643 $tickettocreate->category_code = (
getDolGlobalString(
'MAIN_EMAILCOLLECTOR_TICKET_CATEGORY_CODE',
dol_getIdFromCode($this->db, 1,
'c_ticket_category',
'use_default',
'code', 1)));
3644 $tickettocreate->severity_code = (
getDolGlobalString(
'MAIN_EMAILCOLLECTOR_TICKET_SEVERITY_CODE',
dol_getIdFromCode($this->db, 1,
'c_ticket_severity',
'use_default',
'code', 1)));
3645 $tickettocreate->origin_email = $email_from;
3646 $tickettocreate->origin_replyto = (!empty($replyto) ? $replyto :
null);
3647 $tickettocreate->origin_references = (!empty($headers[
'References']) ? $headers[
'References'] :
null);
3648 $tickettocreate->fk_user_create = $user->id;
3649 $tickettocreate->datec =
dol_now();
3650 $tickettocreate->fk_project = $projectstatic->id;
3651 $tickettocreate->notify_tiers_at_create =
getDolGlobalInt(
'TICKET_CHECK_NOTIFY_THIRDPARTY_AT_CREATION');
3652 $tickettocreate->note_private = $descriptionfull;
3653 $tickettocreate->entity =
$conf->entity;
3655 $tickettocreate->email_date = $dateemail;
3656 $tickettocreate->email_msgid = $msgid;
3657 $tickettocreate->email_from = $fromstring;
3658 $tickettocreate->email_sender = $sender;
3659 $tickettocreate->email_to = $to;
3660 $tickettocreate->email_tocc = $sendtocc;
3661 $tickettocreate->email_tobcc = $sendtobcc;
3662 $tickettocreate->email_subject = $subject;
3663 $tickettocreate->errors_to =
'';
3667 $savesocid = $tickettocreate->socid;
3671 $errorforthisaction = $this->
overwritePropertiesOfObject($tickettocreate, $operation[
'actionparam'], $messagetext, $subject, $header, $operationslog);
3673 $modele =
'UNDEFINED';
3675 if (empty($tickettocreate->ref)) {
3684 $dirmodels = array_merge(array(
'/'), (array)
$conf->modules_parts[
'models']);
3685 foreach ($dirmodels as $reldir) {
3686 $file =
dol_buildpath($reldir.
"core/modules/ticket/".$modele.
'.php', 0);
3687 if (file_exists($file)) {
3688 $classname = $modele;
3693 if ($classname !==
'') {
3694 if ($savesocid > 0) {
3695 if ($savesocid != $tickettocreate->socid) {
3697 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');
3700 if ($tickettocreate->socid > 0) {
3701 $thirdpartystatic->fetch($tickettocreate->socid);
3706 $modModuleToUseForNextValue =
new $classname();
3707 '@phan-var-force ModeleNumRefTicket $modModuleToUseForNextValue';
3708 $defaultref = $modModuleToUseForNextValue->getNextValue(($thirdpartystatic->id > 0 ? $thirdpartystatic : null), $tickettocreate);
3710 $tickettocreate->ref = $defaultref;
3713 if ($errorforthisaction) {
3716 if (is_numeric($tickettocreate->ref) && $tickettocreate->ref <= 0) {
3718 $this->error =
'Failed to create ticket: Can\'t get a valid value for the field ref with numbering template = '.$modele.
', thirdparty id = '.$thirdpartystatic->id;
3721 $tickettocreate->context[
'actionmsg2'] = $langs->trans(
"ActionAC_EMAIL_IN").
' - '.$langs->trans(
"TICKET_CREATEInDolibarr");
3722 $tickettocreate->context[
'actionmsg'] = $langs->trans(
"ActionAC_EMAIL_IN").
' - '.$langs->trans(
"TICKET_CREATEInDolibarr");
3726 $sender_contact =
new Contact($this->db);
3727 $sender_contact->fetch(0,
null,
'', $email_from);
3728 if (!empty($sender_contact->id)) {
3729 $tickettocreate->context[
'contact_id'] = $sender_contact->id;
3732 $result = $tickettocreate->create($user);
3735 $this->error =
'Failed to create ticket: '.$langs->trans($tickettocreate->error);
3736 $this->errors = $tickettocreate->errors;
3739 $destdir =
$conf->ticket->dir_output.
'/'.$tickettocreate->ref;
3744 foreach ($attachments as $attachment) {
3746 $typeattachment = (
string) $attachment->getDisposition();
3747 $filename = $attachment->getName();
3748 $content = $attachment->getContent();
3752 $getMsg = $this->
getmsg($connection, $imapemail, $destdir);
3754 $this->errors = array_merge($this->errors, [$this->error]);
3759 $operationslog .=
'<br>Ticket created with attachments -> id='.dol_escape_htmltag((
string) $tickettocreate->id);
3761 $operationslog .=
'<br>Ticket created without attachments -> id='.dol_escape_htmltag((
string) $tickettocreate->id);
3770 $operationslog .=
'<br>Ticket already exists, so we bypass action "ticket"';
3772 } elseif ($operation[
'type'] ==
'candidature') {
3776 $alreadycreated = $candidaturetocreate->fetch(0,
'', $msgid);
3777 if ($alreadycreated == 0) {
3778 $description = $descriptiontitle;
3784 $descriptionfull = $description;
3786 $descriptionfull =
dol_concatdesc($descriptionfull,
"----- Header");
3790 $candidaturetocreate->subject = $subject;
3791 $candidaturetocreate->message = $description;
3792 $candidaturetocreate->type_code = 0;
3793 $candidaturetocreate->category_code =
null;
3794 $candidaturetocreate->severity_code =
null;
3795 $candidaturetocreate->email = $email_from;
3797 $candidaturetocreate->fk_user_creat = $user->id;
3798 $candidaturetocreate->date_creation =
dol_now();
3799 $candidaturetocreate->fk_project = $projectstatic->id;
3800 $candidaturetocreate->description = $description;
3801 $candidaturetocreate->note_private = $descriptionfull;
3802 $candidaturetocreate->entity =
$conf->entity;
3803 $candidaturetocreate->email_msgid = $msgid;
3804 $candidaturetocreate->email_date = $dateemail;
3805 $candidaturetocreate->status = $candidaturetocreate::STATUS_DRAFT;
3810 $errorforthisaction = $this->
overwritePropertiesOfObject($candidaturetocreate, $operation[
'actionparam'], $messagetext, $subject, $header, $operationslog);
3853 if ($errorforthisaction) {
3857 $result = $candidaturetocreate->create($user);
3860 $this->error =
'Failed to create candidature: '.implode(
', ', $candidaturetocreate->errors);
3861 $this->errors = $candidaturetocreate->errors;
3864 $operationslog .=
'<br>Candidature created without attachments -> id='.dol_escape_htmltag((
string) $candidaturetocreate->id);
3867 } elseif (substr($operation[
'type'], 0, 4) ==
'hook') {
3870 if (!is_object($hookmanager)) {
3871 include_once DOL_DOCUMENT_ROOT.
'/core/class/hookmanager.class.php';
3874 $hookmanager->initHooks([
'emailcolector']);
3876 $parameters = array(
3877 'connection' => $connection,
3878 'imapemail' => $imapemail,
3879 'overview' => $overview,
3881 'from' => $email_from,
3882 'fromtext' => $fromtext,
3884 'actionparam' => $operation[
'actionparam'],
3886 'thirdpartyid' => ($thirdpartyid ? $thirdpartyid : $thirdpartystatic->id),
3887 'objectid' => $objectid,
3888 'objectemail' => $objectemail,
3890 'messagetext' => $messagetext,
3891 'subject' => $subject,
3892 'header' => $header,
3893 'attachments' => $attachments,
3894 'savedattachments' => $savedattachments,
3895 'savedattachmentsdir' => $savedattachmentsdir,
3897 $reshook = $hookmanager->executeHooks(
'doCollectImapOneCollector', $parameters, $this, $operation[
'type']);
3900 $errorforthisaction++;
3901 $this->error = $hookmanager->resPrint;
3902 if (!empty($hookmanager->resPrint)) {
3903 $operationslog .=
'<br>Hook error: '.dol_escape_htmltag($hookmanager->resPrint);
3906 if ($errorforthisaction) {
3908 $operationslog .=
'<br>Hook doCollectImapOneCollector executed with error';
3910 $operationslog .=
'<br>Hook doCollectImapOneCollector executed without error';
3914 if (!$errorforactions) {
3915 $nbactiondoneforemail++;
3921 if (!$errorforactions) {
3922 if (!empty($targetdir)) {
3925 dol_syslog(
"EmailCollector::doCollectOneCollector move message ".($imapemail->getHeader()->get(
'subject')).
" to ".$targetdir, LOG_DEBUG);
3926 $operationslog .=
'<br>Move mail '.($this->uidAsString($imapemail)).
' - '.$msgid.
' - '.$imapemail->getHeader()->get(
'subject').
' to '.$targetdir;
3928 $arrayofemailtodelete[$this->
uidAsString($imapemail)] = $imapemail;
3931 dol_syslog(
"EmailCollector::doCollectOneCollector move message ".($this->
uidAsString($imapemail)).
" to ".$connectstringtarget, LOG_DEBUG);
3932 $operationslog .=
'<br>Move mail '.($this->uidAsString($imapemail)).
' - '.$msgid;
3934 $arrayofemailtodelete[$imapemail] = $msgid;
3939 dol_syslog(
"EmailCollector::doCollectOneCollector message ".($this->
uidAsString($imapemail)).
" '".($imapemail->getHeader()->get(
'subject')).
"' using this->host=".$this->host.
", this->access_type=".$this->acces_type.
" was set to read", LOG_DEBUG);
3941 dol_syslog(
"EmailCollector::doCollectOneCollector message ".($this->
uidAsString($imapemail)).
" to ".$connectstringtarget.
" was set to read", LOG_DEBUG);
3949 unset($objectemail);
3950 unset($projectstatic);
3951 unset($thirdpartystatic);
3952 unset($contactstatic);
3954 $nbemailprocessed++;
3956 if (!$errorforemail) {
3957 $nbactiondone += $nbactiondoneforemail;
3961 $this->db->commit();
3963 $this->db->rollback();
3967 if ($this->maxemailpercollect > 0 && $nbemailok >= $this->maxemailpercollect) {
3968 dol_syslog(
"EmailCollect::doCollectOneCollector We reach maximum of ".$nbemailok.
" collected with success, so we stop this collector now.");
3969 $datelastok = strtotime($headers[
'Date']);
3975 $this->db->rollback();
3979 $output = $langs->trans(
'XEmailsDoneYActionsDone', $nbemailprocessed, $nbemailok, $nbactiondone);
3981 dol_syslog(
"End of loop on emails", LOG_INFO, -1);
3983 $langs->load(
"admin");
3984 $output = $langs->trans(
'NoNewEmailToProcess');
3985 $output .=
' (defaultlang='.$langs->defaultlang.
')';
3991 krsort($arrayofemailtodelete, SORT_NUMERIC);
3993 foreach ($arrayofemailtodelete as $imapemailnum => $imapemail) {
3994 dol_syslog(
"EmailCollect::doCollectOneCollector delete email ".$imapemailnum);
3996 $operationslog .=
"<br> move email ".$imapemailnum.($mode > 0 ?
' (test)' :
'');
3998 if (empty($mode) && empty($error)) {
3999 $tmptargetdir = $targetdir;
4006 $result = $imapemail->move($tmptargetdir,
false);
4009 $operationslog .=
'<br>Exception !!!! '.$e->getMessage();
4011 if (empty($result)) {
4012 dol_syslog(
"Failed to move email into target directory ".$targetdir);
4013 $operationslog .=
'<br>Failed to move email into target directory '.$targetdir;
4019 if (empty($mode) && empty($error)) {
4021 $operationslog .=
"<br>Expunge";
4026 $client->disconnect();
4028 foreach ($arrayofemailtodelete as $imapemail => $msgid) {
4029 dol_syslog(
"EmailCollect::doCollectOneCollector delete email ".$imapemail.
" ".$msgid);
4031 $operationslog .=
"<br> delete email ".$imapemail.
" ".$msgid.($mode > 0 ?
' (test)' :
'');
4033 if (empty($mode) && empty($error)) {
4034 $res = imap_mail_move($connection, $imapemail, $targetdir, CP_UID);
4037 $this->error = imap_last_error();
4038 $this->errors[] = $this->error;
4040 $operationslog .=
'<br>Error in move '.$this->error;
4047 if (empty($mode) && empty($error)) {
4049 $operationslog .=
"<br>Expunge";
4051 imap_expunge($connection);
4053 imap_close($connection);
4056 $this->datelastresult = $now;
4057 $this->lastresult = $output;
4059 $this->debuginfo .=
'IMAP search array used : '.$search;
4061 $this->debuginfo .=
'IMAP search string used : '.$search;
4064 $this->debuginfo .=
'<br>Then search string into email header : '.dol_escape_htmltag($searchhead);
4066 if ($operationslog) {
4067 $this->debuginfo .= $operationslog;
4070 if (empty($error) && empty($mode)) {
4071 $this->datelastok = $datelastok;
4074 if (!empty($this->errors)) {
4075 $this->lastresult .=
"<br>".implode(
"<br>", $this->errors);
4077 $this->codelastresult = ($error ?
'KO' :
'OK');
4083 dol_syslog(
"EmailCollector::doCollectOneCollector end error=".$error, LOG_INFO);
4085 return $error ? -1 : 1;
4100 private function getmsg($mbox, $mid, $destdir =
''): int
4104 global $charset, $htmlmsg, $plainmsg, $attachments;
4105 $htmlmsg = $plainmsg = $charset =
'';
4106 $attachments = array();
4113 $s = imap_fetchstructure($mbox, $mid, FT_UID);
4115 $this->errors = array_merge($this->errors, [imap_last_error()]);
4119 if (empty($s->parts)) {
4121 $this->
getpart($mbox, $mid, $s,
'0');
4124 foreach ($s->parts as $partno0 => $p) {
4125 $this->
getpart($mbox, $mid, $p, (
string) ($partno0 + 1), $destdir);
4158 private function getpart($mbox, $mid, $p, $partno, $destdir =
'')
4161 global $htmlmsg, $plainmsg, $charset, $attachments;
4165 imap_fetchbody($mbox, $mid, $partno, FT_UID) :
4166 imap_body($mbox, $mid, FT_UID);
4168 if ($p->encoding == 4) {
4169 $data = quoted_printable_decode($data);
4170 } elseif ($p->encoding == 3) {
4171 $data = base64_decode($data);
4177 if ($p->parameters) {
4178 foreach ($p->parameters as $x) {
4179 $params[strtolower($x->attribute)] = $x->value;
4182 if (!empty($p->dparameters)) {
4183 foreach ($p->dparameters as $x) {
4184 $params[strtolower($x->attribute)] = $x->value;
4187 '@phan-var-force array{filename?:string,name?:string,charset?:string} $params';
4192 if (!empty($params[
'filename']) || !empty($params[
'name'])) {
4194 $filename = $params[
'filename'] ?? $params[
'name'];
4196 $attachments[$filename] = $data;
4198 if (strlen($destdir)) {
4199 if (substr($destdir, -1) !=
'/') {
4204 $file_name_complete = $filename;
4205 $destination = $destdir.$file_name_complete;
4208 $extension = pathinfo($file_name_complete, PATHINFO_EXTENSION);
4211 $file_name = pathinfo($file_name_complete, PATHINFO_FILENAME);
4214 $file_name_original = $file_name;
4223 while (file_exists($destdir.$file_name.
".".$extension)) {
4224 $file_name = $file_name_original .
' (' . $num .
')';
4225 $file_name_complete = $file_name .
"." . $extension;
4226 $destination = $destdir.$file_name_complete;
4232 file_put_contents($destination, $data);
4238 if ($p->type == 0 && $data) {
4239 if (!empty($params[
'charset'])) {
4244 if (strtolower($p->subtype) ==
'plain') {
4245 $plainmsg .= trim($data).
"\n\n";
4247 $htmlmsg .= $data.
"<br><br>";
4249 $charset = $params[
'charset'];
4250 } elseif ($p->type == 2 && $data) {
4256 if (!empty($params[
'charset'])) {
4259 $plainmsg .= $data.
"\n\n";
4263 if (!empty($p->parts)) {
4264 foreach ($p->parts as $partno0 => $p2) {
4265 $this->
getpart($mbox, $mid, $p2, $partno.
'.'.($partno0 + 1), $destdir);
4281 if (!$string || $fromEncoding == $toEncoding) {
4284 $convertedString = function_exists(
'iconv') ? @iconv($fromEncoding, $toEncoding.
'//IGNORE', $string) :
null;
4285 if (!$convertedString && extension_loaded(
'mbstring')) {
4286 $convertedString = @mb_convert_encoding($string, $toEncoding, $fromEncoding);
4288 if (!$convertedString) {
4289 throw new Exception(
'Mime string encoding conversion failed');
4291 return $convertedString;
4310 if (function_exists(
'imap_mime_header_decode') && function_exists(
'iconv_mime_decode')) {
4311 $elements = imap_mime_header_decode($subject);
4313 if (!empty($elements)) {
4314 $num = count($elements);
4315 for ($i = 0; $i < $num; $i++) {
4316 $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));
4317 $newstring .= $stringinutf8;
4319 $subject = $newstring;
4321 } elseif (!function_exists(
'mb_decode_mimeheader')) {
4322 $subject = mb_decode_mimeheader($subject);
4323 } elseif (function_exists(
'iconv_mime_decode')) {
4324 $subject = iconv_mime_decode($subject, ICONV_MIME_DECODE_CONTINUE_ON_ERROR,
'UTF-8');
4327 return (
string) $subject;
4337 private function saveEmailCollectorAttachmentsToDir($destdir, $attachments)
4339 $destdir = rtrim((
string) $destdir,
'/');
4340 if ($destdir ===
'' || empty($attachments) || !is_array($attachments)) {
4351 $seenHashes = array();
4354 $filelist =
dol_dir_list($destdir,
'files', 0,
'',
'(\\.meta|_preview.*.*\\.png)$',
'date', SORT_DESC, 0, 1);
4355 foreach ($filelist as $fileinfo) {
4356 if (empty($fileinfo[
'fullname']) || !is_file($fileinfo[
'fullname']) || !is_readable($fileinfo[
'fullname'])) {
4359 $hash = hash_file(
'sha256', $fileinfo[
'fullname']);
4360 if ($hash !==
false && empty($seenHashes[$hash])) {
4361 $seenHashes[$hash] = $fileinfo[
'name'];
4367 if (defined(
'DOL_DATA_ROOT')) {
4368 $root = rtrim((
string) DOL_DATA_ROOT,
'/').
'/';
4369 $destdirwithslash = $destdir.
'/';
4370 if (strpos($destdirwithslash, $root) === 0) {
4371 $relativeDir = rtrim(substr($destdirwithslash, strlen($root)),
'/');
4376 foreach ($attachments as $key => $attachment) {
4383 if (is_object($attachment)) {
4384 '@phan-var-force Webklex\PHPIMAP\Attachment $attachment';
4387 $origName = (
string) $attachment->getName();
4388 }
catch (Throwable $e) {
4392 $content = (
string) $attachment->getContent();
4393 }
catch (Throwable $e) {
4397 $tmpmime = (
string) $attachment->getContentType();
4398 $mime = ($tmpmime !==
'' ? $tmpmime :
null);
4399 }
catch (Throwable $e) {
4404 $origName = (
string) $key;
4405 $content = (
string) $attachment;
4408 if ($origName ===
'' || $origName ===
'undefined') {
4409 $origName =
'attachment-'.$index;
4411 if ($content ===
'') {
4416 if ($safeName ===
'') {
4417 $safeName =
'attachment-'.$index;
4420 $contentHash = hash(
'sha256', $content);
4421 $finalName = $safeName;
4422 $useExisting =
false;
4423 if (!empty($seenHashes[$contentHash])) {
4424 $finalName = $seenHashes[$contentHash];
4425 if (file_exists($destdir.
'/'.$finalName)) {
4426 $useExisting =
true;
4430 if (!$useExisting) {
4432 while (file_exists($destdir.
'/'.$finalName)) {
4433 $finalName = preg_replace(
'/(\\.[A-Za-z0-9]{1,10})$/',
'', $safeName).
'-'.$n;
4434 if (preg_match(
'/\\.[A-Za-z0-9]{1,10}$/', $safeName, $m)) {
4435 $finalName .= $m[0];
4441 $seenHashes[$contentHash] = $finalName;
4444 $fullPath = $destdir.
'/'.$finalName;
4445 $size = (file_exists($fullPath) ? filesize($fullPath) : null);
4446 $sizevalue = ($size ===
false ? null : $size);
4447 $sha256 = $contentHash;
4450 'name' => $finalName,
4451 'original_name' => $origName,
4452 'relative_path' => ($relativeDir !==
'' ? $relativeDir.
'/'.$finalName :
''),
4453 'content_type' => $mime,
4454 'size' => ($sizevalue !== null ? (int) $sizevalue : null),
4455 'sha256' => $sha256,
4472 require_once DOL_DOCUMENT_ROOT .
'/core/lib/images.lib.php';
4477 if (!file_exists($destdir)) {
4483 $tmp = explode(
'.', $filename);
4484 $ext = array_pop($tmp);
4485 $filename = implode(
'.', $tmp);
4488 $filepath = $destdir . (preg_match(
'/\/$/', $destdir) ?
'' :
'/') . $filename .
'.' . $ext;
4490 while (file_exists($filepath)) {
4491 $filepath = $destdir . (preg_match(
'/\/$/', $destdir) ?
'' :
'/') . $filename .
'(' . $i .
').' . $ext;
4495 file_put_contents($filepath, $content);
4500 $maxwidthsmall = $tmparraysize[
'maxwidthsmall'];
4501 $maxheightsmall = $tmparraysize[
'maxheightsmall'];
4502 $maxwidthmini = $tmparraysize[
'maxwidthmini'];
4503 $maxheightmini = $tmparraysize[
'maxheightmini'];
4504 $quality = $tmparraysize[
'quality'];
4507 vignette($filepath, $maxwidthsmall, $maxheightsmall,
'_small', $quality,
"thumbs");
4509 vignette($filepath, $maxwidthmini, $maxheightmini,
'_mini', $quality,
"thumbs");
4525 if (is_object($imapemail)) {
4526 return $imapemail->getAttributes()[
"uid"];
4528 return (
string) $imapemail;