forked from Wavyzz/dolibarr
Debug email collector
This commit is contained in:
@@ -452,19 +452,25 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea
|
|||||||
print '<tr class="oddeven">';
|
print '<tr class="oddeven">';
|
||||||
print '<td>';
|
print '<td>';
|
||||||
$arrayoftypes=array(
|
$arrayoftypes=array(
|
||||||
'from'=>array('label'=>'MailFrom', 'data-placeholder'=>'SearchString'),
|
'from'=>array('label'=>'MailFrom', 'data-placeholder'=>$langs->trans('SearchString')),
|
||||||
'to'=>array('label'=>'MailTo', 'data-placeholder'=>'SearchString'),
|
'to'=>array('label'=>'MailTo', 'data-placeholder'=>$langs->trans('SearchString')),
|
||||||
'cc'=>array('label'=>'Cc', 'data-placeholder'=>'SearchString'),
|
'cc'=>array('label'=>'Cc', 'data-placeholder'=>$langs->trans('SearchString')),
|
||||||
'bcc'=>array('label'=>'Bcc', 'data-placeholder'=>'SearchString'),
|
'bcc'=>array('label'=>'Bcc', 'data-placeholder'=>$langs->trans('SearchString')),
|
||||||
'subject'=>array('label'=>'Subject', 'data-placeholder'=>'SearchString'),
|
'subject'=>array('label'=>'Subject', 'data-placeholder'=>$langs->trans('SearchString')),
|
||||||
'body'=>array('label'=>'Body', 'data-placeholder'=>'SearchString'),
|
'body'=>array('label'=>'Body', 'data-placeholder'=>$langs->trans('SearchString')),
|
||||||
'header'=>array('label'=>'Header', 'data-placeholder'=>'HeaderKey SearchString'), // HEADER key value
|
// disabled because PHP imap_search is not compatible IMAPv4, only IMAPv2
|
||||||
'X1'=>'---',
|
//'header'=>array('label'=>'Header', 'data-placeholder'=>'HeaderKey SearchString'), // HEADER key value
|
||||||
|
//'X1'=>'---',
|
||||||
|
//'notinsubject'=>array('label'=>'SubjectNotIn', 'data-placeholder'=>'SearchString'),
|
||||||
|
//'notinbody'=>array('label'=>'BodyNotIn', 'data-placeholder'=>'SearchString'),
|
||||||
|
'X2'=>'---',
|
||||||
'seen'=>array('label'=>'AlreadyRead', 'data-noparam'=>1),
|
'seen'=>array('label'=>'AlreadyRead', 'data-noparam'=>1),
|
||||||
'unseen'=>array('label'=>'NotRead', 'data-noparam'=>1),
|
'unseen'=>array('label'=>'NotRead', 'data-noparam'=>1),
|
||||||
'smaller'=>array('label'=>'SmallerThan', 'data-placeholder'=>'NumberOfBytes'),
|
'unanswered'=>array('label'=>'Unanswered', 'data-noparam'=>1),
|
||||||
'larger'=>array('label'=>'LargerThan', 'data-placeholder'=>'NumberOfBytes'),
|
'answered'=>array('label'=>'Answered', 'data-noparam'=>1),
|
||||||
'X2'=>'---',
|
'smaller'=>array('label'=>'SmallerThan', 'data-placeholder'=>$langs->trans('NumberOfBytes')),
|
||||||
|
'larger'=>array('label'=>'LargerThan', 'data-placeholder'=>$langs->trans('NumberOfBytes')),
|
||||||
|
'X3'=>'---',
|
||||||
'withtrackingid'=>array('label'=>'WithDolTrackingID', 'data-noparam'=>1),
|
'withtrackingid'=>array('label'=>'WithDolTrackingID', 'data-noparam'=>1),
|
||||||
'withouttrackingid'=>array('label'=>'WithoutDolTrackingID', 'data-noparam'=>1)
|
'withouttrackingid'=>array('label'=>'WithoutDolTrackingID', 'data-noparam'=>1)
|
||||||
);
|
);
|
||||||
@@ -530,7 +536,7 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea
|
|||||||
'recordevent'=>'RecordEvent');
|
'recordevent'=>'RecordEvent');
|
||||||
if ($conf->projet->enabled) $arrayoftypes['project']='CreateLeadAndThirdParty';
|
if ($conf->projet->enabled) $arrayoftypes['project']='CreateLeadAndThirdParty';
|
||||||
if ($conf->ticket->enabled) $arrayoftypes['ticket']='CreateTicketAndThirdParty';
|
if ($conf->ticket->enabled) $arrayoftypes['ticket']='CreateTicketAndThirdParty';
|
||||||
print $form->selectarray('operationtype', $arrayoftypes, '', 1, 0, 0, '', 1);
|
print $form->selectarray('operationtype', $arrayoftypes, '', 1, 0, 0, '', 1, 0, 0, '', 'maxwidth300');
|
||||||
print '</td><td>';
|
print '</td><td>';
|
||||||
print '<input type="text" name="operationparam">';
|
print '<input type="text" name="operationparam">';
|
||||||
$htmltext=$langs->transnoentitiesnoconv("OperationParamDesc");
|
$htmltext=$langs->transnoentitiesnoconv("OperationParamDesc");
|
||||||
|
|||||||
@@ -6107,6 +6107,7 @@ $substitutionarray=array_merge($substitutionarray, array(
|
|||||||
{
|
{
|
||||||
$substitutionarray['__DOL_MAIN_URL_ROOT__']=DOL_MAIN_URL_ROOT;
|
$substitutionarray['__DOL_MAIN_URL_ROOT__']=DOL_MAIN_URL_ROOT;
|
||||||
$substitutionarray['__(AnyTranslationKey)__']=$outputlangs->trans('TranslationOfKey');
|
$substitutionarray['__(AnyTranslationKey)__']=$outputlangs->trans('TranslationOfKey');
|
||||||
|
$substitutionarray['__(AnyTranslationKey|langfile)__']=$outputlangs->trans('TranslationOfKey').' (load also language file before)';
|
||||||
$substitutionarray['__[AnyConstantKey]__']=$outputlangs->trans('ValueOfConstantKey');
|
$substitutionarray['__[AnyConstantKey]__']=$outputlangs->trans('ValueOfConstantKey');
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -6135,7 +6136,7 @@ function make_substitutions($text, $substitutionarray, $outputlangs = null)
|
|||||||
|
|
||||||
if (empty($outputlangs)) $outputlangs=$langs;
|
if (empty($outputlangs)) $outputlangs=$langs;
|
||||||
|
|
||||||
// Make substitution for language keys
|
// Make substitution for language keys: __(AnyTranslationKey)__ or __(AnyTranslationKey|langfile)__
|
||||||
if (is_object($outputlangs))
|
if (is_object($outputlangs))
|
||||||
{
|
{
|
||||||
while (preg_match('/__\(([^\)]+)\)__/', $text, $reg))
|
while (preg_match('/__\(([^\)]+)\)__/', $text, $reg))
|
||||||
@@ -6151,8 +6152,8 @@ function make_substitutions($text, $substitutionarray, $outputlangs = null)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make substitution for constant keys. Must be after the substitution of translation, so if text of translation contains a constant,
|
// Make substitution for constant keys.
|
||||||
// it is also converted.
|
// Must be after the substitution of translation, so if the text of translation contains a string __[xxx]__, it is also converted.
|
||||||
while (preg_match('/__\[([^\]]+)\]__/', $text, $reg))
|
while (preg_match('/__\[([^\]]+)\]__/', $text, $reg))
|
||||||
{
|
{
|
||||||
$msgishtml = 0;
|
$msgishtml = 0;
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ foreach($object->fields as $key => $val)
|
|||||||
|
|
||||||
print '<tr><td';
|
print '<tr><td';
|
||||||
print ' class="titlefield';
|
print ' class="titlefield';
|
||||||
if ($val['notnull'] > 0) print ' fieldrequired';
|
//if ($val['notnull'] > 0) print ' fieldrequired'; // No fieldrequired on the view output
|
||||||
if ($val['type'] == 'text' || $val['type'] == 'html') print ' tdtop';
|
if ($val['type'] == 'text' || $val['type'] == 'html') print ' tdtop';
|
||||||
print '">';
|
print '">';
|
||||||
if (! empty($val['help'])) print $form->textwithpicto($langs->trans($val['label']), $langs->trans($val['help']));
|
if (! empty($val['help'])) print $form->textwithpicto($langs->trans($val['label']), $langs->trans($val['help']));
|
||||||
|
|||||||
@@ -103,6 +103,7 @@ class EmailCollector extends CommonObject
|
|||||||
//'filter' => array('type'=>'text', 'label'=>'Filter', 'visible'=>1, 'enabled'=>1, 'position'=>105),
|
//'filter' => array('type'=>'text', 'label'=>'Filter', 'visible'=>1, 'enabled'=>1, 'position'=>105),
|
||||||
//'actiontodo' => array('type'=>'varchar(255)', 'label'=>'ActionToDo', 'visible'=>1, 'enabled'=>1, 'position'=>106),
|
//'actiontodo' => array('type'=>'varchar(255)', 'label'=>'ActionToDo', 'visible'=>1, 'enabled'=>1, 'position'=>106),
|
||||||
'target_directory' => array('type'=>'varchar(255)', 'label'=>'MailboxTargetDirectory', 'visible'=>1, 'enabled'=>1, 'position'=>110, 'notnull'=>0, 'comment'=>"Where to store messages once processed"),
|
'target_directory' => array('type'=>'varchar(255)', 'label'=>'MailboxTargetDirectory', 'visible'=>1, 'enabled'=>1, 'position'=>110, 'notnull'=>0, 'comment'=>"Where to store messages once processed"),
|
||||||
|
'maxemailpercollect' => array('type'=>'integer', 'label'=>'MaxEmailCollectPerCollect','visible'=>-1, 'enabled'=>1, 'position'=>111, 'default'=>100),
|
||||||
'datelastresult' => array('type'=>'datetime', 'label'=>'DateLastCollectResult', 'visible'=>1, 'enabled'=>'$action != "create" && $action != "edit"', 'position'=>121, 'notnull'=>-1,),
|
'datelastresult' => array('type'=>'datetime', 'label'=>'DateLastCollectResult', 'visible'=>1, 'enabled'=>'$action != "create" && $action != "edit"', 'position'=>121, 'notnull'=>-1,),
|
||||||
'codelastresult' => array('type'=>'varchar(16)', 'label'=>'CodeLastResult', 'visible'=>1, 'enabled'=>'$action != "create" && $action != "edit"', 'position'=>122, 'notnull'=>-1,),
|
'codelastresult' => array('type'=>'varchar(16)', 'label'=>'CodeLastResult', 'visible'=>1, 'enabled'=>'$action != "create" && $action != "edit"', 'position'=>122, 'notnull'=>-1,),
|
||||||
'lastresult' => array('type'=>'varchar(255)', 'label'=>'LastResult', 'visible'=>1, 'enabled'=>'$action != "create" && $action != "edit"', 'position'=>123, 'notnull'=>-1,),
|
'lastresult' => array('type'=>'varchar(255)', 'label'=>'LastResult', 'visible'=>1, 'enabled'=>'$action != "create" && $action != "edit"', 'position'=>123, 'notnull'=>-1,),
|
||||||
@@ -167,6 +168,7 @@ class EmailCollector extends CommonObject
|
|||||||
public $password;
|
public $password;
|
||||||
public $source_directory;
|
public $source_directory;
|
||||||
public $target_directory;
|
public $target_directory;
|
||||||
|
public $maxemailpercollect;
|
||||||
public $datelastresult;
|
public $datelastresult;
|
||||||
public $lastresult;
|
public $lastresult;
|
||||||
// END MODULEBUILDER PROPERTIES
|
// END MODULEBUILDER PROPERTIES
|
||||||
@@ -717,12 +719,6 @@ class EmailCollector extends CommonObject
|
|||||||
return $nberror;
|
return $nberror;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* overwitePropertiesOfObject
|
|
||||||
*
|
|
||||||
* @return int 0=OK, Nb of error if error
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* overwitePropertiesOfObject
|
* overwitePropertiesOfObject
|
||||||
*
|
*
|
||||||
@@ -755,7 +751,8 @@ class EmailCollector extends CommonObject
|
|||||||
}
|
}
|
||||||
if ($tmpclass && ($tmpclass != $object->element)) continue; // Property is for another type of object
|
if ($tmpclass && ($tmpclass != $object->element)) continue; // Property is for another type of object
|
||||||
|
|
||||||
if (property_exists($object, $tmpproperty) || preg_match('/^options_/', $tmpproperty))
|
//if (property_exists($object, $tmpproperty) || preg_match('/^options_/', $tmpproperty))
|
||||||
|
if ($tmpproperty)
|
||||||
{
|
{
|
||||||
$sourcestring='';
|
$sourcestring='';
|
||||||
$sourcefield='';
|
$sourcefield='';
|
||||||
@@ -782,8 +779,12 @@ class EmailCollector extends CommonObject
|
|||||||
if ($sourcestring)
|
if ($sourcestring)
|
||||||
{
|
{
|
||||||
$regforval=array();
|
$regforval=array();
|
||||||
//var_dump($regexstring);var_dump($sourcestring);
|
$regexoptions='';
|
||||||
if (preg_match('/'.$regexstring.'/ms', $sourcestring, $regforval))
|
if (strtolower($sourcefield) == 'body') $regexoptions='ms'; // The m means ^ and $ char is valid at each new line. The s means the char '.' is valid for new lines char too
|
||||||
|
if (strtolower($sourcefield) == 'header') $regexoptions='m'; // The m means ^ and $ char is valid at each new line.
|
||||||
|
|
||||||
|
//var_dump($tmpproperty.' - '.$regexstring.' - '.$regexoptions.' - '.$sourcestring);
|
||||||
|
if (preg_match('/'.$regexstring.'/'.$regexoptions, $sourcestring, $regforval))
|
||||||
{
|
{
|
||||||
//var_dump($regforval[1]);exit;
|
//var_dump($regforval[1]);exit;
|
||||||
// Overwrite param $tmpproperty
|
// Overwrite param $tmpproperty
|
||||||
@@ -794,7 +795,6 @@ class EmailCollector extends CommonObject
|
|||||||
// Regex not found
|
// Regex not found
|
||||||
$object->$tmpproperty = null;
|
$object->$tmpproperty = null;
|
||||||
}
|
}
|
||||||
//var_dump($object->$tmpproperty);exit;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -806,8 +806,27 @@ class EmailCollector extends CommonObject
|
|||||||
}
|
}
|
||||||
elseif (preg_match('/^SET:(.*)$/', $valueforproperty, $reg))
|
elseif (preg_match('/^SET:(.*)$/', $valueforproperty, $reg))
|
||||||
{
|
{
|
||||||
if (preg_match('/^options_/', $tmpproperty)) $object->array_options[preg_replace('/^options_/', '', $tmpproperty)] = $reg[1];
|
$valuetouse = $reg[1];
|
||||||
else $object->$tmpproperty = $reg[1];
|
$substitutionarray=array();
|
||||||
|
$matcharray=array();
|
||||||
|
preg_match_all('/__([a-z0-9]+(?:_[a-z0-9]+)?)__/i', $valuetouse, $matcharray);
|
||||||
|
//var_dump($tmpproperty.' - '.$object->$tmpproperty.' - '.$valuetouse); var_dump($matcharray);
|
||||||
|
if (is_array($matcharray[1])) // $matcharray[1] is array with list of substitution key found without the __
|
||||||
|
{
|
||||||
|
foreach($matcharray[1] as $keytoreplace)
|
||||||
|
{
|
||||||
|
if ($keytoreplace && isset($object->$keytoreplace))
|
||||||
|
{
|
||||||
|
$substitutionarray['__'.$keytoreplace.'__']=$object->$keytoreplace;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//var_dump($substitutionarray);
|
||||||
|
dol_syslog(var_export($substitutionarray, true));
|
||||||
|
//var_dump($substitutionarray);
|
||||||
|
$valuetouse = make_substitutions($valuetouse, $substitutionarray);
|
||||||
|
if (preg_match('/^options_/', $tmpproperty)) $object->array_options[preg_replace('/^options_/', '', $tmpproperty)] = $valuetouse;
|
||||||
|
else $object->$tmpproperty = $valuetouse;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -887,7 +906,8 @@ class EmailCollector extends CommonObject
|
|||||||
$host=dol_getprefix('email');
|
$host=dol_getprefix('email');
|
||||||
|
|
||||||
// Define the IMAP search string
|
// Define the IMAP search string
|
||||||
// See https://tools.ietf.org/html/rfc3501#section-6.4.4
|
// See https://tools.ietf.org/html/rfc3501#section-6.4.4 for IMAPv4 (PHP not yet compatible)
|
||||||
|
// See https://tools.ietf.org/html/rfc1064 page 13 for IMAPv2
|
||||||
//$search='ALL';
|
//$search='ALL';
|
||||||
$search='UNDELETED'; // Seems not supported by some servers
|
$search='UNDELETED'; // Seems not supported by some servers
|
||||||
$searchhead='';
|
$searchhead='';
|
||||||
@@ -905,8 +925,13 @@ class EmailCollector extends CommonObject
|
|||||||
if ($rule['type'] == 'body') $search.=($search?' ':'').'BODY "'.str_replace('"', '', $rule['rulevalue']).'"';
|
if ($rule['type'] == 'body') $search.=($search?' ':'').'BODY "'.str_replace('"', '', $rule['rulevalue']).'"';
|
||||||
if ($rule['type'] == 'header') $search.=($search?' ':'').'HEADER '.$rule['rulevalue'];
|
if ($rule['type'] == 'header') $search.=($search?' ':'').'HEADER '.$rule['rulevalue'];
|
||||||
|
|
||||||
|
if ($rule['type'] == 'notinsubject') $search.=($search?' ':'').'SUBJECT NOT "'.str_replace('"', '', $rule['rulevalue']).'"';
|
||||||
|
if ($rule['type'] == 'notinbody') $search.=($search?' ':'').'BODY NOT "'.str_replace('"', '', $rule['rulevalue']).'"';
|
||||||
|
|
||||||
if ($rule['type'] == 'seen') $search.=($search?' ':'').'SEEN';
|
if ($rule['type'] == 'seen') $search.=($search?' ':'').'SEEN';
|
||||||
if ($rule['type'] == 'unseen') $search.=($search?' ':'').'UNSEEN';
|
if ($rule['type'] == 'unseen') $search.=($search?' ':'').'UNSEEN';
|
||||||
|
if ($rule['type'] == 'unanswered') $search.=($search?' ':'').'UNANSWERED';
|
||||||
|
if ($rule['type'] == 'answered') $search.=($search?' ':'').'ANSWERED';
|
||||||
if ($rule['type'] == 'smaller') $search.=($search?' ':'').'SMALLER "'.str_replace('"', '', $rule['rulevalue']).'"';
|
if ($rule['type'] == 'smaller') $search.=($search?' ':'').'SMALLER "'.str_replace('"', '', $rule['rulevalue']).'"';
|
||||||
if ($rule['type'] == 'larger') $search.=($search?' ':'').'LARGER "'.str_replace('"', '', $rule['rulevalue']).'"';
|
if ($rule['type'] == 'larger') $search.=($search?' ':'').'LARGER "'.str_replace('"', '', $rule['rulevalue']).'"';
|
||||||
|
|
||||||
@@ -945,9 +970,87 @@ class EmailCollector extends CommonObject
|
|||||||
// Loop on each email found
|
// Loop on each email found
|
||||||
if (! $error && ! empty($arrayofemail) && count($arrayofemail) > 0)
|
if (! $error && ! empty($arrayofemail) && count($arrayofemail) > 0)
|
||||||
{
|
{
|
||||||
|
// Loop to get part html and plain
|
||||||
|
/*
|
||||||
|
0 multipart/mixed
|
||||||
|
1 multipart/alternative
|
||||||
|
1.1 text/plain
|
||||||
|
1.2 text/html
|
||||||
|
2 message/rfc822
|
||||||
|
2 multipart/mixed
|
||||||
|
2.1 multipart/alternative
|
||||||
|
2.1.1 text/plain
|
||||||
|
2.1.2 text/html
|
||||||
|
2.2 message/rfc822
|
||||||
|
2.2 multipart/alternative
|
||||||
|
2.2.1 text/plain
|
||||||
|
2.2.2 text/html
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* create_part_array
|
||||||
|
*
|
||||||
|
* @param Object $structure Structure
|
||||||
|
* @param string $prefix prefix
|
||||||
|
* @return array Array with number and object
|
||||||
|
*/
|
||||||
|
/*function createPartArray($structure, $prefix = "")
|
||||||
|
{
|
||||||
|
//print_r($structure);
|
||||||
|
$part_array=array();
|
||||||
|
if (count($structure->parts) > 0) { // There some sub parts
|
||||||
|
foreach ($structure->parts as $count => $part) {
|
||||||
|
addPartToArray($part, $prefix.($count+1), $part_array);
|
||||||
|
}
|
||||||
|
}else{ // Email does not have a seperate mime attachment for text
|
||||||
|
$part_array[] = array('part_number' => $prefix.'1', 'part_object' => $structure);
|
||||||
|
}
|
||||||
|
return $part_array;
|
||||||
|
}*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sub function for createPartArray(). Only called by createPartArray() and itself.
|
||||||
|
*
|
||||||
|
* @param Object $obj Structure
|
||||||
|
* @param string $partno Part no
|
||||||
|
* @param array $part_array array
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
/*function addPartToArray($obj, $partno, &$part_array)
|
||||||
|
{
|
||||||
|
$part_array[] = array('part_number' => $partno, 'part_object' => $obj);
|
||||||
|
if ($obj->type == 2) { // Check to see if the part is an attached email message, as in the RFC-822 type
|
||||||
|
//print_r($obj);
|
||||||
|
if (array_key_exists('parts', $obj)) { // Check to see if the email has parts
|
||||||
|
foreach ($obj->parts as $count => $part) {
|
||||||
|
// Iterate here again to compensate for the broken way that imap_fetchbody() handles attachments
|
||||||
|
if (count($part->parts) > 0) {
|
||||||
|
foreach ($part->parts as $count2 => $part2) {
|
||||||
|
addPartToArray($part2, $partno.".".($count2+1), $part_array);
|
||||||
|
}
|
||||||
|
}else{ // Attached email does not have a seperate mime attachment for text
|
||||||
|
$part_array[] = array('part_number' => $partno.'.'.($count+1), 'part_object' => $obj);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}else{ // Not sure if this is possible
|
||||||
|
$part_array[] = array('part_number' => $partno.'.1', 'part_object' => $obj);
|
||||||
|
}
|
||||||
|
}else{ // If there are more sub-parts, expand them out.
|
||||||
|
if (array_key_exists('parts', $obj)) {
|
||||||
|
foreach ($obj->parts as $count => $p) {
|
||||||
|
addPartToArray($p, $partno.".".($count+1), $part_array);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}*/
|
||||||
|
|
||||||
|
dol_syslog("Start of loop on email", LOG_INFO, 1);
|
||||||
|
|
||||||
foreach($arrayofemail as $imapemail)
|
foreach($arrayofemail as $imapemail)
|
||||||
{
|
{
|
||||||
if ($nbemailprocessed > 100) break; // Do not process more than 100 email per launch
|
if ($nbemailprocessed > 1000)
|
||||||
|
{
|
||||||
|
break; // Do not process more than 1000 email per launch (this is a different protection than maxnbcollectedpercollect
|
||||||
|
}
|
||||||
|
|
||||||
$header = imap_fetchheader($connection, $imapemail, 0);
|
$header = imap_fetchheader($connection, $imapemail, 0);
|
||||||
$matches=array();
|
$matches=array();
|
||||||
@@ -988,125 +1091,63 @@ class EmailCollector extends CommonObject
|
|||||||
|
|
||||||
$this->db->begin();
|
$this->db->begin();
|
||||||
|
|
||||||
//$message = imap_body($connection, $imapemail, 0);
|
// GET Email meta datas
|
||||||
$overview = imap_fetch_overview($connection, $imapemail, 0);
|
$overview = imap_fetch_overview($connection, $imapemail, 0);
|
||||||
|
|
||||||
|
dol_syslog("** Process email - msgid=".$overview[0]->message_id." date=".dol_print_date($overview[0]->udate, 'dayrfc', 'gmt')." subject=".$overview[0]->subject);
|
||||||
|
|
||||||
|
// Parse IMAP email structure
|
||||||
|
global $htmlmsg, $plainmsg, $charset, $attachments;
|
||||||
|
$this->getmsg($connection, $imapemail);
|
||||||
|
|
||||||
|
//$htmlmsg,$plainmsg,$charset,$attachments
|
||||||
|
$messagetext = $plainmsg ? $plainmsg : dol_string_nohtmltag($htmlmsg, 0);
|
||||||
|
/*var_dump($plainmsg);
|
||||||
|
var_dump($htmlmsg);
|
||||||
|
var_dump($messagetext);*/
|
||||||
|
/*var_dump($charset);
|
||||||
|
var_dump($attachments);
|
||||||
|
exit;*/
|
||||||
|
|
||||||
|
// Parse IMAP email structure
|
||||||
|
/*
|
||||||
$structure = imap_fetchstructure($connection, $imapemail, 0);
|
$structure = imap_fetchstructure($connection, $imapemail, 0);
|
||||||
|
|
||||||
$partplain = $parthtml = -1;
|
$partplain = $parthtml = -1;
|
||||||
// Loop to get part html and plain
|
$encodingplain = $encodinghtml = '';
|
||||||
/*
|
|
||||||
0 multipart/mixed
|
|
||||||
1 multipart/alternative
|
|
||||||
1.1 text/plain
|
|
||||||
1.2 text/html
|
|
||||||
2 message/rfc822
|
|
||||||
2 multipart/mixed
|
|
||||||
2.1 multipart/alternative
|
|
||||||
2.1.1 text/plain
|
|
||||||
2.1.2 text/html
|
|
||||||
2.2 message/rfc822
|
|
||||||
2.2 multipart/alternative
|
|
||||||
2.2.1 text/plain
|
|
||||||
2.2.2 text/html
|
|
||||||
*/
|
|
||||||
/**
|
|
||||||
* create_part_array
|
|
||||||
*
|
|
||||||
* @param Object $structure Structure
|
|
||||||
* @param string $prefix prefix
|
|
||||||
* @return array Array with number and object
|
|
||||||
*/
|
|
||||||
function createPartArray($structure, $prefix = "")
|
|
||||||
{
|
|
||||||
//print_r($structure);
|
|
||||||
$part_array=array();
|
|
||||||
if (count($structure->parts) > 0) { // There some sub parts
|
|
||||||
foreach ($structure->parts as $count => $part) {
|
|
||||||
add_part_to_array($part, $prefix.($count+1), $part_array);
|
|
||||||
}
|
|
||||||
}else{ // Email does not have a seperate mime attachment for text
|
|
||||||
$part_array[] = array('part_number' => $prefix.'1', 'part_object' => $obj);
|
|
||||||
}
|
|
||||||
return $part_array;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sub function for createPartArray(). Only called by createPartArray() and itself.
|
|
||||||
*
|
|
||||||
* @param Object $obj Structure
|
|
||||||
* @param string $partno Part no
|
|
||||||
* @param array $part_array array
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
function addPartToArray($obj, $partno, &$part_array)
|
|
||||||
{
|
|
||||||
$part_array[] = array('part_number' => $partno, 'part_object' => $obj);
|
|
||||||
if ($obj->type == 2) { // Check to see if the part is an attached email message, as in the RFC-822 type
|
|
||||||
//print_r($obj);
|
|
||||||
if (array_key_exists('parts', $obj)) { // Check to see if the email has parts
|
|
||||||
foreach ($obj->parts as $count => $part) {
|
|
||||||
// Iterate here again to compensate for the broken way that imap_fetchbody() handles attachments
|
|
||||||
if (count($part->parts) > 0) {
|
|
||||||
foreach ($part->parts as $count2 => $part2) {
|
|
||||||
addPartToArray($part2, $partno.".".($count2+1), $part_array);
|
|
||||||
}
|
|
||||||
}else{ // Attached email does not have a seperate mime attachment for text
|
|
||||||
$part_array[] = array('part_number' => $partno.'.'.($count+1), 'part_object' => $obj);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}else{ // Not sure if this is possible
|
|
||||||
$part_array[] = array('part_number' => $partno.'.1', 'part_object' => $obj);
|
|
||||||
}
|
|
||||||
}else{ // If there are more sub-parts, expand them out.
|
|
||||||
if (array_key_exists('parts', $obj)) {
|
|
||||||
foreach ($obj->parts as $count => $p) {
|
|
||||||
addPartToArray($p, $partno.".".($count+1), $part_array);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$result = createPartArray($structure, '');
|
$result = createPartArray($structure, '');
|
||||||
//var_dump($result);exit;
|
|
||||||
foreach($result as $part)
|
foreach($result as $part)
|
||||||
{
|
{
|
||||||
if ($part['part_object']->subtype == 'HTML') $parthtml=$part['part_number'];
|
// $part['part_object']->type seems 0 for content
|
||||||
if ($part['part_object']->subtype == 'PLAIN') $partplain=$part['part_number'];
|
// $part['part_object']->type seems 5 for attachment
|
||||||
|
if (empty($part['part_object'])) continue;
|
||||||
|
if ($part['part_object']->subtype == 'HTML')
|
||||||
|
{
|
||||||
|
$parthtml=$part['part_number'];
|
||||||
|
if ($part['part_object']->encoding == 4)
|
||||||
|
{
|
||||||
|
$encodinghtml = 'aaa';
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
if ($part['part_object']->subtype == 'PLAIN')
|
||||||
|
{
|
||||||
|
$partplain=$part['part_number'];
|
||||||
|
if ($part['part_object']->encoding == 4)
|
||||||
|
{
|
||||||
|
$encodingplain = 'rr';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//var_dump($result); var_dump($partplain); var_dump($parthtml);
|
||||||
|
|
||||||
/* OLD CODE to get parthtml and partplain
|
var_dump($structure);
|
||||||
if (count($structure->parts) > 0) { // There some sub parts
|
|
||||||
foreach($structure->parts as $key => $part)
|
|
||||||
{
|
|
||||||
if ($part->subtype == 'HTML') $parthtml=($key+1); // For example: $parthtml = 1 or 2
|
|
||||||
if ($part->subtype == 'PLAIN') $partplain=($key+1);
|
|
||||||
if ($part->subtype == 'ALTERNATIVE')
|
|
||||||
{
|
|
||||||
if (count($part->parts) > 0)
|
|
||||||
{
|
|
||||||
foreach($part->parts as $key2 => $part2)
|
|
||||||
{
|
|
||||||
if ($part2->subtype == 'HTML') $parthtml=($key+1).'.'.($key2+1); // For example: $parthtml = 1.1 or 1.2
|
|
||||||
if ($part2->subtype == 'PLAIN') $partplain=($key+1).'.'.($key2+1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
$partplain=($key+1).'.1';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
$partplain=1;
|
|
||||||
}*/
|
|
||||||
|
|
||||||
/*var_dump($structure);
|
|
||||||
var_dump($parthtml);
|
var_dump($parthtml);
|
||||||
var_dump($partplain);*/
|
var_dump($partplain);
|
||||||
|
|
||||||
$messagetext = imap_fetchbody($connection, $imapemail, ($parthtml != '-1' ? $parthtml : ($partplain != '-1' ? $partplain : 1)), FT_PEEK);
|
$messagetext = imap_fetchbody($connection, $imapemail, ($parthtml != '-1' ? $parthtml : ($partplain != '-1' ? $partplain : 1)), FT_PEEK);
|
||||||
|
*/
|
||||||
|
|
||||||
//var_dump($messagetext);
|
//var_dump($messagetext);
|
||||||
//var_dump($structure->parts[0]->parts);
|
//var_dump($structure->parts[0]->parts);
|
||||||
@@ -1282,12 +1323,12 @@ class EmailCollector extends CommonObject
|
|||||||
elseif ($operation['type'] == 'ticket') $descriptiontitle = $langs->trans("TicketCreatedByEmailCollector", $msgid);
|
elseif ($operation['type'] == 'ticket') $descriptiontitle = $langs->trans("TicketCreatedByEmailCollector", $msgid);
|
||||||
else $descriptiontitle = $langs->trans("ActionAC_".$actioncode).' - '.$langs->trans("MailFrom").' '.$from;
|
else $descriptiontitle = $langs->trans("ActionAC_".$actioncode).' - '.$langs->trans("MailFrom").' '.$from;
|
||||||
|
|
||||||
$descriptionmeta = dol_concatdesc($descriptionmeta, $langs->trans("Topic").' : '.$subject);
|
$descriptionmeta = dol_concatdesc($descriptionmeta, $langs->trans("MailTopic").' : '.dol_escape_htmltag($subject));
|
||||||
$descriptionmeta = dol_concatdesc($descriptionmeta, $langs->trans("From").' : '.$fromstring);
|
$descriptionmeta = dol_concatdesc($descriptionmeta, $langs->trans("MailFrom").($langs->trans("MailFrom") != 'From' ? ' (From)':'').' : '.dol_escape_htmltag($fromstring));
|
||||||
if ($sender) $descriptionmeta = dol_concatdesc($descriptionmeta, $langs->trans("Sender").' : '.$sender);
|
if ($sender) $descriptionmeta = dol_concatdesc($descriptionmeta, $langs->trans("Sender").($langs->trans("Sender") != 'Sender' ? ' (Sender)':'').' : '.dol_escape_htmltag($sender));
|
||||||
$descriptionmeta = dol_concatdesc($descriptionmeta, $langs->trans("To").' : '.$to);
|
$descriptionmeta = dol_concatdesc($descriptionmeta, $langs->trans("MailTo").($langs->trans("MailTo") != 'To' ? ' (To)':'').' : '.dol_escape_htmltag($to));
|
||||||
//if ($cc) $descriptionmeta = dol_concatdesc($descriptionmeta, $langs->trans("Cc").' : '.$cc);
|
if ($sendtocc) $descriptionmeta = dol_concatdesc($descriptionmeta, $langs->trans("MailCC").($langs->trans("MailCC") != 'CC' ? ' (CC)':'').' : '.dol_escape_htmltag($sendtocc));
|
||||||
//if ($bcc) $descriptionmeta = dol_concatdesc($descriptionmeta, $langs->trans("Bcc").' : '.$bcc);
|
//if ($bcc) $descriptionmeta = dol_concatdesc($descriptionmeta, $langs->trans("Bcc").' : '.dol_escape_htmltag($bcc));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Search and create thirdparty
|
// Search and create thirdparty
|
||||||
@@ -1521,12 +1562,12 @@ class EmailCollector extends CommonObject
|
|||||||
$percent_opp_status = dol_getIdFromCode($this->db, 'PROSP', 'c_lead_status', 'code', 'percent');
|
$percent_opp_status = dol_getIdFromCode($this->db, 'PROSP', 'c_lead_status', 'code', 'percent');
|
||||||
|
|
||||||
$projecttocreate->title = $subject;
|
$projecttocreate->title = $subject;
|
||||||
$projecttocreate->date_start = $now;
|
$projecttocreate->date_start = $date;
|
||||||
$projecttocreate->date_end = '';
|
$projecttocreate->date_end = '';
|
||||||
$projecttocreate->opp_status = $id_opp_status;
|
$projecttocreate->opp_status = $id_opp_status;
|
||||||
$projecttocreate->opp_percent = $percent_opp_status;
|
$projecttocreate->opp_percent = $percent_opp_status;
|
||||||
$projecttocreate->description = dol_concatdesc(dolGetFirstLineOfText(dol_string_nohtmltag($description, 2), 10), '...'.$langs->transnoentities("SeePrivateNote").'...');
|
$projecttocreate->description = dol_concatdesc(dolGetFirstLineOfText(dol_string_nohtmltag($description, 2), 10), '...'.$langs->transnoentities("SeePrivateNote").'...');
|
||||||
$projecttocreate->note_private = dol_concatdesc($descriptionfull, dol_string_nohtmltag($descriptionfull, 2));
|
$projecttocreate->note_private = $descriptionfull;
|
||||||
$projecttocreate->entity = $conf->entity;
|
$projecttocreate->entity = $conf->entity;
|
||||||
|
|
||||||
// Get next project Ref
|
// Get next project Ref
|
||||||
@@ -1616,11 +1657,12 @@ class EmailCollector extends CommonObject
|
|||||||
$tickettocreate->severity_code = 0;
|
$tickettocreate->severity_code = 0;
|
||||||
$tickettocreate->origin_email = $from;
|
$tickettocreate->origin_email = $from;
|
||||||
$tickettocreate->fk_user_create = $user->id;
|
$tickettocreate->fk_user_create = $user->id;
|
||||||
$tickettocreate->entity = $conf->entity;
|
|
||||||
$tickettocreate->datec = $date;
|
$tickettocreate->datec = $date;
|
||||||
$tickettocreate->fk_project = $projectstatic->id;
|
$tickettocreate->fk_project = $projectstatic->id;
|
||||||
$tickettocreate->fk_soc = $thirdpartystatic->id;
|
$tickettocreate->fk_soc = $thirdpartystatic->id;
|
||||||
$tickettocreate->notify_tiers_at_create = 0;
|
$tickettocreate->notify_tiers_at_create = 0;
|
||||||
|
$tickettocreate->note_private = $descriptionfull;
|
||||||
|
$tickettocreate->entity = $conf->entity;
|
||||||
//$tickettocreate->fk_contact = $contactstatic->id;
|
//$tickettocreate->fk_contact = $contactstatic->id;
|
||||||
|
|
||||||
// Get next project Ref
|
// Get next project Ref
|
||||||
@@ -1709,12 +1751,26 @@ class EmailCollector extends CommonObject
|
|||||||
$errorforemail++;
|
$errorforemail++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unset($objectemail);
|
||||||
|
unset($projectstatic);
|
||||||
|
unset($thirdpartystatic);
|
||||||
|
unset($contactstatic);
|
||||||
|
|
||||||
|
$nbemailprocessed++;
|
||||||
|
|
||||||
if (! $errorforemail)
|
if (! $errorforemail)
|
||||||
{
|
{
|
||||||
$nbactiondone += $nbactiondoneforemail;
|
$nbactiondone += $nbactiondoneforemail;
|
||||||
$nbemailok++;
|
$nbemailok++;
|
||||||
|
|
||||||
$this->db->commit();
|
$this->db->commit();
|
||||||
|
|
||||||
|
// Stop the loop to process email if we reach maximum collected per collect
|
||||||
|
if ($this->maxemailpercollect > 0 && $nbemailok >= $this->maxemailpercollect)
|
||||||
|
{
|
||||||
|
dol_syslog("EmailCollect::doCollectOneCollector We reach maximum of ".$nbemailok." collected with success, so we stop this collector now.");
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -1722,16 +1778,11 @@ class EmailCollector extends CommonObject
|
|||||||
|
|
||||||
$this->db->rollback();
|
$this->db->rollback();
|
||||||
}
|
}
|
||||||
|
|
||||||
$nbemailprocessed++;
|
|
||||||
|
|
||||||
unset($objectemail);
|
|
||||||
unset($projectstatic);
|
|
||||||
unset($thirdpartystatic);
|
|
||||||
unset($contactstatic);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$output=$langs->trans('XEmailsDoneYActionsDone', $nbemailprocessed, $nbemailok, $nbactiondone);
|
$output=$langs->trans('XEmailsDoneYActionsDone', $nbemailprocessed, $nbemailok, $nbactiondone);
|
||||||
|
|
||||||
|
dol_syslog("End of loop on emails", LOG_INFO, -1);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -1757,4 +1808,134 @@ class EmailCollector extends CommonObject
|
|||||||
|
|
||||||
return $error?-1:1;
|
return $error?-1:1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Loop to get part html and plain. Code found on PHP imap_fetchstructure documentation
|
||||||
|
|
||||||
|
/**
|
||||||
|
* getmsg
|
||||||
|
*
|
||||||
|
* @param Object $mbox Structure
|
||||||
|
* @param string $mid prefix
|
||||||
|
* @return array Array with number and object
|
||||||
|
*/
|
||||||
|
function getmsg($mbox, $mid) {
|
||||||
|
// input $mbox = IMAP stream, $mid = message id
|
||||||
|
// output all the following:
|
||||||
|
global $charset,$htmlmsg,$plainmsg,$attachments;
|
||||||
|
$htmlmsg = $plainmsg = $charset = '';
|
||||||
|
$attachments = array();
|
||||||
|
|
||||||
|
// HEADER
|
||||||
|
//$h = imap_header($mbox,$mid);
|
||||||
|
// add code here to get date, from, to, cc, subject...
|
||||||
|
|
||||||
|
// BODY
|
||||||
|
$s = imap_fetchstructure($mbox,$mid);
|
||||||
|
|
||||||
|
if (!$s->parts) // simple
|
||||||
|
$this->getpart($mbox,$mid,$s,0); // pass 0 as part-number
|
||||||
|
else { // multipart: cycle through each part
|
||||||
|
foreach ($s->parts as $partno0=>$p)
|
||||||
|
{
|
||||||
|
$this->getpart($mbox, $mid, $p, $partno0+1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* partno string
|
||||||
|
0 multipart/mixed
|
||||||
|
1 multipart/alternative
|
||||||
|
1.1 text/plain
|
||||||
|
1.2 text/html
|
||||||
|
2 message/rfc822
|
||||||
|
2 multipart/mixed
|
||||||
|
2.1 multipart/alternative
|
||||||
|
2.1.1 text/plain
|
||||||
|
2.1.2 text/html
|
||||||
|
2.2 message/rfc822
|
||||||
|
2.2 multipart/alternative
|
||||||
|
2.2.1 text/plain
|
||||||
|
2.2.2 text/html
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* Sub function for getpart(). Only called by createPartArray() and itself.
|
||||||
|
*
|
||||||
|
* @param Object $mbox Structure
|
||||||
|
* @param string $mid Part no
|
||||||
|
* @param Object $p Object p
|
||||||
|
* @param string $partno Partno
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
private function getpart($mbox, $mid, $p, $partno) {
|
||||||
|
// $partno = '1', '2', '2.1', '2.1.3', etc for multipart, 0 if simple
|
||||||
|
global $htmlmsg,$plainmsg,$charset,$attachments;
|
||||||
|
|
||||||
|
// DECODE DATA
|
||||||
|
$data = ($partno)?
|
||||||
|
imap_fetchbody($mbox,$mid,$partno): // multipart
|
||||||
|
imap_body($mbox,$mid); // simple
|
||||||
|
// Any part may be encoded, even plain text messages, so check everything.
|
||||||
|
if ($p->encoding==4)
|
||||||
|
$data = quoted_printable_decode($data);
|
||||||
|
elseif ($p->encoding==3)
|
||||||
|
$data = base64_decode($data);
|
||||||
|
|
||||||
|
// PARAMETERS
|
||||||
|
// get all parameters, like charset, filenames of attachments, etc.
|
||||||
|
$params = array();
|
||||||
|
if ($p->parameters)
|
||||||
|
{
|
||||||
|
foreach ($p->parameters as $x)
|
||||||
|
{
|
||||||
|
$params[strtolower($x->attribute)] = $x->value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ($p->dparameters)
|
||||||
|
{
|
||||||
|
foreach ($p->dparameters as $x)
|
||||||
|
{
|
||||||
|
$params[strtolower($x->attribute)] = $x->value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ATTACHMENT
|
||||||
|
// Any part with a filename is an attachment,
|
||||||
|
// so an attached text file (type 0) is not mistaken as the message.
|
||||||
|
if ($params['filename'] || $params['name']) {
|
||||||
|
// filename may be given as 'Filename' or 'Name' or both
|
||||||
|
$filename = ($params['filename'])? $params['filename'] : $params['name'];
|
||||||
|
// filename may be encoded, so see imap_mime_header_decode()
|
||||||
|
$attachments[$filename] = $data; // this is a problem if two files have same name
|
||||||
|
}
|
||||||
|
|
||||||
|
// TEXT
|
||||||
|
if ($p->type==0 && $data) {
|
||||||
|
// Messages may be split in different parts because of inline attachments,
|
||||||
|
// so append parts together with blank row.
|
||||||
|
if (strtolower($p->subtype)=='plain')
|
||||||
|
$plainmsg .= trim($data) ."\n\n";
|
||||||
|
else
|
||||||
|
$htmlmsg .= $data ."<br><br>";
|
||||||
|
$charset = $params['charset']; // assume all parts are same charset
|
||||||
|
}
|
||||||
|
|
||||||
|
// EMBEDDED MESSAGE
|
||||||
|
// Many bounce notifications embed the original message as type 2,
|
||||||
|
// but AOL uses type 1 (multipart), which is not handled here.
|
||||||
|
// There are no PHP functions to parse embedded messages,
|
||||||
|
// so this just appends the raw source to the main message.
|
||||||
|
elseif ($p->type==2 && $data) {
|
||||||
|
$plainmsg .= $data."\n\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
// SUBPART RECURSION
|
||||||
|
if ($p->parts) {
|
||||||
|
foreach ($p->parts as $partno0=>$p2)
|
||||||
|
{
|
||||||
|
$this->getpart($mbox,$mid,$p2,$partno.'.'.($partno0+1)); // 1.2, 1.2.1, etc.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -159,7 +159,7 @@ class EmailCollectorFilter extends CommonObject
|
|||||||
$this->errors[]=$langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Type"));
|
$this->errors[]=$langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Type"));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (! in_array($this->type, array('seen','unseen','withtrackingid','withouttrackingid')) && empty($this->rulevalue))
|
if (! in_array($this->type, array('seen', 'unseen', 'unanswered', 'answered', 'withtrackingid', 'withouttrackingid')) && empty($this->rulevalue))
|
||||||
{
|
{
|
||||||
$langs->load("errors");
|
$langs->load("errors");
|
||||||
$this->errors[]=$langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("SearchString"));
|
$this->errors[]=$langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("SearchString"));
|
||||||
|
|||||||
@@ -285,6 +285,7 @@ ALTER TABLE llx_product ADD INDEX idx_product_fk_project (fk_project);
|
|||||||
ALTER TABLE llx_actioncomm ADD COLUMN calling_duration integer;
|
ALTER TABLE llx_actioncomm ADD COLUMN calling_duration integer;
|
||||||
|
|
||||||
ALTER TABLE llx_emailcollector_emailcollector ADD COLUMN datelastok datetime;
|
ALTER TABLE llx_emailcollector_emailcollector ADD COLUMN datelastok datetime;
|
||||||
|
ALTER TABLE llx_emailcollector_emailcollector ADD COLUMN maxemailpercollect integer DEFAULT 100;
|
||||||
|
|
||||||
DELETE FROM llx_const WHERE name = 'THEME_ELDY_USE_HOVER' AND value = '0';
|
DELETE FROM llx_const WHERE name = 'THEME_ELDY_USE_HOVER' AND value = '0';
|
||||||
DELETE FROM llx_const WHERE name = 'THEME_ELDY_USE_CHECKED' AND value = '0';
|
DELETE FROM llx_const WHERE name = 'THEME_ELDY_USE_CHECKED' AND value = '0';
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ CREATE TABLE llx_emailcollector_emailcollector(
|
|||||||
password varchar(128),
|
password varchar(128),
|
||||||
source_directory varchar(255) NOT NULL,
|
source_directory varchar(255) NOT NULL,
|
||||||
target_directory varchar(255),
|
target_directory varchar(255),
|
||||||
|
maxemailpercollect integer DEFAULT 100,
|
||||||
datelastresult datetime,
|
datelastresult datetime,
|
||||||
codelastresult varchar(16),
|
codelastresult varchar(16),
|
||||||
lastresult varchar(255),
|
lastresult varchar(255),
|
||||||
|
|||||||
@@ -72,6 +72,8 @@ UseSearchToSelectContactTooltip=Also if you have a large number of third parties
|
|||||||
DelaiedFullListToSelectCompany=Wait until a key is pressed before loading content of Third Parties combo list.<br>This may increase performance if you have a large number of third parties, but it is less convenient.
|
DelaiedFullListToSelectCompany=Wait until a key is pressed before loading content of Third Parties combo list.<br>This may increase performance if you have a large number of third parties, but it is less convenient.
|
||||||
DelaiedFullListToSelectContact=Wait until a key is pressed before loading content of Contact combo list.<br>This may increase performance if you have a large number of contacts, but it is less convenient)
|
DelaiedFullListToSelectContact=Wait until a key is pressed before loading content of Contact combo list.<br>This may increase performance if you have a large number of contacts, but it is less convenient)
|
||||||
NumberOfKeyToSearch=Number of characters to trigger search: %s
|
NumberOfKeyToSearch=Number of characters to trigger search: %s
|
||||||
|
NumberOfBytes=Number of Bytes
|
||||||
|
SearchString=Search string
|
||||||
NotAvailableWhenAjaxDisabled=Not available when Ajax disabled
|
NotAvailableWhenAjaxDisabled=Not available when Ajax disabled
|
||||||
AllowToSelectProjectFromOtherCompany=On document of a third party, can choose a project linked to another third party
|
AllowToSelectProjectFromOtherCompany=On document of a third party, can choose a project linked to another third party
|
||||||
JavascriptDisabled=JavaScript disabled
|
JavascriptDisabled=JavaScript disabled
|
||||||
@@ -1828,6 +1830,7 @@ EMailHost=Host of email IMAP server
|
|||||||
MailboxSourceDirectory=Mailbox source directory
|
MailboxSourceDirectory=Mailbox source directory
|
||||||
MailboxTargetDirectory=Mailbox target directory
|
MailboxTargetDirectory=Mailbox target directory
|
||||||
EmailcollectorOperations=Operations to do by collector
|
EmailcollectorOperations=Operations to do by collector
|
||||||
|
MaxEmailCollectPerCollect=Max number of emails collected per collect
|
||||||
CollectNow=Collect now
|
CollectNow=Collect now
|
||||||
ConfirmCloneEmailCollector=Are you sure you want to clone the Email collector %s ?
|
ConfirmCloneEmailCollector=Are you sure you want to clone the Email collector %s ?
|
||||||
DateLastCollectResult=Date latest collect tried
|
DateLastCollectResult=Date latest collect tried
|
||||||
|
|||||||
@@ -19,6 +19,8 @@ MailTopic=Email topic
|
|||||||
MailText=Message
|
MailText=Message
|
||||||
MailFile=Attached files
|
MailFile=Attached files
|
||||||
MailMessage=Email body
|
MailMessage=Email body
|
||||||
|
SubjectNotIn=Not in Subject
|
||||||
|
BodyNotIn=Not in Body
|
||||||
ShowEMailing=Show emailing
|
ShowEMailing=Show emailing
|
||||||
ListOfEMailings=List of emailings
|
ListOfEMailings=List of emailings
|
||||||
NewMailing=New emailing
|
NewMailing=New emailing
|
||||||
|
|||||||
Reference in New Issue
Block a user