--- /dev/null
+<?php
+/*
+ * Bacula(R) - The Network Backup Solution
+ * Baculum - Bacula web interface
+ *
+ * Copyright (C) 2013-2022 Kern Sibbald
+ *
+ * The main author of Baculum is Marcin Haba.
+ * The original author of Bacula is Kern Sibbald, with contributions
+ * from many others, a complete list can be found in the file AUTHORS.
+ *
+ * You may use this file and others of this release according to the
+ * license defined in the LICENSE file, which includes the Affero General
+ * Public License, v3.0 ("AGPLv3") and some additional permissions and
+ * terms pursuant to its AGPLv3 Section 7.
+ *
+ * This notice must be preserved when any source code is
+ * conveyed and/or propagated.
+ *
+ * Bacula(R) is a registered trademark of Kern Sibbald.
+ */
+
+namespace Baculum\API\Modules;
+
+/**
+ * Get console output for JSON type commands (like .jlist).
+ *
+ * @author Marcin Haba <marcin.haba@bacula.pl>
+ * @category API
+ * @package Baculum API
+ */
+abstract class ConsoleOutputJSONPage extends ConsoleOutputPage {
+
+ /**
+ * Parse '.jlist' type command output.
+ *
+ * @param array $output dot query command output
+ * @return object parsed output or empty object if there occurs a problem with parsing output
+ */
+ protected function parseOutput(array $output) {
+ $out = new \StdClass;
+ for ($i = 0; $i < count($output); $i++) {
+ if (preg_match('/^[{\[]/', $output[$i]) === 1) {
+ $out = json_decode($output[$i]);
+ break;
+ }
+ }
+ return $out;
+ }
+}
+?>
--- /dev/null
+<?php
+/*
+ * Bacula(R) - The Network Backup Solution
+ * Baculum - Bacula web interface
+ *
+ * Copyright (C) 2013-2022 Kern Sibbald
+ *
+ * The main author of Baculum is Marcin Haba.
+ * The original author of Bacula is Kern Sibbald, with contributions
+ * from many others, a complete list can be found in the file AUTHORS.
+ *
+ * You may use this file and others of this release according to the
+ * license defined in the LICENSE file, which includes the Affero General
+ * Public License, v3.0 ("AGPLv3") and some additional permissions and
+ * terms pursuant to its AGPLv3 Section 7.
+ *
+ * This notice must be preserved when any source code is
+ * conveyed and/or propagated.
+ *
+ * Bacula(R) is a registered trademark of Kern Sibbald.
+ */
+
+use Baculum\API\Modules\ConsoleOutputJSONPage;
+use Baculum\Common\Modules\Logging;
+use Baculum\Common\Modules\Errors\{ClientError,PluginError,PluginM365Error};
+
+/**
+ * List emails backed up using Microsoft 365 plugin.
+ *
+ * @author Marcin Haba <marcin.haba@bacula.pl>
+ * @category API
+ * @package Baculum API
+ */
+class PluginM365EmailList extends ConsoleOutputJSONPage {
+
+ public function get() {
+ $misc = $this->getModule('misc');
+ $client = null;
+ $clientid = $this->Request->contains('id') ? (int)$this->Request['id'] : 0;
+ $result = $this->getModule('bconsole')->bconsoleCommand(
+ $this->director,
+ ['.client'],
+ null,
+ true
+ );
+ if ($result->exitcode === 0) {
+ $client_val = $this->getModule('client')->getClientById($clientid);
+ if (is_object($client_val) && in_array($client_val->name, $result->output)) {
+ $client = $client_val->name;
+ } else {
+ $this->output = ClientError::MSG_ERROR_CLIENT_DOES_NOT_EXISTS;
+ $this->error = ClientError::ERROR_CLIENT_DOES_NOT_EXISTS;
+ return;
+ }
+ } else {
+ $this->output = PluginError::MSG_ERROR_WRONG_EXITCODE;
+ $this->error = PluginError::ERROR_WRONG_EXITCODE;
+ return;
+ }
+
+ $tenantid = $this->Request->contains('tenantid') ? $this->Request['tenantid'] : null;
+ $fd_plugin_cfg = $this->getModule('fd_plugin_cfg')->getConfig('m365', $client, $tenantid);
+ if (!empty($tenantid) && (!$misc->isValidUUID($tenantid) || count($fd_plugin_cfg) == 0)) {
+ $this->output = PluginM365Error::MSG_ERROR_TENANT_DOES_NOT_EXISTS;
+ $this->error = PluginM365Error::ERROR_TENANT_DOES_NOT_EXISTS;
+ return;
+ }
+ $tenant = $fd_plugin_cfg['tenant_name'];
+
+ $params = [
+ 'client' => $client,
+ 'tenant' => $tenant
+ ];
+ if ($this->Request->contains('mailbox') && $misc->isValidEmail($this->Request['mailbox'])) {
+ $params['mailbox'] = $this->Request['mailbox'];
+ }
+ if ($this->Request->contains('mailbox_pattern') && $misc->isValidEmail($this->Request['mailbox_pattern'])) {
+ $params['mailbox_pattern'] = $this->Request['mailbox_pattern'];
+ }
+ if ($this->Request->contains('limit') && $misc->isValidInteger($this->Request['limit'])) {
+ $params['limit'] = (int)$this->Request['limit'];
+ }
+ if ($this->Request->contains('mintime') && $misc->isValidBDate($this->Request['mintime'])) {
+ $params['mintime'] = $this->Request['mintime'];
+ }
+ if ($this->Request->contains('maxtime') && $misc->isValidBDate($this->Request['maxtime'])) {
+ $params['maxtime'] = $this->Request['maxtime'];
+ }
+ if ($this->Request->contains('folder') && $misc->isValidFilename($this->Request['folder'])) {
+ $params['folder'] = $this->Request['folder'];
+ }
+ if ($this->Request->contains('tags') && $misc->isValidName($this->Request['tags'])) {
+ $params['tags'] = $this->Request['tags'];
+ }
+ if ($this->Request->contains('from') && $misc->isValidEmail($this->Request['from'])) {
+ $params['from'] = $this->Request['from'];
+ }
+ if ($this->Request->contains('to') && $misc->isValidEmail($this->Request['to'])) {
+ $params['to'] = $this->Request['to'];
+ }
+ if ($this->Request->contains('cc') && $misc->isValidEmail($this->Request['cc'])) {
+ $params['cc'] = $this->Request['cc'];
+ }
+ if ($this->Request->contains('minsize') && $misc->isValidInteger($this->Request['minsize'])) {
+ $params['minsize'] = $this->Request['minsize'];
+ }
+ if ($this->Request->contains('maxsize') && $misc->isValidInteger($this->Request['maxsize'])) {
+ $params['maxsize'] = $this->Request['maxsize'];
+ }
+ if ($this->Request->contains('conversationid') && $misc->isValidNameExt($this->Request['conversationid'])) {
+ $params['conversationid'] = $this->Request['conversationid'];
+ }
+ $out = $this->getJSONOutput($params);
+
+ $output = [];
+ $error = PluginM365Error::ERROR_NO_ERRORS;
+ if ($out->exitcode === 0) {
+ $output = $out->output;
+ } else {
+ $error = PluginM365Error::ERROR_WRONG_EXITCODE;
+ $output = PluginM365Error::MSG_ERROR_WRONG_EXITCODE . implode(PHP_EOL, $out->output);
+ }
+ $this->output = $output;
+ $this->error = $error;
+ }
+
+ /**
+ * Get M365 email list in JSON string format.
+ *
+ * @param array $params command parameters
+ * @return StdClass object with output and exitcode
+ */
+ protected function getRawOutput($params = []) {
+ $cmd = [
+ '.jlist',
+ 'metadata',
+ 'type="email"',
+ 'tenant="' . $params['tenant'] . '"'
+ ];
+
+ if (key_exists('mailbox', $params)) {
+ $cmd[] ='owner="' . $params['mailbox'] . '"';
+ }
+ if (key_exists('mailbox_pattern', $params)) {
+ $cmd[] ='owner="' . $params['mailbox_pattern'] . '%"';
+ }
+ if (key_exists('limit', $params)) {
+ $cmd[] ='limit="' . $params['limit'] . '"';
+ }
+ if (key_exists('mintime', $params)) {
+ $cmd[] ='mintime="' . $params['mintime'] . ' 0:00:00"';
+ }
+ if (key_exists('maxtime', $params)) {
+ $cmd[] ='maxtime="' . $params['maxtime'] . ' 23:59:59"';
+ }
+ if (key_exists('folder', $params)) {
+ $cmd[] ='foldername="' . $params['folder'] . '"';
+ }
+ if (key_exists('tags', $params)) {
+ $cmd[] ='tags="' . $params['tags'] . '"';
+ }
+ if (key_exists('from', $params)) {
+ $cmd[] ='from="' . $params['from'] . '"';
+ }
+ if (key_exists('to', $params)) {
+ $cmd[] ='to="' . $params['to'] . '"';
+ }
+ if (key_exists('cc', $params)) {
+ $cmd[] ='cc="' . $params['cc'] . '"';
+ }
+ if (key_exists('minsize', $params)) {
+ $cmd[] ='minsize="' . $params['minsize'] . '"';
+ }
+ if (key_exists('maxsize', $params)) {
+ $cmd[] ='maxsize="' . $params['maxsize'] . '"';
+ }
+ if (key_exists('conversationid', $params)) {
+ $cmd[] ='conversationid="' . $params['conversationid'] . '"';
+ }
+ $ret = $this->getModule('bconsole')->bconsoleCommand(
+ $this->director,
+ $cmd
+ );
+
+ if ($ret->exitcode !== 0) {
+ $this->getModule('logging')->log(
+ Logging::CATEGORY_EXECUTE,
+ 'Wrong output from m365 RAW email list: ' . implode(PHP_EOL, $ret->output)
+ );
+ }
+ return $ret;
+ }
+
+ /**
+ * Get M365 email list in validated and formatted JSON format.
+ *
+ * @param array $params command parameters
+ * @return StdClass object with output and exitcode
+ */
+ protected function getJSONOutput($params = []) {
+ $ret = $this->getRawOutput($params);
+ if ($ret->exitcode === 0) {
+ $ret->output = $this->parseOutput($ret->output);
+ if ($ret->output->error === 0) {
+ $ret->output = $ret->output->data;
+ } else {
+ $ret->output = $ret->output->errmsg;
+ }
+ }
+ return $ret;
+ }
+}
},
"Event": {
"$ref": "#/definitions/Event"
+ },
+ "PluginM365Emails": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/PluginM365Email"
+ }
+ },
+ "PluginM365Email": {
+ "$ref": "#/definitions/PluginM365Email"
}
},
"parameters": {
},
"TenantId": {
"name": "tenantid",
- "in": "query",
+ "in": "path",
"description": "Tenant identifier",
- "required": false,
+ "required": true,
"schema": {
"type": "string"
}
"$ref": "#/components/parameters/ClientId"
},
{
- "$ref": "#/components/parameters/TenantId"
+ "name": "tenantid",
+ "in": "path",
+ "description": "Tenant identifier",
+ "required": false,
+ "schema": {
+ "type": "string"
+ }
},
{
"$ref": "#/components/parameters/Output"
}
]
}
+ },
+ "/api/v2/plugins/m365/{clientid}/{tenantid}/emails": {
+ "get": {
+ "tags": ["plugins"],
+ "summary": "Microsoft 365 plugin email list",
+ "description": "Get Microsoft 365 email list.",
+ "responses": {
+ "200": {
+ "description": "List of Microsoft 365 emails",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "properties": {
+ "output": {
+ "$ref": "#/components/schemas/PluginM365Emails"
+ },
+ "error": {
+ "type": "integer",
+ "description": "Error code",
+ "enum": [0, 1, 4, 5, 6, 7, 11, 1000]
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "parameters": [
+ {
+ "$ref": "#/components/parameters/ClientId"
+ },
+ {
+ "$ref": "#/components/parameters/TenantId"
+ },
+ {
+ "$ref": "#/components/parameters/Limit"
+ },
+ {
+ "name": "mailbox",
+ "in": "query",
+ "required": false,
+ "description": "Mailbox address",
+ "schema": {
+ "type": "string"
+ }
+ },
+ {
+ "name": "mailbox_pattern",
+ "in": "query",
+ "required": false,
+ "description": "Mailbox pattern address (it can be partial email address)",
+ "schema": {
+ "type": "string"
+ }
+ },
+ {
+ "name": "mintime",
+ "in": "query",
+ "required": false,
+ "description": "Date start (YYYY-MM-DD)",
+ "schema": {
+ "type": "string"
+ }
+ },
+ {
+ "name": "maxtime",
+ "in": "query",
+ "required": false,
+ "description": "Date end (YYYY-MM-DD)",
+ "schema": {
+ "type": "string"
+ }
+ },
+ {
+ "name": "folder",
+ "in": "query",
+ "required": false,
+ "description": "Email folder name",
+ "schema": {
+ "type": "string"
+ }
+ },
+ {
+ "name": "tags",
+ "in": "query",
+ "required": false,
+ "description": "Email tags",
+ "schema": {
+ "type": "string"
+ }
+ },
+ {
+ "name": "from",
+ "in": "query",
+ "required": false,
+ "description": "Email sender (from)",
+ "schema": {
+ "type": "string"
+ }
+ },
+ {
+ "name": "to",
+ "in": "query",
+ "required": false,
+ "description": "Email recipient (to)",
+ "schema": {
+ "type": "string"
+ }
+ },
+ {
+ "name": "cc",
+ "in": "query",
+ "required": false,
+ "description": "Email copy address (cc)",
+ "schema": {
+ "type": "string"
+ }
+ },
+ {
+ "name": "minsize",
+ "in": "query",
+ "required": false,
+ "description": "Email minimum size in bytes",
+ "schema": {
+ "type": "integer"
+ }
+ },
+ {
+ "name": "maxsize",
+ "in": "query",
+ "required": false,
+ "description": "Email maximum size in bytes",
+ "schema": {
+ "type": "integer"
+ }
+ },
+ {
+ "name": "conversationid",
+ "in": "query",
+ "required": false,
+ "description": "Email conversation identifier",
+ "schema": {
+ "type": "string"
+ }
+ }
+ ]
+ }
}
},
"definitions": {
"type": "string"
}
}
+ },
+ "PluginM365Email": {
+ "type": "object",
+ "properties": {
+ "jobid": {
+ "description": "Job identifier",
+ "type": "integer"
+ },
+ "fileindex": {
+ "description": "File index",
+ "type": "integer"
+ },
+ "emailtenant": {
+ "description": "Tenant name",
+ "type": "string"
+ },
+ "emailowner": {
+ "description": "Email owner",
+ "type": "string"
+ },
+ "emailbodypreview": {
+ "description": "Email body preview",
+ "type": "string"
+ },
+ "emailcc": {
+ "description": "Email copy address (cc)",
+ "type": "string"
+ },
+ "emailconversationid": {
+ "description": "Email conversation identifier",
+ "type": "string"
+ },
+ "emailfoldername": {
+ "description": "Email folder name",
+ "type": "string"
+ },
+ "emailfrom": {
+ "description": "Email sender (from)",
+ "type": "string"
+ },
+ "emailid": {
+ "description": "Email identifier",
+ "type": "string"
+ },
+ "emailimportance": {
+ "description": "Email importance",
+ "type": "string"
+ },
+ "emailinternetmessageid": {
+ "description": "Email Internet message identifier",
+ "type": "string"
+ },
+ "emailisread": {
+ "description": "Email is read flag",
+ "type": "integer"
+ },
+ "emailisdraft": {
+ "description": "Email is draft flag",
+ "type": "integer"
+ },
+ "emailtime": {
+ "description": "Email time (YYYY-MM-DD HH:II:SS)",
+ "type": "string"
+ },
+ "emailsubject": {
+ "description": "Email subject",
+ "type": "string"
+ },
+ "emailtags": {
+ "description": "Email tags",
+ "type": "string"
+ },
+ "emailto": {
+ "description": "Email recipient (to)",
+ "type": "string"
+ },
+ "emailsize": {
+ "description": "Email size in bytes",
+ "type": "string"
+ },
+ "emailhasattachment": {
+ "description": "Email attachment flag",
+ "type": "integer"
+ },
+ "plugin": {
+ "description": "Plugin name",
+ "type": "string"
+ }
+ }
}
}
}