<?php

/**
 * OpenKM, Open Knowledge Management System S.L.  (http://www.openkm.com)
 * Copyright (c) 2006-2018
 *
 * No bytes were intentionally harmed during the development of this application.
 *
 * This program is commercial software; you can use it under the terms of the
 * EULA - OpenKM SDK End User License Agreement as published by OpenKM Knowledge Management System S.L.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * EULA - OpenKM SDK End User License Agreement for more details:
 * http://docs.openkm.com/kcenter/view/licenses/eula-openkm-sdk-end-user-license-agreement.html
 */

namespace openkm\impl;

use openkm\bean\Document;
use openkm\bean\Mail;
use openkm\definition\BaseMail;
use openkm\util\UriHelper;
use Httpful\Request;
use Httpful\Mime;
use openkm\util\Status;
use openkm\util\TypeException;
use openkm\exception\UnsupportMimeTypeException;
use openkm\exception\FileSizeExceededException;
use openkm\exception\VirusDetectedException;
use openkm\exception\AccessDeniedException;
use openkm\exception\PathNotFoundException;
use openkm\exception\RepositoryException;
use openkm\exception\DatabaseException;
use Httpful\Exception\ConnectionErrorException;
use openkm\exception\UnknowException;
use openkm\exception\ItemExistsException;
use openkm\exception\ExtensionException;
use openkm\exception\AutomationException;
use openkm\exception\LockException;
use openkm\exception\UserQuotaExceededException;
use openkm\exception\IOException;
use openkm\exception\MessagingException;

/**
 * MailImpl
 *
 * @author sochoa
 */
class MailImpl extends ClientImpl implements BaseMail {

    /**
     * Create a new mail
     * 
     * @param Mail $mail
     * @return Mail Return as a result an object Mail.
     * @throws ConnectionErrorException
     * @throws AccessDeniedException
     * @throws RepositoryException
     * @throws PathNotFoundException
     * @throws ItemExistsException
     * @throws DatabaseException
     * @throws AutomationExcekction
     * @throws VirusDetectedException
     * @throws UserQuotaExceededException
     * @throws UnknowException
     */
    public function createMail(Mail $mail) {
        try {
            $uri = UriHelper::getUri($this->host, UriHelper::MAIL_CREATE);
            $client = Request::post($uri);
            $mailXML = new \SimpleXMLElement('<mail></mail>');
            $mailXML->addChild('author', $mail->getAuthor());
            $mailXML->addChild('created', $mail->getCreated());
            $mailXML->addChild('nodeClass', $mail->getNodeClass());
            $mailXML->addChild('path', $mail->getPath());
            $mailXML->addChild('permissions', $mail->getPermissions());
            if ($mail->isSubscribed() == 1) {
                $mailXML->addChild('subscribed', 'true');
            } else {
                $mailXML->addChild('subscribed', 'false');
            }
            $mailXML->addChild('uuid', $mail->getUuid());
            //mail
            $mailXML->addChild('title', $mail->getTitle());
            $mailXML->addChild('from', $mail->getFrom());
            $mailXML->addChild('sentDate', $mail->getSentDate());
            $mailXML->addChild('receivedDate', $mail->getReceivedDate());
            $mailXML->addChild('subject', $mail->getSubject());
            $mailXML->addChild('content', $mail->getContent());
            $mailXML->addChild('mimeType', $mail->getMimeType());
            $mailXML->addChild('headers', $mail->getHeaders());
            $mailXML->addChild('raw', $mail->getRaw());
            $mailXML->addChild('origin', $mail->getOrigin());
            $mailXML->addChild('size', $mail->getSize());
            if ($mail->istHasAttachments() == 1) {
                $mailXML->addChild('hasAttachments', 'true');
            } else {
                $mailXML->addChild('hasAttachments', 'false');
            }
            foreach ($mail->getReply() as $reply) {
                $mailXML->addChild('reply', $reply);
            }
            foreach ($mail->getTo() as $to) {
                $mailXML->addChild('to', $to);
            }
            foreach ($mail->getCc() as $cc) {
                $mailXML->addChild('cc', $cc);
            }
            foreach ($mail->getBcc() as $bcc) {
                $mailXML->addChild('bcc', $bcc);
            }
            foreach ($mail->getCategories() as $category) {
                $categoryXML = $mailXML->addChild('categories');
                $categoryXML->addChild('author', $category->getAuthor());
                $categoryXML->addChild('created', $category->getCreated());
                $categoryXML->addChild('nodeClass', $category->getNodeClass());
                $categoryXML->addChild('path', $category->getPath());
                $categoryXML->addChild('permissions', $category->getPermissions());
                $categoryXML->addChild('subscribed', $category->isSubscribed());
                $categoryXML->addChild('uuid', $category->getUuid());
                $categoryXML->addChild('hasChildren', $category->isHasChildren());
                $categoryXML->addChild('style', $category->getStyle());
            }
            foreach ($mail->getKeywords() as $keyword) {
                $mailXML->addChild('keywords', $keyword);
            }

            foreach ($mail->getNotes() as $note) {
                $noteXML = $mailXML->addChild('notes');
                $noteXML->addChild('author', $note->getAuthor());
                $noteXML->addChild('date', $note->getDate());
                $noteXML->addChild('path', $note->getPath());
                $noteXML->addChild('text', $note->getText());
            }
            $client->body($mailXML->asXML());
            $response = $this->getClient($client);
            if ($response->code == Status::OK) {
                return $this->phpMail($response->body);
            } else {
                if ($response->code == Status::UNAUTHORIZED) {
                    throw new AccessDeniedException($response->body, $response->code);
                } else if ($response->code == Status::INTERNAL_SERVER_ERROR) {
                    $position = strpos($response->body, ':');
                    if ($position) {
                        $error = substr($response->body, 0, $position);
                        $msg = substr($response->body, $position + 1, strlen($response->body));
                        if ($error == TypeException::REPOSITORY_EXCEPTION) {
                            throw new RepositoryException($error . ': ' . $msg);
                        } else if ($error == TypeException::PATH_NOT_FOUND_EXCEPTION) {
                            throw new PathNotFoundException($error . ': ' . $msg);
                        } else if ($error == TypeException::ITEM_EXISTS_EXCEPTION) {
                            throw new ItemExistsException($error . ': ' . $msg);
                        } else if ($error == TypeException::DATABASE_EXCEPTION) {
                            throw new DatabaseException($error . ': ' . $msg);
                        } else if ($error == TypeException::AUTOMATION_EXCEPTION) {
                            throw new AutomationException($error . ': ' . $msg);
                        } else if ($error == TypeException::VIRUS_DETECTED_EXCEPTION) {
                            throw new VirusDetectedException($error . ': ' . $msg);
                        } else if ($error == TypeException::USER_QUOTA_EXCEEDED_EXCEPTION) {
                            throw new UserQuotaExceededException($error . ': ' . $msg);
                        } else {
                            throw new UnknowException($error . ': ' . $msg);
                        }
                    } else {
                        throw new UnknowException("HTTP error code " . $response->code . ": " . $response->body);
                    }
                } else {
                    throw new UnknowException("HTTP error code " . $response->code . ": " . $response->body);
                }
            }
        } catch (ConnectionErrorException $cee) {
            throw new ConnectionErrorException('ConnectionErrorException: ' . $cee->getMessage());
        }
    }

    /**
     * Get Mail Properties
     * 
     * @param string $mailId The uuid or path of the Mail
     * @return Mail Return the mail properties.
     * @throws ConnectionErrorException
     * @throws AccessDeniedException
     * @throws RepositoryException
     * @throws PathNotFoundException
     * @throws DatabaseException
     * @throws UnknowException
     */
    public function getMailProperties($mailId) {
        try {
            $uri = UriHelper::getUri($this->host, UriHelper::MAIL_GET_PROPERTIES);
            $uri .= '?mailId=' . urlencode($mailId);
            $client = Request::get($uri);
            $response = $this->getClient($client);
            if ($response->code == Status::OK) {
                return $this->phpMail($response->body);
            } else {
                if ($response->code == Status::UNAUTHORIZED) {
                    throw new AccessDeniedException($response->body, $response->code);
                } else if ($response->code == Status::INTERNAL_SERVER_ERROR) {
                    $position = strpos($response->body, ':');
                    if ($position) {
                        $error = substr($response->body, 0, $position);
                        $msg = substr($response->body, $position + 1, strlen($response->body));
                        if ($error == TypeException::REPOSITORY_EXCEPTION) {
                            throw new RepositoryException($error . ': ' . $msg);
                        } else if ($error == TypeException::PATH_NOT_FOUND_EXCEPTION) {
                            throw new PathNotFoundException($error . ': ' . $msg);
                        } else if ($error == TypeException::DATABASE_EXCEPTION) {
                            throw new DatabaseException($error . ': ' . $msg);
                        } else {
                            throw new UnknowException($error . ': ' . $msg);
                        }
                    } else {
                        throw new UnknowException("HTTP error code " . $response->code . ": " . $response->body);
                    }
                } else {
                    throw new UnknowException("HTTP error code " . $response->code . ": " . $response->body);
                }
            }
        } catch (ConnectionErrorException $cee) {
            throw new ConnectionErrorException('ConnectionErrorException: ' . $cee->getMessage());
        }
    }

    /**
     * Delete a mail.
     * 
     * @param string $mailId The uuid or path of the Mail
     * @throws ConnectionErrorException
     * @throws AccessDeniedException
     * @throws RepositoryException
     * @throws PathNotFoundException
     * @throws LockException
     * @throws DatabaseException
     * @throws AutomationException
     * @throws UnknowException
     */
    public function deleteMail($mailId) {
        try {
            $uri = UriHelper::getUri($this->host, UriHelper::MAIL_DELETE);
            $uri .= '?mailId=' . urlencode($mailId);
            $client = Request::delete($uri);
            $response = $this->getClient($client);
            if ($response->code != Status::NO_CONTENT) {
                if ($response->code == Status::UNAUTHORIZED) {
                    throw new AccessDeniedException($response->body, $response->code);
                } else if ($response->code == Status::INTERNAL_SERVER_ERROR) {
                    $position = strpos($response->body, ':');
                    if ($position) {
                        $error = substr($response->body, 0, $position);
                        $msg = substr($response->body, $position + 1, strlen($response->body));
                        if ($error == TypeException::REPOSITORY_EXCEPTION) {
                            throw new RepositoryException($error . ': ' . $msg);
                        } else if ($error == TypeException::PATH_NOT_FOUND_EXCEPTION) {
                            throw new PathNotFoundException($error . ': ' . $msg);
                        } else if ($error == TypeException::LOCK_EXCEPTION) {
                            throw new LockException($error . ': ' . $msg);
                        } else if ($error == TypeException::DATABASE_EXCEPTION) {
                            throw new DatabaseException($error . ': ' . $msg);
                        } else if ($error == TypeException::AUTOMATION_EXCEPTION) {
                            throw new AutomationException($error . ': ' . $msg);
                        } else {
                            throw new UnknowException($error . ': ' . $msg);
                        }
                    } else {
                        throw new UnknowException("HTTP error code " . $response->code . ": " . $response->body);
                    }
                } else {
                    throw new UnknowException("HTTP error code " . $response->code . ": " . $response->body);
                }
            }
        } catch (ConnectionErrorException $cee) {
            throw new ConnectionErrorException('ConnectionErrorException: ' . $cee->getMessage());
        }
    }

    /**
     * Change the name of a mail.
     * 
     * From OpenKM frontend UI the subject is used to show the mail name at file browser table. That means this change will take effect internally on mail path, but will not be appreciated from default UI.
     * 
     * @param string $mailId The uuid or path of the Mail
     * @param string $newName The new name for the Mail
     * @return Mail Returns the Mail
     * @throws ConnectionErrorException
     * @throws AccessDeniedException
     * @throws RepositoryException
     * @throws PathNotFoundException
     * @throws DatabaseException
     * @throws ItemExistsException
     * @throws UnknowException
     */
    public function renameMail($mailId, $newName) {
        try {
            $uri = UriHelper::getUri($this->host, UriHelper::MAIL_RENAME);
            $uri .= '?mailId=' . urlencode($mailId) . '&newName=' . urlencode($newName);
            $client = Request::put($uri);
            $response = $this->getClient($client);
            if ($response->code == Status::OK) {
                return $this->phpMail($response->body);
            } else {
                if ($response->code == Status::UNAUTHORIZED) {
                    throw new AccessDeniedException($response->body, $response->code);
                } else if ($response->code == Status::INTERNAL_SERVER_ERROR) {
                    $position = strpos($response->body, ':');
                    if ($position) {
                        $error = substr($response->body, 0, $position);
                        $msg = substr($response->body, $position + 1, strlen($response->body));
                        if ($error == TypeException::REPOSITORY_EXCEPTION) {
                            throw new RepositoryException($error . ': ' . $msg);
                        } else if ($error == TypeException::PATH_NOT_FOUND_EXCEPTION) {
                            throw new PathNotFoundException($error . ': ' . $msg);
                        } else if ($error == TypeException::DATABASE_EXCEPTION) {
                            throw new DatabaseException($error . ': ' . $msg);
                        } else if ($error == TypeException::ITEM_EXISTS_EXCEPTION) {
                            throw new ItemExistsException($error . ': ' . $msg);
                        } else {
                            throw new UnknowException($error . ': ' . $msg);
                        }
                    } else {
                        throw new UnknowException("HTTP error code " . $response->code . ": " . $response->body);
                    }
                } else {
                    throw new UnknowException("HTTP error code " . $response->code . ": " . $response->body);
                }
            }
        } catch (ConnectionErrorException $cee) {
            throw new ConnectionErrorException('ConnectionErrorException: ' . $cee->getMessage());
        }
    }

    /**
     * Move mail into a folder or record.
     * 
     * @param string $mailId The uuid or path of the Mail
     * @param string $dstId The uuid or path of the Folder or Record
     * @throws ConnectionErrorException
     * @throws AccessDeniedException
     * @throws RepositoryException
     * @throws PathNotFoundException
     * @throws DatabaseException
     * @throws ItemExistsException
     * @throws UnknowException
     */
    public function moveMail($mailId, $dstId) {
        try {
            $uri = UriHelper::getUri($this->host, UriHelper::MAIL_MOVE);
            $uri .= '?mailId=' . urlencode($mailId) . '&dstId=' . urlencode($dstId);
            $client = Request::put($uri);
            $response = $this->getClient($client);
            if ($response->code != Status::NO_CONTENT) {
                if ($response->code == Status::UNAUTHORIZED) {
                    throw new AccessDeniedException($response->body, $response->code);
                } else if ($response->code == Status::INTERNAL_SERVER_ERROR) {
                    $position = strpos($response->body, ':');
                    if ($position) {
                        $error = substr($response->body, 0, $position);
                        $msg = substr($response->body, $position + 1, strlen($response->body));
                        if ($error == TypeException::REPOSITORY_EXCEPTION) {
                            throw new RepositoryException($error . ': ' . $msg);
                        } else if ($error == TypeException::PATH_NOT_FOUND_EXCEPTION) {
                            throw new PathNotFoundException($error . ': ' . $msg);
                        } else if ($error == TypeException::DATABASE_EXCEPTION) {
                            throw new DatabaseException($error . ': ' . $msg);
                        } else if ($error == TypeException::ITEM_EXISTS_EXCEPTION) {
                            throw new ItemExistsException($error . ': ' . $msg);
                        } else {
                            throw new UnknowException($error . ': ' . $msg);
                        }
                    } else {
                        throw new UnknowException("HTTP error code " . $response->code . ": " . $response->body);
                    }
                } else {
                    throw new UnknowException("HTTP error code " . $response->code . ": " . $response->body);
                }
            }
        } catch (ConnectionErrorException $cee) {
            throw new ConnectionErrorException('ConnectionErrorException: ' . $cee->getMessage());
        }
    }

    /**
     * Get Record children
     * 
     * @param string $fldId The uuid or path of the Folder or a record node.
     * @return array Return a list of all mails which their parent is fldId.
     * @throws ConnectionErrorException
     * @throws AccessDeniedException
     * @throws PathNotFoundException
     * @throws RepositoryException
     * @throws DatabaseException
     * @throws UnknowException
     */
    public function getMailChildren($fldId) {
        try {
            $uri = UriHelper::getUri($this->host, UriHelper::MAIL_GET_CHILDREN);
            $uri .= '?fldId=' . urlencode($fldId);
            $client = Request::get($uri);
            $response = $this->getClient($client);
            if ($response->code == Status::OK) {
                $mails = [];
                foreach ($response->body->mail as $mailXML) {
                    $mails[] = $this->phpMail($mailXML);
                }
                return $mails;
            } else {
                if ($response->code == Status::UNAUTHORIZED) {
                    throw new AccessDeniedException($response->body, $response->code);
                } else if ($response->code == Status::INTERNAL_SERVER_ERROR) {
                    $position = strpos($response->body, ':');
                    if ($position) {
                        $error = substr($response->body, 0, $position);
                        $msg = substr($response->body, $position + 1, strlen($response->body));
                        if ($error == TypeException::PATH_NOT_FOUND_EXCEPTION) {
                            throw new PathNotFoundException($error . ': ' . $msg);
                        } else if ($error == TypeException::REPOSITORY_EXCEPTION) {
                            throw new RepositoryException($error . ': ' . $msg);
                        } else if ($error == TypeException::DATABASE_EXCEPTION) {
                            throw new DatabaseException($error . ': ' . $msg);
                        } else {
                            throw new UnknowException($error . ': ' . $msg);
                        }
                    } else {
                        throw new UnknowException("HTTP error code " . $response->code . ": " . $response->body);
                    }
                } else {
                    throw new UnknowException("HTTP error code " . $response->code . ": " . $response->body);
                }
            }
        } catch (ConnectionErrorException $cee) {
            throw new ConnectionErrorException('ConnectionErrorException: ' . $cee->getMessage());
        }
    }

    /**
     * Is valid Mail
     * 
     * @param string $mailId The uuid or path of the Mail
     * @return bool Return a boolean that indicate if the node is a mail or not.
     * @throws ConnectionErrorException
     * @throws AccessDeniedException
     * @throws PathNotFoundException
     * @throws RepositoryException
     * @throws DatabaseException
     * @throws UnknowException
     */
    public function isValidMail($mailId) {
        try {
            $uri = UriHelper::getUri($this->host, UriHelper::MAIL_IS_VALID);
            $uri .= '?mailId=' . urlencode($mailId);
            $client = Request::get($uri);
            $response = $this->getClientWithHTMLResponse($client);
            if ($response->code == Status::OK) {
                if ($response->body == 'true') {
                    return true;
                } else {
                    return false;
                }
            } else {
                if ($response->code == Status::UNAUTHORIZED) {
                    throw new AccessDeniedException($response->body, $response->code);
                } else if ($response->code == Status::INTERNAL_SERVER_ERROR) {
                    $position = strpos($response->body, ':');
                    if ($position) {
                        $error = substr($response->body, 0, $position);
                        $msg = substr($response->body, $position + 1, strlen($response->body));
                        if ($error == TypeException::PATH_NOT_FOUND_EXCEPTION) {
                            throw new PathNotFoundException($error . ': ' . $msg);
                        } else if ($error == TypeException::REPOSITORY_EXCEPTION) {
                            throw new RepositoryException($error . ': ' . $msg);
                        } else if ($error == TypeException::DATABASE_EXCEPTION) {
                            throw new DatabaseException($error . ': ' . $msg);
                        } else {
                            throw new UnknowException($error . ': ' . $msg);
                        }
                    } else {
                        throw new UnknowException("HTTP error code " . $response->code . ": " . $response->body);
                    }
                } else {
                    throw new UnknowException("HTTP error code " . $response->code . ": " . $response->body);
                }
            }
        } catch (ConnectionErrorException $cee) {
            throw new ConnectionErrorException('ConnectionErrorException: ' . $cee->getMessage());
        }
    }

    /**
     * Get Mail path
     * 
     * @param string $uuid The uuid of the Document
     * @return string Convert mail UUID to mail path.
     * @throws ConnectionErrorException
     * @throws AccessDeniedException
     * @throws RepositoryException
     * @throws DatabaseException
     * @throws UnknowException
     */
    public function getMailPath($uuid) {
        try {
            $uri = UriHelper::getUri($this->host, UriHelper::MAIL_GET_PATH);
            $uri .= '/' . urlencode($uuid);
            $client = Request::get($uri);
            $response = $this->getClientWithHTMLResponse($client);
            if ($response->code == Status::OK) {
                return (string) $response->body;
            } else {
                if ($response->code == Status::UNAUTHORIZED) {
                    throw new AccessDeniedException($response->body, $response->code);
                } else if ($response->code == Status::INTERNAL_SERVER_ERROR) {
                    $position = strpos($response->body, ':');
                    if ($position) {
                        $error = substr($response->body, 0, $position);
                        $msg = substr($response->body, $position + 1, strlen($response->body));
                        if ($error == TypeException::REPOSITORY_EXCEPTION) {
                            throw new RepositoryException($error . ': ' . $msg);
                        } else if ($error == TypeException::DATABASE_EXCEPTION) {
                            throw new DatabaseException($error . ': ' . $msg);
                        } else {
                            throw new UnknowException($error . ': ' . $msg);
                        }
                    } else {
                        throw new UnknowException("HTTP error code " . $response->code . ": " . $response->body);
                    }
                } else {
                    throw new UnknowException("HTTP error code " . $response->code . ": " . $response->body);
                }
            }
        } catch (ConnectionErrorException $cee) {
            throw new ConnectionErrorException('ConnectionErrorException: ' . $cee->getMessage());
        }
    }

    /**
     * Store into the mail an attachment.
     * 
     * @param string $mailId The uuid or path of the Mail
     * @param type $docName The name of the Attachment
     * @param string $content Recommend using file_get_contents — Reads entire file into a string
     * @return Document Return as a result an object Document with the properties of the created Attachment.
     * @throws ConnectionErrorException
     * @throws AccessDeniedException
     * @throws IOException
     * @throws UnsupportMimeTypeException
     * @throws FileSizeExceededException
     * @throws UserQuotaExceededException
     * @throws VirusDetectedException
     * @throws ItemExistsException
     * @throws PathNotFoundException
     * @throws RepositoryException
     * @throws DatabaseException
     * @throws ExtensionException
     * @throws AutomationException
     * @throws UnknowException
     */
    public function createAttachment($mailId, $docName, $content) {
        try {
            $uri = UriHelper::getUri($this->host, UriHelper::MAIL_CREATE_ATTACHMENTS);
            $params = [];
            $params['mailId'] = $mailId;
            $params['docName'] = $docName;
            $params['content'] = $content;
            $client = Request::post($uri);
            $client->body($params, Mime::UPLOAD);
            $client->authenticateWith($this->user, $this->password);
            $client->expects(Mime::XML);
            $response = $client->send();
            if ($response->code == Status::OK) {
                return $this->phpDocument($response->body);
            } else {
                if ($response->code == Status::UNAUTHORIZED) {
                    throw new AccessDeniedException($response->body, $response->code);
                } else if ($response->code == Status::INTERNAL_SERVER_ERROR) {
                    $position = strpos($response->body, ':');
                    if ($position) {
                        $error = substr($response->body, 0, $position);
                        $msg = substr($response->body, $position + 1, strlen($response->body));
                        if ($error == TypeException::IO_EXCEPTION) {
                            throw new IOException($error . ': ' . $msg);
                        } else if ($error == TypeException::UNSUPPORTED_MIME_TYPE_EXCEPTION) {
                            throw new UnsupportMimeTypeException($error . ': ' . $msg);
                        } else if ($error == TypeException::FILE_SIZE_EXCEEDED_EXCEPTION) {
                            throw new FileSizeExceededException($error . ': ' . $msg);
                        } else if ($error == TypeException::USER_QUOTA_EXCEEDED_EXCEPTION) {
                            throw new UserQuotaExceededException($error . ': ' . $msg);
                        } else if ($error == TypeException::VIRUS_DETECTED_EXCEPTION) {
                            throw new VirusDetectedException($error . ': ' . $msg);
                        } else if ($error == TypeException::ITEM_EXISTS_EXCEPTION) {
                            throw new ItemExistsException($error . ': ' . $msg);
                        } else if ($error == TypeException::PATH_NOT_FOUND_EXCEPTION) {
                            throw new PathNotFoundException($error . ': ' . $msg);
                        } else if ($error == TypeException::REPOSITORY_EXCEPTION) {
                            throw new RepositoryException($error . ': ' . $msg);
                        } else if ($error == TypeException::DATABASE_EXCEPTION) {
                            throw new DatabaseException($error . ': ' . $msg);
                        } else if ($error == TypeException::EXTENSION_EXCEPTION) {
                            throw new ExtensionException($error . ': ' . $msg);
                        } else if ($error == TypeException::AUTOMATION_EXCEPTION) {
                            throw new AutomationException($error . ': ' . $msg);
                        } else {
                            throw new UnknowException($error . ': ' . $msg);
                        }
                    } else {
                        throw new UnknowException("HTTP error code " . $response->code . ": " . $response->body);
                    }
                } else {
                    throw new UnknowException("HTTP error code " . $response->code . ": " . $response->body);
                }
            }
        } catch (ConnectionErrorException $cee) {
            throw new ConnectionErrorException('ConnectionErrorException: ' . $cee->getMessage());
        }
    }

    /**
     * Delete a mail attachment.
     * 
     * @param string $mailId The uuid or path of the Mail
     * @param string $docId The uuid or path of the Document
     * @throws ConnectionErrorException
     * @throws AccessDeniedException
     * @throws PathNotFoundException
     * @throws RepositoryException
     * @throws DatabaseException
     * @throws LockException
     * @throws UnknowException
     */
    public function deleteAttachment($mailId, $docId) {
        try {
            $uri = UriHelper::getUri($this->host, UriHelper::MAIL_DELETE_ATTACHMENTS);
            $uri .= '?mailId=' . urlencode($mailId) . '&docId=' . urlencode($docId);
            $client = Request::delete($uri);
            $response = $this->getClient($client);
            if ($response->code != Status::NO_CONTENT) {
                if ($response->code == Status::UNAUTHORIZED) {
                    throw new AccessDeniedException($response->body, $response->code);
                } else if ($response->code == Status::INTERNAL_SERVER_ERROR) {
                    $position = strpos($response->body, ':');
                    if ($position) {
                        $error = substr($response->body, 0, $position);
                        $msg = substr($response->body, $position + 1, strlen($response->body));
                        if ($error == TypeException::PATH_NOT_FOUND_EXCEPTION) {
                            throw new PathNotFoundException($error . ': ' . $msg);
                        } else if ($error == TypeException::REPOSITORY_EXCEPTION) {
                            throw new RepositoryException($error . ': ' . $msg);
                        } else if ($error == TypeException::DATABASE_EXCEPTION) {
                            throw new DatabaseException($error . ': ' . $msg);
                        } else if ($error == TypeException::LOCK_EXCEPTION) {
                            throw new LockException($error . ': ' . $msg);
                        } else {
                            throw new UnknowException($error . ': ' . $msg);
                        }
                    } else {
                        throw new UnknowException("HTTP error code " . $response->code . ": " . $response->body);
                    }
                } else {
                    throw new UnknowException("HTTP error code " . $response->code . ": " . $response->body);
                }
            }
        } catch (ConnectionErrorException $cee) {
            throw new ConnectionErrorException('ConnectionErrorException: ' . $cee->getMessage());
        }
    }

    /**
     * Get Attachments 
     * 
     * @param string $mailId The uuid or path of the Mail
     * @return array Retrieve a list of all documents attatchment of a mail.
     * @throws ConnectionErrorException
     * @throws AccessDeniedException
     * @throws PathNotFoundException
     * @throws RepositoryException
     * @throws DatabaseException
     * @throws UnknowException
     */
    public function getAttachments($mailId) {
        try {
            $uri = UriHelper::getUri($this->host, UriHelper::MAIL_GET_ATTACHMENTS);
            $uri .= '?mailId=' . urlencode($mailId);
            $client = Request::get($uri);
            $response = $this->getClient($client);
            if ($response->code == Status::OK) {
                $documents = [];
                foreach ($response->body->document as $documentXML) {
                    $documents[] = $this->phpDocument($documentXML);
                }
                return $documents;
            } else {
                if ($response->code == Status::UNAUTHORIZED) {
                    throw new AccessDeniedException($response->body, $response->code);
                } else if ($response->code == Status::INTERNAL_SERVER_ERROR) {
                    $position = strpos($response->body, ':');
                    if ($position) {
                        $error = substr($response->body, 0, $position);
                        $msg = substr($response->body, $position + 1, strlen($response->body));
                        if ($error == TypeException::PATH_NOT_FOUND_EXCEPTION) {
                            throw new PathNotFoundException($error . ': ' . $msg);
                        } else if ($error == TypeException::REPOSITORY_EXCEPTION) {
                            throw new RepositoryException($error . ': ' . $msg);
                        } else if ($error == TypeException::DATABASE_EXCEPTION) {
                            throw new DatabaseException($error . ': ' . $msg);
                        } else {
                            throw new UnknowException($error . ': ' . $msg);
                        }
                    } else {
                        throw new UnknowException("HTTP error code " . $response->code . ": " . $response->body);
                    }
                } else {
                    throw new UnknowException("HTTP error code " . $response->code . ": " . $response->body);
                }
            }
        } catch (ConnectionErrorException $cee) {
            throw new ConnectionErrorException('ConnectionErrorException: ' . $cee->getMessage());
        }
    }

    /**
     * Folder is definitely removed from repository.
     * 
     * Usually you will purge mails into /okm:trash/userId - the personal trash user locations - but is possible to directly purge any mail from the whole repository.
     * 
     * When a mail is purged only will be able to be restored from a previously repository backup. The purge action remove the mail definitely from the repository.
     * 
     * @param string $mailId The uuid or path of the Mail<
     * @throws ConnectionErrorException
     * @throws AccessDeniedException
     * @throws PathNotFoundException
     * @throws RepositoryException
     * @throws DatabaseException
     * @throws LockException
     * @throws UnknowException
     */
    public function purgeMail($mailId) {
        try {
            $uri = UriHelper::getUri($this->host, UriHelper::MAIL_PURGE);
            $uri .= '?mailId=' . urlencode($mailId);
            $client = Request::put($uri);
            $response = $this->getClient($client);
            if ($response->code != Status::NO_CONTENT) {
                if ($response->code == Status::UNAUTHORIZED) {
                    throw new AccessDeniedException($response->body, $response->code);
                } else if ($response->code == Status::INTERNAL_SERVER_ERROR) {
                    $position = strpos($response->body, ':');
                    if ($position) {
                        $error = substr($response->body, 0, $position);
                        $msg = substr($response->body, $position + 1, strlen($response->body));
                        if ($error == TypeException::PATH_NOT_FOUND_EXCEPTION) {
                            throw new PathNotFoundException($error . ': ' . $msg);
                        } else if ($error == TypeException::REPOSITORY_EXCEPTION) {
                            throw new RepositoryException($error . ': ' . $msg);
                        } else if ($error == TypeException::DATABASE_EXCEPTION) {
                            throw new DatabaseException($error . ': ' . $msg);
                        } else if ($error == TypeException::LOCK_EXCEPTION) {
                            throw new LockException($error . ': ' . $msg);
                        } else {
                            throw new UnknowException($error . ': ' . $msg);
                        }
                    } else {
                        throw new UnknowException("HTTP error code " . $response->code . ": " . $response->body);
                    }
                } else {
                    throw new UnknowException("HTTP error code " . $response->code . ": " . $response->body);
                }
            }
        } catch (ConnectionErrorException $cee) {
            throw new ConnectionErrorException('ConnectionErrorException: ' . $cee->getMessage());
        }
    }

    /**
     * Copy mail into a folder or record.
     * 
     * Only the security grants are copyed to destination, the metadata, keywords, etc. of the folder are not copyed. 
     * See "extendedMailCopy" method for this feature.
     * 
     * @param string $mailId The uuid or path of the Mail
     * @param string $dstId The uuid or path of the Folder or Record
     * @param string $newName The new name for the Document. Value is null, document will preservate the same name.
     * @throws ConnectionErrorException
     * @throws AccessDeniedException
     * @throws PathNotFoundException
     * @throws RepositoryException
     * @throws DatabaseException
     * @throws ExtensionException
     * @throws ItemExistsException
     * @throws AutomationException
     * @throws IOException
     * @throws UnknowException
     */
    public function copyMail($mailId, $dstId, $newName) {
        try {
            $uri = UriHelper::getUri($this->host, UriHelper::MAIL_COPY);
            $uri .= '?mailId=' . urlencode($mailId) . '&dstId=' . urlencode($dstId) . '&newName=' . urlencode($newName);
            $client = Request::put($uri);
            $response = $this->getClient($client);
            if ($response->code != Status::NO_CONTENT) {
                if ($response->code == Status::UNAUTHORIZED) {
                    throw new AccessDeniedException($response->body, $response->code);
                } else if ($response->code == Status::INTERNAL_SERVER_ERROR) {
                    $position = strpos($response->body, ':');
                    if ($position) {
                        $error = substr($response->body, 0, $position);
                        $msg = substr($response->body, $position + 1, strlen($response->body));
                        if ($error == TypeException::REPOSITORY_EXCEPTION) {
                            throw new RepositoryException($error . ': ' . $msg);
                        } else if ($error == TypeException::PATH_NOT_FOUND_EXCEPTION) {
                            throw new PathNotFoundException($error . ': ' . $msg);
                        } else if ($error == TypeException::ITEM_EXISTS_EXCEPTION) {
                            throw new ItemExistsException($error . ': ' . $msg);
                        } else if ($error == TypeException::DATABASE_EXCEPTION) {
                            throw new DatabaseException($error . ': ' . $msg);
                        } else if ($error == TypeException::AUTOMATION_EXCEPTION) {
                            throw new AutomationException($error . ': ' . $msg);
                        } else if ($error == TypeException::IO_EXCEPTION) {
                            throw new IOException($error . ': ' . $msg);
                        } else if ($error == TypeException::USER_QUOTA_EXCEEDED_EXCEPTION) {
                            throw new UserQuotaExceededException($error . ': ' . $msg);
                        } else {
                            throw new UnknowException($error . ': ' . $msg);
                        }
                    } else {
                        throw new UnknowException("HTTP error code " . $response->code . ": " . $response->body);
                    }
                } else {
                    throw new UnknowException("HTTP error code " . $response->code . ": " . $response->body);
                }
            }
        } catch (ConnectionErrorException $cee) {
            throw new ConnectionErrorException('ConnectionErrorException: ' . $cee->getMessage());
        }
    }

    /**
     * Copy mail width with associated data into a folder or record.
     * 
     * * By default only the binary data and the security grants, the metadata, keywords etc... of the folder are not copyed.      
     * Additional:
     * 
     * > When category paramater is true the original values of the categories will be copied.
     * > When keywords paramater is true the original values of the keywords will be copied.
     * > When propertyGroups paramater is true the original values of the metadata groups will be copied.
     * > When notes paramater is true the original values of the notes will be copied.
     * > When wiki paramater is true the original values of the wiki will be copied.
     * 
     * @param string $mailId The uuid or path of the Document
     * @param string $dstId The uuid or path of the Folder or Record
     * @param bool $categories
     * @param bool $keywords
     * @param bool $propertyGroups
     * @param bool $notes
     * @param bool $wiki
     * @param string $newName The new name for the Mail. Value is null, mail will preservate the same name.
     * @throws ConnectionErrorException
     * @throws AccessDeniedException
     * @throws ItemExistsException
     * @throws PathNotFoundException
     * @throws RepositoryException
     * @throws IOException
     * @throws DatabaseException
     * @throws UserQuotaExceededException
     * @throws AutomationException
     * @throws UnknowException 
     */
    public function extendedMailCopy($mailId, $dstId, $categories, $keywords, $propertyGroups, $notes, $wiki, $newName) {
        try {
            $uri = UriHelper::getUri($this->host, UriHelper::MAIL_EXTENDED_COPY);
            $uri .= '?mailId=' . urlencode($mailId) . '&dstId=' . urlencode($dstId) . '&newName=' . urlencode($newName);
            if ($categories == 1) {
                $uri .= '&categories=true';
            } else {
                $uri.= '&categories=false';
            }
            if ($keywords == 1) {
                $uri .= '&keywords=true';
            } else {
                $uri.= '&keywords=false';
            }
            if ($propertyGroups == 1) {
                $uri .= '&propertyGroups=true';
            } else {
                $uri .= '&propertyGroups=false';
            }
            if ($notes == 1) {
                $uri .= '&notes=true';
            } else {
                $uri.= '&notes=false';
            }
            if ($wiki == 1) {
                $uri .= '&wiki=true';
            } else {
                $uri.= '&wiki=false';
            }
            $client = Request::put($uri);
            $response = $this->getClient($client);
            if ($response->code != Status::NO_CONTENT) {
                if ($response->code == Status::UNAUTHORIZED) {
                    throw new AccessDeniedException($response->body, $response->code);
                } else if ($response->code == Status::INTERNAL_SERVER_ERROR) {
                    $position = strpos($response->body, ':');
                    if ($position) {
                        $error = substr($response->body, 0, $position);
                        $msg = substr($response->body, $position + 1, strlen($response->body));
                        if ($error == TypeException::ITEM_EXISTS_EXCEPTION) {
                            throw new ItemExistsException($error . ': ' . $msg);
                        } else if ($error == TypeException::PATH_NOT_FOUND_EXCEPTION) {
                            throw new PathNotFoundException($error . ': ' . $msg);
                        } else if ($error == TypeException::REPOSITORY_EXCEPTION) {
                            throw new RepositoryException($error . ': ' . $msg);
                        } else if ($error == TypeException::IO_EXCEPTION) {
                            throw new IOException($error . ': ' . $msg);
                        } else if ($error == TypeException::DATABASE_EXCEPTION) {
                            throw new DatabaseException($error . ': ' . $msg);
                        } else if ($error == TypeException::USER_QUOTA_EXCEEDED_EXCEPTION) {
                            throw new UserQuotaExceededException($error . ': ' . $msg);
                        } else if ($error == TypeException::AUTOMATION_EXCEPTION) {
                            throw new AutomationException($error . ': ' . $msg);
                        } else {
                            throw new UnknowException($error . ': ' . $msg);
                        }
                    } else {
                        throw new UnknowException("HTTP error code " . $response->code . ": " . $response->body);
                    }
                } else {
                    throw new UnknowException("HTTP error code " . $response->code . ": " . $response->body);
                }
            }
        } catch (ConnectionErrorException $cee) {
            throw new ConnectionErrorException('ConnectionErrorException: ' . $cee->getMessage());
        }
    }
    
    /**
     * Send mail message with attachement.
     * 
     * @param string $from The mail from
     * @param array $toRecipients Array of mail accounts destination
     * @param array $ccRecipients Array of mail accounts destination (optional)
     * @param array $bccRecipients Array of mail accounts destination (optional)
     * @param string $subject The mail subject
     * @param string $body The message of the email
     * @param array $docsId Array of valid document uuid already into OpenKM that will be send as attachment into mail (optional)
     * @param string $dstId The uuid or path of the Folder or Record. The dstId parameter indicate where the mail will be stored into the repository after be sended.
     * @throws ConnectionErrorException
     * @throws AccessDeniedException
     * @throws PathNotFoundException
     * @throws ItemExistsException
     * @throws AutomationException
     * @throws VirusDetectedException
     * @throws UserQuotaExceededException
     * @throws UnsupportMimeTypeException
     * @throws FileSizeExceededException
     * @throws RepositoryException
     * @throws DatabaseException
     * @throws IOException
     * @throws UnknowException
     */
    public function sendMailWithAttachments($from, $toRecipients, $ccRecipients, $bccRecipients, $subject, $body, $docsId, $dstId) {
        try {
            $uri = UriHelper::getUri($this->host, UriHelper::MAIL_SEND_MAIL_WITH_ATTACHMENTS);
            $params['from'] = $from;
            $params['subject'] = $subject;
            $params['dstId'] = $dstId;
            $to = '';
            foreach ($toRecipients as $value) {
                $to .= $value . ';';
            }
            $params['to'] = substr($to, 0, strlen($to) - 1);

            $cc = '';
            foreach ($ccRecipients as $value) {
                $cc .= $value . ';';
            }
            if (!empty($cc)) {
                $params['cc'] = substr($cc, 0, strlen($cc) - 1);
            }

            $bcc = '';
            foreach ($bccRecipients as $value) {
                $bcc .= $value . ';';
            }
            if (!empty($bcc)) {
                $params['bcc'] = substr($bcc, 0, strlen($bcc) - 1);
            }

            $documents = '';
            foreach ($docsId as $value) {
                $documents .= $value . ';';
            }
            if (!empty($documents)) {
                $params['docsId'] = substr($documents, 0, strlen($documents) - 1);
            }
            $params['body'] = $body;
            $client = Request::post($uri);
            $client->body($params, Mime::UPLOAD);
            $client->authenticateWith($this->user, $this->password);
            $response = $client->send();
            if ($response->code != Status::NO_CONTENT) {
                if ($response->code == Status::UNAUTHORIZED) {
                    throw new AccessDeniedException($response->body, $response->code);
                } else if ($response->code == Status::INTERNAL_SERVER_ERROR) {
                    $position = strpos($response->body, ':');
                    if ($position) {
                        $error = substr($response->body, 0, $position);
                        $msg = substr($response->body, $position + 1, strlen($response->body));
                        if ($error == TypeException::PATH_NOT_FOUND_EXCEPTION) {
                            throw new PathNotFoundException($error . ': ' . $msg);
                        } else if ($error == TypeException::ITEM_EXISTS_EXCEPTION) {
                            throw new ItemExistsException($error . ': ' . $msg);
                        } else if ($error == TypeException::AUTOMATION_EXCEPTION) {
                            throw new AutomationException($error . ': ' . $msg);
                        } else if ($error == TypeException::VIRUS_DETECTED_EXCEPTION) {
                            throw new VirusDetectedException($error . ': ' . $msg);
                        } else if ($error == TypeException::USER_QUOTA_EXCEEDED_EXCEPTION) {
                            throw new UserQuotaExceededException($error . ': ' . $msg);
                        } else if ($error == TypeException::UNSUPPORTED_MIME_TYPE_EXCEPTION) {
                            throw new UnsupportMimeTypeException($error . ': ' . $msg);
                        } else if ($error == TypeException::FILE_SIZE_EXCEEDED_EXCEPTION) {
                            throw new FileSizeExceededException($error . ': ' . $msg);
                        } else if ($error == TypeException::REPOSITORY_EXCEPTION) {
                            throw new RepositoryException($error . ': ' . $msg);
                        } else if ($error == TypeException::DATABASE_EXCEPTION) {
                            throw new DatabaseException($error . ': ' . $msg);
                        } else if ($error == TypeException::IO_EXCEPTION) {
                            throw new IOException($error . ': ' . $msg);
                        } else {
                            throw new UnknowException($error . ': ' . $msg);
                        }
                    } else {
                        throw new UnknowException("HTTP error code " . $response->code . ": " . $response->body);
                    }
                } else {
                    throw new UnknowException("HTTP error code " . $response->code . ": " . $response->body);
                }
            }
        } catch (ConnectionErrorException $cee) {
            throw new ConnectionErrorException('ConnectionErrorException: ' . $cee->getMessage());
        }
    }

    /**
     * Import a mail in EML format.
     * 
     * @param string $dstId The uuid or path of the Folder or Record. The dstId parameter indicate where the mail will be stored in the repository after is sent.
     * @param string $title The title of the Mail. 
     * @param string $content Recommend using file_get_contents — Reads entire file into a string
     * @return Mail Returns the Mail
     * @throws ConnectionErrorException
     * @throws AccessDeniedException
     * @throws MessagingException
     * @throws PathNotFoundException
     * @throws DatabaseException
     * @throws ItemExistsException
     * @throws AutomationException
     * @throws VirusDetectedException
     * @throws UserQuotaExceededException
     * @throws UnsupportMimeTypeException
     * @throws FileSizeExceededException
     * @throws RepositoryException
     * @throws ExtensionException
     * @throws IOException
     * @throws UnknowException
     */
    public function importEml($dstId, $title, $content) {
        try {
            $uri = UriHelper::getUri($this->host, UriHelper::MAIL_IMPORT_EML);
            $params = [];
            $params['dstId'] = $dstId;
            $params['title'] = $title;
            $params['content'] = $content;
            $client = Request::post($uri);
            $client->body($params, Mime::UPLOAD);
            $client->authenticateWith($this->user, $this->password);
            $client->expects(Mime::XML);
            $response = $client->send();
            if ($response->code == Status::OK) {
                return $this->phpMail($response->body);
            } else {
                if ($response->code == Status::UNAUTHORIZED) {
                    throw new AccessDeniedException($response->body, $response->code);
                } else if ($response->code == Status::INTERNAL_SERVER_ERROR) {
                    $position = strpos($response->body, ':');
                    if ($position) {
                        $error = substr($response->body, 0, $position);
                        $msg = substr($response->body, $position + 1, strlen($response->body));
                        if ($error == TypeException::MESSAGING_EXCEPTION) {
                            throw new MessagingException($error . ': ' . $msg);
                        } else if ($error == TypeException::PATH_NOT_FOUND_EXCEPTION) {
                            throw new PathNotFoundException($error . ': ' . $msg);
                        } else if ($error == TypeException::DATABASE_EXCEPTION) {
                            throw new DatabaseException($error . ': ' . $msg);
                        } else if ($error == TypeException::ITEM_EXISTS_EXCEPTION) {
                            throw new ItemExistsException($error . ': ' . $msg);
                        } else if ($error == TypeException::AUTOMATION_EXCEPTION) {
                            throw new AutomationException($error . ': ' . $msg);
                        } else if ($error == TypeException::VIRUS_DETECTED_EXCEPTION) {
                            throw new VirusDetectedException($error . ': ' . $msg);
                        } else if ($error == TypeException::USER_QUOTA_EXCEEDED_EXCEPTION) {
                            throw new UserQuotaExceededException($error . ': ' . $msg);
                        } else if ($error == TypeException::UNSUPPORTED_MIME_TYPE_EXCEPTION) {
                            throw new UnsupportMimeTypeException($error . ': ' . $msg);
                        } else if ($error == TypeException::FILE_SIZE_EXCEEDED_EXCEPTION) {
                            throw new FileSizeExceededException($error . ': ' . $msg);
                        } else if ($error == TypeException::REPOSITORY_EXCEPTION) {
                            throw new RepositoryException($error . ': ' . $msg);
                        } else if ($error == TypeException::DATABASE_EXCEPTION) {
                            throw new DatabaseException($error . ': ' . $msg);
                        } else if ($error == TypeException::EXTENSION_EXCEPTION) {
                            throw new ExtensionException($error . ': ' . $msg);
                        } else if ($error == TypeException::IO_EXCEPTION) {
                            throw new IOException($error . ': ' . $msg);
                        } else {
                            throw new UnknowException($error . ': ' . $msg);
                        }
                    } else {
                        throw new UnknowException("HTTP error code " . $response->code . ": " . $response->body);
                    }
                } else {
                    throw new UnknowException("HTTP error code " . $response->code . ": " . $response->body);
                }
            }
        } catch (ConnectionErrorException $cee) {
            throw new ConnectionErrorException('ConnectionErrorException: ' . $cee->getMessage());
        }
    }

    /**
     * Import a mail in MSG format.
     * 
     * @param string $dstId The uuid or path of the Folder or Record. The dstId parameter indicate where the mail will be stored in the repository after is sent.
     * @param string $title The title of the Mail. 
     * @param string $content Recommend using file_get_contents — Reads entire file into a string
     * @return Mail Returns the Mail
     * @throws ConnectionErrorException
     * @throws AccessDeniedException
     * @throws MessagingException
     * @throws PathNotFoundException
     * @throws DatabaseException
     * @throws ItemExistsException
     * @throws AutomationException
     * @throws VirusDetectedException
     * @throws UserQuotaExceededException
     * @throws UnsupportMimeTypeException
     * @throws FileSizeExceededException
     * @throws RepositoryException
     * @throws ExtensionException
     * @throws IOException
     * @throws UnknowException
     */
    public function importMsg($dstId, $title, $content) {
        try {
            $uri = UriHelper::getUri($this->host, UriHelper::MAIL_IMPORT_MSG);
            $params = [];
            $params['dstId'] = $dstId;
            $params['title'] = $title;
            $params['content'] = $content;
            $client = Request::post($uri);
            $client->body($params, Mime::UPLOAD);
            $client->authenticateWith($this->user, $this->password);
            $client->expects(Mime::XML);
            $response = $client->send();
            if ($response->code == Status::OK) {
                return $this->phpMail($response->body);
            } else {
                if ($response->code == Status::UNAUTHORIZED) {
                    throw new AccessDeniedException($response->body, $response->code);
                } else if ($response->code == Status::INTERNAL_SERVER_ERROR) {
                    $position = strpos($response->body, ':');
                    if ($position) {
                        $error = substr($response->body, 0, $position);
                        $msg = substr($response->body, $position + 1, strlen($response->body));
                        if ($error == TypeException::MESSAGING_EXCEPTION) {
                            throw new MessagingException($error . ': ' . $msg);
                        } else if ($error == TypeException::PATH_NOT_FOUND_EXCEPTION) {
                            throw new PathNotFoundException($error . ': ' . $msg);
                        } else if ($error == TypeException::DATABASE_EXCEPTION) {
                            throw new DatabaseException($error . ': ' . $msg);
                        } else if ($error == TypeException::ITEM_EXISTS_EXCEPTION) {
                            throw new ItemExistsException($error . ': ' . $msg);
                        } else if ($error == TypeException::AUTOMATION_EXCEPTION) {
                            throw new AutomationException($error . ': ' . $msg);
                        } else if ($error == TypeException::VIRUS_DETECTED_EXCEPTION) {
                            throw new VirusDetectedException($error . ': ' . $msg);
                        } else if ($error == TypeException::USER_QUOTA_EXCEEDED_EXCEPTION) {
                            throw new UserQuotaExceededException($error . ': ' . $msg);
                        } else if ($error == TypeException::UNSUPPORTED_MIME_TYPE_EXCEPTION) {
                            throw new UnsupportMimeTypeException($error . ': ' . $msg);
                        } else if ($error == TypeException::FILE_SIZE_EXCEEDED_EXCEPTION) {
                            throw new FileSizeExceededException($error . ': ' . $msg);
                        } else if ($error == TypeException::REPOSITORY_EXCEPTION) {
                            throw new RepositoryException($error . ': ' . $msg);
                        } else if ($error == TypeException::DATABASE_EXCEPTION) {
                            throw new DatabaseException($error . ': ' . $msg);
                        } else if ($error == TypeException::EXTENSION_EXCEPTION) {
                            throw new ExtensionException($error . ': ' . $msg);
                        } else if ($error == TypeException::IO_EXCEPTION) {
                            throw new IOException($error . ': ' . $msg);
                        } else {
                            throw new UnknowException($error . ': ' . $msg);
                        }
                    } else {
                        throw new UnknowException("HTTP error code " . $response->code . ": " . $response->body);
                    }
                } else {
                    throw new UnknowException("HTTP error code " . $response->code . ": " . $response->body);
                }
            }
        } catch (ConnectionErrorException $cee) {
            throw new ConnectionErrorException('ConnectionErrorException: ' . $cee->getMessage());
        }
    }

    /**
     * Set Mail title.
     * 
     * @param string $mailId The uuid or path of the Document
     * @param string $title The title of the Mail
     * @throws ConnectionErrorException
     * @throws AccessDeniedException
     * @throws RepositoryException
     * @throws PathNotFoundException
     * @throws DatabaseException
     * @throws LockException
     * @throws UnknowException
     */
    public function setMailTitle($mailId, $title) {
        try {
            $uri = UriHelper::getUri($this->host, UriHelper::MAIL_SET_TITLE);
            $uri .= '?mailId=' . urlencode($mailId) . '&title=' . urlencode($title);
            $client = Request::put($uri);
            $response = $this->getClient($client);
            if ($response->code != Status::NO_CONTENT) {
                if ($response->code == Status::UNAUTHORIZED) {
                    throw new AccessDeniedException($response->body, $response->code);
                } else if ($response->code == Status::INTERNAL_SERVER_ERROR) {
                    $position = strpos($response->body, ':');
                    if ($position) {
                        $error = substr($response->body, 0, $position);
                        $msg = substr($response->body, $position + 1, strlen($response->body));
                        if ($error == TypeException::REPOSITORY_EXCEPTION) {
                            throw new RepositoryException($error . ': ' . $msg);
                        } else if ($error == TypeException::PATH_NOT_FOUND_EXCEPTION) {
                            throw new PathNotFoundException($error . ': ' . $msg);
                        } else if ($error == TypeException::DATABASE_EXCEPTION) {
                            throw new DatabaseException($error . ': ' . $msg);
                        } else if ($error == TypeException::LOCK_EXCEPTION) {
                            throw new LockException($error . ': ' . $msg);
                        } else {
                            throw new UnknowException($error . ': ' . $msg);
                        }
                    } else {
                        throw new UnknowException("HTTP error code " . $response->code . ": " . $response->body);
                    }
                } else {
                    throw new UnknowException("HTTP error code " . $response->code . ": " . $response->body);
                }
            }
        } catch (ConnectionErrorException $cee) {
            throw new ConnectionErrorException('ConnectionErrorException: ' . $cee->getMessage());
        }
    }

    /**
     * Sends a mail.
     * 
     * @param string $subject The mail subject
     * @param string $body The message of the email     
     * @param array $recipients Array of mail accounts destination     
     * @throws ConnectionErrorException
     * @throws AccessDeniedException
     * @throws IOException
     * @throws UnknowException
     */
    public function sendMail($subject, $body, $recipients = []) {
        try {
            $uri = UriHelper::getUri($this->host, UriHelper::MAIL_SEND_MAIL);
            $params['subject'] = $subject;
            $params['body'] = $body;
            $recipient = '';
            foreach ($recipients as $value) {
                $recipient .= $value . ';';
            }
            $params['recipient'] = substr($recipient, 0, strlen($recipient) - 1);

            $client = Request::post($uri);
            $client->body($params, Mime::UPLOAD);
            $client->authenticateWith($this->user, $this->password);
            $response = $client->send();
            if ($response->code != Status::NO_CONTENT) {
                if ($response->code == Status::UNAUTHORIZED) {
                    throw new AccessDeniedException($response->body, $response->code);
                } else if ($response->code == Status::INTERNAL_SERVER_ERROR) {
                    $position = strpos($response->body, ':');
                    if ($position) {
                        $error = substr($response->body, 0, $position);
                        $msg = substr($response->body, $position + 1, strlen($response->body));
                        if ($error == TypeException::IO_EXCEPTION) {
                            throw new IOException($error . ': ' . $msg);
                        } else {
                            throw new UnknowException($error . ': ' . $msg);
                        }
                    } else {
                        throw new UnknowException("HTTP error code " . $response->code . ": " . $response->body);
                    }
                } else {
                    throw new UnknowException("HTTP error code " . $response->code . ": " . $response->body);
                }
            }
        } catch (ConnectionErrorException $cee) {
            throw new ConnectionErrorException('ConnectionErrorException: ' . $cee->getMessage());
        }
    }
}
