mirror of
https://github.com/EGroupware/egroupware.git
synced 2024-11-21 23:43:17 +01:00
* Mail: new modus for vacation notice to not save message to INBOX and REST API to set vacation handling
This commit is contained in:
parent
7771710aee
commit
027ad398d6
@ -2312,8 +2312,8 @@ class CalDAV extends HTTP_WebDAV_Server
|
||||
'%3F' => '?',
|
||||
));
|
||||
|
||||
$ok = ($id || isset($_GET['add-member']) && $_SERVER['REQUEST_METHOD'] == 'POST') &&
|
||||
($user || $user === 0) && in_array($app,array('addressbook','calendar','infolog','principals'));
|
||||
$ok = ($id || isset($_GET['add-member']) && $_SERVER['REQUEST_METHOD'] === 'POST') &&
|
||||
($user || $user === 0) && self::app_handler($app);
|
||||
|
||||
if ($this->debug)
|
||||
{
|
||||
|
@ -1398,12 +1398,13 @@ class Imap extends Horde_Imap_Client_Socket implements Imap\PushIface
|
||||
/**
|
||||
* Set vacation message for given user
|
||||
*
|
||||
* @param int|string $_euser nummeric account_id or imap username
|
||||
* @param int|string $_euser numeric account_id or imap username
|
||||
* @param array $_vacation
|
||||
* @param string $_scriptName =null
|
||||
* @param string|null& $vacation_rule=null on return Sieve vacation rule
|
||||
* @return boolean
|
||||
*/
|
||||
public function setVacationUser($_euser, array $_vacation, $_scriptName=null)
|
||||
public function setVacationUser($_euser, array $_vacation, $_scriptName=null, string &$vacation_rule=null)
|
||||
{
|
||||
if ($this->debug) error_log(__METHOD__.' User:'.array2string($_euser).' Scriptname:'.array2string($_scriptName).' VacationMessage:'.array2string($_vacation));
|
||||
|
||||
@ -1418,7 +1419,7 @@ class Imap extends Horde_Imap_Client_Socket implements Imap\PushIface
|
||||
$this->scriptName =& $this->sieve->scriptName;
|
||||
$this->error =& $this->sieve->error;
|
||||
}
|
||||
$ret = $this->setVacation($_vacation, $_scriptName);
|
||||
$ret = $this->setVacation($_vacation, $_scriptName, $vacation_rule);
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
@ -184,15 +184,22 @@ class Script
|
||||
}
|
||||
break;
|
||||
case "vacation" :
|
||||
if (preg_match("/^ *#vacation&&(.*)&&(.*)&&(.*)&&(.*)&&(.*)/i",$line,$bits) ||
|
||||
if (preg_match("/^ *#vacation&&(.*)&&(.*)&&(.*)&&(.*)&&(.*)&&(.*)/i",$line,$bits) ||
|
||||
preg_match("/^ *#vacation&&(.*)&&(.*)&&(.*)&&(.*)&&(.*)/i",$line,$bits) ||
|
||||
preg_match("/^ *#vacation&&(.*)&&(.*)&&(.*)&&(.*)/i",$line,$bits)) {
|
||||
$vacation['days'] = $bits[1];
|
||||
$vaddresslist = preg_replace("/\"|\s/","",$bits[2]);
|
||||
$vaddresses = preg_split("/,/",$vaddresslist);
|
||||
$vacation['text'] = $bits[3];
|
||||
|
||||
// <crnl>s will be encoded as \\n. undo this.
|
||||
$vacation['text'] = preg_replace("/\\\\n/","\r\n",$vacation['text']);
|
||||
if (($vacation['text'] = $bits[3]) === 'false')
|
||||
{
|
||||
$vacation['text'] = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
// <crnl>s will be encoded as \\n. undo this.
|
||||
$vacation['text'] = preg_replace("/\\\\n/","\r\n",$vacation['text']);
|
||||
}
|
||||
$vacation['modus'] = $bits[6] ?? null;
|
||||
|
||||
if (strpos($bits[4],'-')!== false)
|
||||
{
|
||||
@ -245,8 +252,11 @@ class Script
|
||||
*
|
||||
* @param Sieve $connection
|
||||
* @param boolean $utf7imap_fileinto =false true: encode foldernames with utf7imap, default utf8
|
||||
* @param string|null& $vac_rule on return vacation-rule in sieve syntax
|
||||
* @param bool $throw_exceptions =false true: throw exception with error-message
|
||||
* @return bool false on error with error-message in $this->error
|
||||
*/
|
||||
function updateScript (Sieve $connection, $utf7imap_fileinto=false)
|
||||
function updateScript (Sieve $connection, $utf7imap_fileinto=false, &$vac_rule=null, bool $throw_exceptions=false)
|
||||
{
|
||||
#global $_SESSION,$default,$sieve;
|
||||
global $default,$sieve;
|
||||
@ -411,8 +421,8 @@ class Script
|
||||
|
||||
if ($this->vacation) {
|
||||
$vacation = $this->vacation;
|
||||
if (!$vacation['days']) $vacation['days'] = ($default->vacation_days ? $default->vacation_days:'');
|
||||
if (!$vacation['text']) $vacation['text'] = ($default->vacation_text ? $default->vacation_text:'');
|
||||
if (!$vacation['days']) $vacation['days'] = $default->vacation_days ?: '';
|
||||
if (!$vacation['text']) $vacation['text'] = $default->vacation_text ?: '';
|
||||
if (!$vacation['status']) $vacation['status'] = 'on';
|
||||
|
||||
// filter out invalid addresses.
|
||||
@ -430,11 +440,12 @@ class Script
|
||||
if (($vacation['status'] == 'on' && strlen(trim($vacation['text']))>0)|| $vacation['status'] == 'by_date') // +24*3600 to include the end_date day
|
||||
{
|
||||
$vacation_active = true;
|
||||
$vac_rule = '';
|
||||
if ($vacation['text'])
|
||||
{
|
||||
if ($this->extensions['regex'])
|
||||
{
|
||||
$newscriptbody .= "if header :regex ".'"X-Spam-Status" '.'"\\\\bYES\\\\b"'."{\n\tstop;\n}\n"; //stop vacation reply if it is spam
|
||||
$vac_rule .= "if header :regex " . '"X-Spam-Status" ' . '"\\\\bYES\\\\b"' . "{\n\tstop;\n}\n"; //stop vacation reply if it is spam
|
||||
$regexused = 1;
|
||||
}
|
||||
else
|
||||
@ -442,56 +453,64 @@ class Script
|
||||
// if there are no regex'es supported use a different Anti-Spam Rule: if X-Spam-Status holds
|
||||
// additional spamscore information (e.g. BAYES) this rule may prevent Vacation notification
|
||||
// TODO: refine rule without using regex
|
||||
$newscriptbody .= "if header :contains ".'"X-Spam-Status" '.'"YES"'."{\n\tstop;\n}\n"; //stop vacation reply if it is spam
|
||||
$vac_rule .= "if header :contains " . '"X-Spam-Status" ' . '"YES"' . "{\n\tstop;\n}\n"; //stop vacation reply if it is spam
|
||||
}
|
||||
}
|
||||
if (trim($vacation['forwards'])) {
|
||||
$if = array();
|
||||
foreach($vacation['addresses'] as $addr) {
|
||||
$if[] = 'address :contains ["To","TO","Cc","CC"] "'.trim($addr).'"';
|
||||
}
|
||||
$newscriptbody .= 'if anyof ('.implode(', ',$if).") {\n";
|
||||
foreach(preg_split('/, ?/',$vacation['forwards']) as $addr) {
|
||||
$newscriptbody .= "\tredirect \"".trim($addr)."\";\n";
|
||||
}
|
||||
$newscriptbody .= "\tkeep;\n}\n";
|
||||
}
|
||||
$vac_rule = "vacation :days " . $vacation['days'];
|
||||
$first = 1;
|
||||
if (!empty($vacation['addresses'][0]))
|
||||
if (trim($vacation['forwards']))
|
||||
{
|
||||
$vac_rule .= " :addresses [";
|
||||
foreach ($vacation['addresses'] as $vaddress) {
|
||||
$if = array();
|
||||
foreach ($vacation['addresses'] as $addr)
|
||||
{
|
||||
$if[] = 'address :contains ["To","TO","Cc","CC"] "' . trim($addr) . '"';
|
||||
}
|
||||
$vac_rule .= 'if anyof (' . implode(', ', $if) . ") {\n";
|
||||
foreach (preg_split('/, ?/', $vacation['forwards']) as $addr)
|
||||
{
|
||||
$vac_rule .= "\tredirect \"" . trim($addr) . "\";\n";
|
||||
}
|
||||
$vac_rule .= "\tkeep;\n}\n";
|
||||
}
|
||||
if (!isset($vacation['modus']) || $vacation['modus'] !== 'store')
|
||||
{
|
||||
$vac_rule .= "vacation :days " . $vacation['days'];
|
||||
$first = 1;
|
||||
if (!empty($vacation['addresses'][0]))
|
||||
{
|
||||
$vac_rule .= " :addresses [";
|
||||
foreach ($vacation['addresses'] as $vaddress)
|
||||
{
|
||||
if (!$first) $vac_rule .= ", ";
|
||||
$vac_rule .= "\"" . trim($vaddress) . "\"";
|
||||
$first = 0;
|
||||
}
|
||||
$vac_rule .= "] ";
|
||||
}
|
||||
$vac_rule .= "] ";
|
||||
$message = $vacation['text'];
|
||||
if ($vacation['status'] === 'by_date' && ($vacation['start_date'] || $vacation['end_date']))
|
||||
{
|
||||
$format_date = 'd M Y'; // see to it, that there is always a format, because if it is missing - no date will be output
|
||||
if (!empty($GLOBALS['egw_info']['user']['preferences']['common']['dateformat'])) $format_date = $GLOBALS['egw_info']['user']['preferences']['common']['dateformat'];
|
||||
$message = str_replace(array('$$start$$', '$$end$$'), array(
|
||||
date($format_date, $vacation['start_date']),
|
||||
date($format_date, $vacation['end_date']),
|
||||
), $message);
|
||||
}
|
||||
$vac_rule .= " text:\n" . $message . "\n.\n;\n\n";
|
||||
}
|
||||
$message = $vacation['text'];
|
||||
if ($vacation['status'] === 'by_date' && ($vacation['start_date'] || $vacation['end_date']))
|
||||
if (isset($vacation['modus']) && $vacation['modus'] === 'notice')
|
||||
{
|
||||
$format_date = 'd M Y'; // see to it, that there is always a format, because if it is missing - no date will be output
|
||||
if (!empty($GLOBALS['egw_info']['user']['preferences']['common']['dateformat'])) $format_date = $GLOBALS['egw_info']['user']['preferences']['common']['dateformat'];
|
||||
$message = str_replace(array('$$start$$','$$end$$'),array(
|
||||
date($format_date,$vacation['start_date']),
|
||||
date($format_date,$vacation['end_date']),
|
||||
),$message);
|
||||
$vac_rule .= "discard;\n";
|
||||
}
|
||||
$vac_rule .= " text:\n" . $message . "\n.\n;\n\n";
|
||||
if ($vacation['status'] === 'by_date' && $this->extensions['date'] && $vacation['start_date'] && $vacation['end_date'])
|
||||
{
|
||||
$newscriptbody .= "if allof (\n".
|
||||
$vac_rule = "if allof (\n".
|
||||
"currentdate :value \"ge\" \"date\" \"". date('Y-m-d', $vacation['start_date']) ."\",\n".
|
||||
"currentdate :value \"le\" \"date\" \"". date('Y-m-d', $vacation['end_date']) ."\")\n".
|
||||
"{\n".
|
||||
$vac_rule."\n".
|
||||
"}\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
$newscriptbody .= $vac_rule;
|
||||
}
|
||||
$newscriptbody .= $vac_rule;
|
||||
}
|
||||
|
||||
// update with any changes.
|
||||
@ -624,10 +643,11 @@ class Script
|
||||
$first = 0;
|
||||
}
|
||||
|
||||
$vacation['text'] = preg_replace("/\r?\n/","\\n",$vacation['text']);
|
||||
$vacation['text'] = $vacation['text'] === false ? 'false' : preg_replace("/\r?\n/","\\n", $vacation['text']);
|
||||
$newscriptfoot .= "&&" . $vacation['text'] . "&&" .
|
||||
($vacation['status']=='by_date' ? $vacation['start_date'].'-'.$vacation['end_date'] : $vacation['status']);
|
||||
if ($vacation['forwards']) $newscriptfoot .= '&&' . $vacation['forwards'];
|
||||
$newscriptfoot .= '&&' . ($vacation['forwards'] ?? '');
|
||||
if (!empty($vacation['modus'])) $newscriptfoot .= '&&' . $vacation['modus'];
|
||||
$newscriptfoot .= "\n";
|
||||
}
|
||||
if ($this->emailNotification) {
|
||||
@ -651,6 +671,7 @@ class Script
|
||||
$connection->installScript($this->name, $newscript, true);
|
||||
}
|
||||
catch (\Exception $e) {
|
||||
if ($throw_exceptions) throw $e;
|
||||
$this->errstr = 'updateScript: putscript failed: ' . $e->getMessage().($e->details?': '.$e->details:'');
|
||||
if ($regexused && !$this->extensions['regex']) $this->errstr .= " REGEX is not an supported CAPABILITY";
|
||||
error_log(__METHOD__.__LINE__.' # Error: ->'.$this->errstr);
|
||||
@ -661,4 +682,4 @@ class Script
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
@ -150,7 +150,7 @@ class Sieve extends Horde\ManageSieve
|
||||
* @param array $_vacation
|
||||
* @param string $_scriptName
|
||||
*/
|
||||
function setVacation(array $_vacation, $_scriptName=null)
|
||||
function setVacation(array $_vacation, $_scriptName=null, &$vaction_rule=null, $throw_exception=false)
|
||||
{
|
||||
if ($this->debug)
|
||||
{
|
||||
@ -159,7 +159,7 @@ class Sieve extends Horde\ManageSieve
|
||||
$script = $this->retrieveRules($_scriptName);
|
||||
$script->debug = $this->debug;
|
||||
$script->vacation = $_vacation;
|
||||
$ret = $script->updateScript($this);
|
||||
$ret = $script->updateScript($this, false, $vaction_rule, $throw_exception);
|
||||
$this->error = $script->errstr;
|
||||
return $ret;
|
||||
}
|
||||
@ -225,4 +225,4 @@ class Sieve extends Horde\ManageSieve
|
||||
|
||||
return $script;
|
||||
}
|
||||
}
|
||||
}
|
@ -133,4 +133,59 @@ Location: https://example.org/egroupware/groupdav.php/mail/attachment/<token>
|
||||
"location": "/mail/attachments/<filename>--xM35lY"
|
||||
}
|
||||
```
|
||||
</details>
|
||||
|
||||
- ```POST /mail[/<id>]/vacation``` enable or disable vacation message or forwarding
|
||||
|
||||
<details>
|
||||
<summary>Example: Setting a vacation message with given start- and end-date</summary>
|
||||
|
||||
The content of the POST request is a JSON encoded object with following attributes
|
||||
- ```status```: "on" (default, if not start/end), "off" or "by_date" (default, if start/end given)
|
||||
- ```start```: start-date "YYYY-mm-dd", or e.g. "+2days" (optional)
|
||||
- ```end```: end-date (last day of vacation) "YYYY-mm-dd" (optional)
|
||||
- ```text```: vacation notice to the sender (can container $$start$$ and $$end$$ placeholders)
|
||||
- ```modus```: "notice+store" (default) send vacation notice and store in INBOX, "notice": only send notice, "store": only store
|
||||
- ```forwards```: array of strings with (RFC882) email addresses (optional, default no forwarding)
|
||||
- ```addresses```: array of strings with (RFC882) email addresses (optional, default primary email address only)
|
||||
- ```days```: integer, after how many days should a sender get the vacation message again (optional, otherwise default is used)
|
||||
|
||||
> The ```POST``` request is handled like a ```PATCH```, only the given attributes are replaced, use null to unset them.
|
||||
|
||||
```
|
||||
curl -i https://example.org/egroupware/groupdav.php/mail/vacation --user <user> -X POST -H 'Content-Type: application/json' \
|
||||
--data-binary '{"message":"I'm away from $$start$$ to $$end$$, will respond when I'm back.","start":"2023-01-01","end":"2023-01-10"}'
|
||||
|
||||
HTTP/1.1 200 Ok
|
||||
|
||||
{
|
||||
"status": 200,
|
||||
"message": "Vacation handling stored"
|
||||
}
|
||||
```
|
||||
</details>
|
||||
|
||||
- ```GET /mail[/<id>]/vacation``` get current vacation message/handling
|
||||
|
||||
<details>
|
||||
<summary>Example: Querying the current vacation handling</summary>
|
||||
|
||||
For an explanation of the returned attributes of the returned object, see the POST request.
|
||||
|
||||
```
|
||||
curl -i https://example.org/egroupware/groupdav.php/mail/vacation --user <user> -H 'Accept: application/json'
|
||||
|
||||
HTTP/1.1 200 Ok
|
||||
|
||||
{
|
||||
"start":"2023-01-01",
|
||||
"end":"2023-01-10",
|
||||
"status": "by_date",
|
||||
"modus": "notice+store",
|
||||
"text":"I'm away from $$start$$ to $$end$$, will respond when I'm back.",
|
||||
"days": 5,
|
||||
"addresses": ["me@example.org","webmaster@example.org"],
|
||||
"forwards": ["hugo.meyer@example.org","sven@example.com"]
|
||||
}
|
||||
```
|
||||
</details>
|
@ -416,6 +416,7 @@ only name mail de Nur Name
|
||||
only needed for some servers, that do not return all folders on root level queries to retrieve all folders for that level mail de wird nur für bestimmte Server gebraucht, die NICHT alle Ordner für Root-Knoten-Abfragen zurückgeben (damit wird in diesem Fall explizit auf Ordner in den Prefixes der Namespaces geprüft)
|
||||
only one window mail de nur ein einziges Fenster
|
||||
only send message, do not copy a version of the message to the configured sent folder mail de Versende Nachricht, kopiere sie nicht in den konfigurierten Gesendet-Ordner
|
||||
only store message in inbox, do not send vacation notice mail de Nachricht nur im Posteingang speichern, keine Abwesenheitsnotiz versenden
|
||||
open in html mode mail de In HTML-Modus öffnen
|
||||
open in text mode mail de In Text-Modus öffnen
|
||||
open with collabora office mail de Mit Collabora Online öffnen
|
||||
@ -548,6 +549,8 @@ send a reject message: mail de Ablehnungs-E-Mail senden:
|
||||
send files as mail de Dateien versenden als
|
||||
send message and move to send folder (if configured) mail de Versende Nachricht und kopiere diese in den konfigurierten Gesendet-Ordner
|
||||
send message pgp encrypted: requires keys from all recipients! mail de Nachricht PGP-verschlüsselt senden: benötigt Schlüssel von allen Empfängern!
|
||||
send only a vacation notice, do not store message in inbox mail de Sende nur eine Abwesenheitsnotiz, die Nachricht selbst NICHT im Posteingang speichern
|
||||
send vacation notice and store message in inbox mail de Sende eine Abwesenheitsnotiz und speichere die Mail im Posteingang
|
||||
sender mail de Absender
|
||||
sent mail de Gesendet
|
||||
sent folder mail de Ordner für gesendete Nachrichten
|
||||
@ -698,8 +701,8 @@ yes, offer copy option mail de Ja, mit Kopieroption
|
||||
yes, only trigger connection reset mail de Ja, aber führe nur das zurücksetzen der Verbindung aus
|
||||
yes, show all debug information available for the user mail de Ja, zeige alle dem Benutzer zugänglichen Informationen an.
|
||||
yes, show basic info only mail de Ja, nur Basis Informationen anzeigen
|
||||
you can select what info to be displayed on email tag mail de Sie können auswählen, welche Informationen auf dem E-Mail-Tag angezeigt werden sollen
|
||||
you can either choose to save as infolog or tracker, not both. mail de Sie können eine E-Mail entweder als InfoLog-, ODER als Ticket-Eintrag speichern, nicht beides gleichzeitig.
|
||||
you can select what info to be displayed on email tag mail de Sie können auswählen, welche Informationen auf dem E-Mail-Tag angezeigt werden sollen
|
||||
you can use $$start$$ for the above start date and $$end$$ for the end date. mail de Sie können $$start$$ für das obige Start- und $$end$$ für das Enddatum verwenden.
|
||||
you may add this certificate into your contact, if you trust this signature. mail de Sie können dieses Zertifikat in Ihren Kontakt speichern, wenn Sie dieser Signatur trauen.
|
||||
you need to enter your s/mime passphrase to send this message. mail de Sie müssen Ihr S/MIME-Passwort eingeben um diese Nachricht zu senden.
|
||||
|
@ -416,6 +416,7 @@ only name mail en only name
|
||||
only needed for some servers, that do not return all folders on root level queries to retrieve all folders for that level mail en only needed for some servers, that do not return all folders on root level queries to retrieve all folders for that level
|
||||
only one window mail en only one window
|
||||
only send message, do not copy a version of the message to the configured sent folder mail en only send message, do not copy a version of the message to the configured sent folder
|
||||
only store message in inbox, do not send vacation notice mail en Only store message in INBOX, do NOT send vacation notice
|
||||
open in html mode mail en Open in HTML mode
|
||||
open in text mode mail en Open in Text mode
|
||||
open with collabora office mail en Open with Collabora Office
|
||||
@ -548,6 +549,8 @@ send a reject message: mail en Send a reject message:
|
||||
send files as mail en Send files as
|
||||
send message and move to send folder (if configured) mail en send message and move to send folder (if configured)
|
||||
send message pgp encrypted: requires keys from all recipients! mail en Send message PGP encrypted: requires keys from all recipients!
|
||||
send only a vacation notice, do not store message in inbox mail en Send only a vacation notice, do NOT store message in INBOX
|
||||
send vacation notice and store message in inbox mail en Send vacation notice and store message in INBOX
|
||||
sender mail en sender
|
||||
sent mail en Sent
|
||||
sent folder mail en sent folder
|
||||
@ -698,8 +701,8 @@ yes, offer copy option mail en yes, offer copy option
|
||||
yes, only trigger connection reset mail en yes, only trigger connection reset
|
||||
yes, show all debug information available for the user mail en yes, show all debug information available for the user
|
||||
yes, show basic info only mail en yes, show basic info only
|
||||
you can select what info to be displayed on email tag mail en You can select what info to be displayed on email tag
|
||||
you can either choose to save as infolog or tracker, not both. mail en You can either choose to save as infolog OR tracker, not both.
|
||||
you can select what info to be displayed on email tag mail en You can select what info to be displayed on email tag
|
||||
you can use $$start$$ for the above start date and $$end$$ for the end date. mail en You can use $$start$$ for the above start date and $$end$$ for the end date.
|
||||
you may add this certificate into your contact, if you trust this signature. mail en You may add this certificate into your contact, if you trust this signature.
|
||||
you need to enter your s/mime passphrase to send this message. mail en You need to enter your S/MIME passphrase to send this message.
|
||||
|
@ -31,7 +31,7 @@ class ApiHandler extends Api\CalDAV\Handler
|
||||
/**
|
||||
* Options for json_encode of responses
|
||||
*/
|
||||
const JSON_RESPONSE_OPTIONS = JSON_PRETTY_PRINT|JSON_UNESCAPED_UNICODE|JSON_UNESCAPED_SLASHES;
|
||||
const JSON_RESPONSE_OPTIONS = JSON_PRETTY_PRINT|JSON_UNESCAPED_UNICODE|JSON_UNESCAPED_SLASHES|JSON_THROW_ON_ERROR;
|
||||
|
||||
/**
|
||||
* Handle post request for mail (send or compose mail and upload attachments)
|
||||
@ -60,6 +60,10 @@ class ApiHandler extends Api\CalDAV\Handler
|
||||
{
|
||||
return self::storeAttachment($path, $options['stream'] ?? $options['content']);
|
||||
}
|
||||
elseif (preg_match('#^/mail(/(\d+))?/vacation/?$#', $path, $matches))
|
||||
{
|
||||
return self::updateVacation($user, $options['content'], $matches[2]);
|
||||
}
|
||||
elseif (preg_match('#^/mail(/(\d+))?(/compose)?#', $path, $matches))
|
||||
{
|
||||
$ident_id = $matches[2] ?? self::defaultIdentity($user);
|
||||
@ -132,22 +136,70 @@ class ApiHandler extends Api\CalDAV\Handler
|
||||
throw new \Exception('Not Found', 404);
|
||||
}
|
||||
catch (\Throwable $e) {
|
||||
_egw_log_exception($e);
|
||||
header('Content-Type: application/json');
|
||||
echo json_encode([
|
||||
'error' => $code = $e->getCode() ?: 500,
|
||||
'message' => $e->getMessage(),
|
||||
]+(empty($GLOBALS['egw_info']['server']['exception_show_trace']) ? [] : [
|
||||
'trace' => array_map(static function($trace)
|
||||
{
|
||||
$trace['file'] = str_replace(EGW_SERVER_ROOT.'/', '', $trace['file']);
|
||||
return $trace;
|
||||
}, $e->getTrace())
|
||||
]), self::JSON_RESPONSE_OPTIONS);
|
||||
return (400 <= $code && $code < 600 ? $code : 500).' '.$e->getMessage();
|
||||
return self::handleException($e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update vacation message/handling with JSON data given in $content
|
||||
*
|
||||
* @param int $user
|
||||
* @param array $content
|
||||
* @param int|null $identity
|
||||
* @return bool
|
||||
* @throws Api\Exception\AssertionFailed
|
||||
* @throws Api\Exception\NotFound
|
||||
*/
|
||||
protected static function updateVacation(int $user, string $content, int $identity=null)
|
||||
{
|
||||
$account = self::getMailAccount($user, $identity);
|
||||
$vacation = $account->imapServer()->getVacationUser($user);
|
||||
if (!($update = json_decode($content, true, 3, JSON_THROW_ON_ERROR)))
|
||||
{
|
||||
return throw new \Exeception('Invalid request: no content', 400);
|
||||
}
|
||||
// Sieve class stores them as timestamps
|
||||
foreach(['start', 'end'] as $name)
|
||||
{
|
||||
if (isset($update[$name]))
|
||||
{
|
||||
$vacation[$name.'_date'] = (new Api\DateTime($update[$name]))->format('ts');
|
||||
if (empty($update['status'])) $update['status'] = 'by_date';
|
||||
}
|
||||
elseif (array_key_exists($name, $update))
|
||||
{
|
||||
$vacation[$name.'_date'] = null;
|
||||
if (empty($update['status'])) $update['status'] = 'off';
|
||||
}
|
||||
unset($update[$name]);
|
||||
}
|
||||
// Sieve class stores them as comma-separated string
|
||||
if (array_key_exists('forwards', $update))
|
||||
{
|
||||
$vacation['forwards'] = implode(',', $update['forwards'] ?? []);
|
||||
unset($update['forwards']);
|
||||
}
|
||||
static $modi = ['notice+store', 'notice', 'store'];
|
||||
if (isset($update['modus']) && !in_array($update['modus'], $modi))
|
||||
{
|
||||
throw new \Exception("Invalid value '$update[modus]' for attribute modus, allowed values are: '".implode("', '", $modi)."'", 400);
|
||||
}
|
||||
if (($invalid=array_diff(array_keys($update), ['start','end','status','modus','text','addresses','forwards','days'])))
|
||||
{
|
||||
throw new \Exception("Invalid attribute: ".implode(', ', $invalid), 400);
|
||||
}
|
||||
$vacation_rule = null;
|
||||
$sieve = new Api\Mail\Sieve($account->imapServer());
|
||||
$sieve->setVacation(array_merge($vacation, $update), null, $vacation_rule, true);
|
||||
echo json_encode([
|
||||
'status' => 200,
|
||||
'message' => 'Vacation handling updated',
|
||||
'vacation_rule' => $vacation_rule,
|
||||
'vacation' => self::returnVacation($account->imapServer()->getVacationUser($user)),
|
||||
], self::JSON_RESPONSE_OPTIONS);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Store uploaded attachment and return token
|
||||
*
|
||||
@ -324,13 +376,93 @@ class ApiHandler extends Api\CalDAV\Handler
|
||||
*/
|
||||
function get(&$options,$id,$user=null)
|
||||
{
|
||||
$path = rtrim($options['path'], '/');
|
||||
if (empty($user))
|
||||
{
|
||||
$user = $GLOBALS['egw_info']['user']['account_id'];
|
||||
}
|
||||
else
|
||||
{
|
||||
$prefix = '/'.Api\Accounts::id2name($user);
|
||||
if (str_starts_with($path, $prefix)) $path = substr($path, strlen($prefix));
|
||||
}
|
||||
header('Content-Type: application/json');
|
||||
echo json_encode($all=iterator_to_array(Api\Mail\Account::identities([], true, 'name',
|
||||
$user ?: $GLOBALS['egw_info']['user']['account_id'])), JSON_PRETTY_PRINT|JSON_UNESCAPED_SLASHES|JSON_UNESCAPED_UNICODE);
|
||||
return true;
|
||||
try
|
||||
{
|
||||
switch ($path)
|
||||
{
|
||||
case '/mail':
|
||||
echo json_encode(iterator_to_array(Api\Mail\Account::identities([], true, 'name', $user)),
|
||||
self::JSON_RESPONSE_OPTIONS);
|
||||
return true;
|
||||
|
||||
case preg_match('#^/mail(/(\d+))?/vacation$#', $path, $matches) === 1:
|
||||
$account = self::getMailAccount($user, $matches[2] ?? null);
|
||||
echo json_encode(self::returnVacation($account->imapServer()->getVacationUser($user)), self::JSON_RESPONSE_OPTIONS);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
catch (\Throwable $e) {
|
||||
return self::handleException($e);
|
||||
}
|
||||
return '501 Not Implemented';
|
||||
}
|
||||
|
||||
protected static function returnVacation(array $vacation)
|
||||
{
|
||||
return array_filter([
|
||||
'status' => $vacation['status'],
|
||||
'start' => isset($vacation['start_date']) ? Api\DateTime::to($vacation['start_date'], 'Y-m-d') : null,
|
||||
'end' => $vacation['end_date'] ? Api\DateTime::to($vacation['end_date'], 'Y-m-d') : null,
|
||||
'text' => $vacation['text'],
|
||||
'modus' => $vacation['modus'] ?? "notice+store",
|
||||
'days' => (int)($vacation['days'] ?? 0),
|
||||
'addresses' => $vacation['addresses'] ?? null,
|
||||
'forwards' => empty($vacation['forwards']) ? [] : preg_split('/, ?/', $vacation['forwards']),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get mail account specified by identity or users default one
|
||||
*
|
||||
* @param int $user
|
||||
* @param int|null $ident_id
|
||||
* @return Api\Mail\Account
|
||||
* @throws Api\Exception\NotFound
|
||||
*/
|
||||
protected static function getMailAccount(int $user, int $ident_id=null) : Api\Mail\Account
|
||||
{
|
||||
if (empty($ident_id))
|
||||
{
|
||||
return Api\Mail\Account::get_default();
|
||||
}
|
||||
$identity = Api\Mail\Account::read_identity($ident_id, false, $user);
|
||||
return Api\Mail\Account::read($identity['acc_id']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle exception by returning an appropriate HTTP status and JSON content with an error message
|
||||
*
|
||||
* @param \Throwable $e
|
||||
* @return string
|
||||
*/
|
||||
protected function handleException(\Throwable $e) : string
|
||||
{
|
||||
_egw_log_exception($e);
|
||||
header('Content-Type: application/json');
|
||||
echo json_encode([
|
||||
'error' => $code = $e->getCode() ?: 500,
|
||||
'message' => $e->getMessage(),
|
||||
]+(empty($GLOBALS['egw_info']['server']['exception_show_trace']) ? [] : [
|
||||
'trace' => array_map(static function($trace)
|
||||
{
|
||||
$trace['file'] = str_replace(EGW_SERVER_ROOT.'/', '', $trace['file']);
|
||||
return $trace;
|
||||
}, $e->getTrace())
|
||||
]), self::JSON_RESPONSE_OPTIONS);
|
||||
return (400 <= $code && $code < 600 ? $code : 500).' '.$e->getMessage();
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle get request for an applications entry
|
||||
*
|
||||
|
@ -34,16 +34,24 @@
|
||||
<et2-select-email id="forwards" allowFreeEntries="true" width="100%" multiple="true" searchUrl="EGroupware\Api\Etemplate\Widget\Taglist::ajax_email" placeholder="do not forward"></et2-select-email>
|
||||
</row>
|
||||
<row>
|
||||
<et2-description value="Resend after how many days?"></et2-description>
|
||||
<et2-number id="days" min="1" max="31" precision="0"></et2-number>
|
||||
<et2-description value="Vacation notice"></et2-description>
|
||||
<et2-select id="modus">
|
||||
<option value="notice+store">Send vacation notice and store message in INBOX</option>
|
||||
<option value="notice">Send only a vacation notice, do NOT store message in INBOX</option>
|
||||
<option value="store">Only store message in INBOX, do NOT send vacation notice</option>
|
||||
</et2-select>
|
||||
</row>
|
||||
<row>
|
||||
<row valign="top">
|
||||
<et2-description value="With message:"></et2-description>
|
||||
<et2-vbox span="all">
|
||||
<et2-textarea id="text" rows="10" class="et2_required" required="1"></et2-textarea>
|
||||
<et2-description id="by_date_label" value="You can use $$start$$ for the above start date and $$end$$ for the end date."></et2-description>
|
||||
</et2-vbox>
|
||||
</row>
|
||||
<row>
|
||||
<et2-description value="Resend after how many days?"></et2-description>
|
||||
<et2-number id="days" min="1" max="31" precision="0"></et2-number>
|
||||
</row>
|
||||
<row>
|
||||
<et2-description value="Set it as default:" disabled="@is_not_admin_user"></et2-description>
|
||||
<et2-checkbox id="set_as_default"></et2-checkbox>
|
||||
|
Loading…
Reference in New Issue
Block a user