/**
  * Decrypt a message and download the files of the message to the $outputFolder
  *
  * Note: This does not check the MAC before, which you should always do when
  * you want to use this in your own application! Use {@link checkMac()} for doing so.
  *
  * @param string $threemaId The sender ID (= the ID the message came from)
  * @param string $messageId
  * @param string $box box as binary string
  * @param string $nonce nonce as binary string
  * @param string|null|false $outputFolder folder for storing the files,
  * 							null=current folder, false=do not download files
  * @param \Closure $downloadMessage
  * @return ReceiveMessageResult
  * @throws Exception
  * @throws \Threema\MsgApi\Exceptions\BadMessageException
  * @throws \Threema\MsgApi\Exceptions\DecryptionFailedException
  * @throws \Threema\MsgApi\Exceptions\UnsupportedMessageTypeException
  */
 public final function receiveMessage($threemaId, $messageId, $box, $nonce, $outputFolder = null, \Closure $downloadMessage = null)
 {
     //fetch the public key
     $receiverPublicKey = $this->connection->fetchPublicKey($threemaId);
     if (null === $receiverPublicKey || !$receiverPublicKey->isSuccess()) {
         throw new Exception('Invalid threema id');
     }
     $message = $this->cryptTool->decryptMessage($box, $this->privateKey, $this->cryptTool->hex2bin($receiverPublicKey->getPublicKey()), $nonce);
     if (null === $message || false === is_object($message)) {
         throw new Exception('Could not encrypt box');
     }
     $receiveResult = new ReceiveMessageResult($messageId, $message);
     if ($outputFolder === false) {
         return $receiveResult;
     }
     if ($outputFolder === null || strlen($outputFolder) == 0) {
         $outputFolder = '.';
     }
     if ($message instanceof ImageMessage) {
         $result = $this->downloadFile($message, $message->getBlobId(), $downloadMessage);
         if (null !== $result && true === $result->isSuccess()) {
             $image = $this->cryptTool->decryptImage($result->getData(), $this->cryptTool->hex2bin($receiverPublicKey->getPublicKey()), $this->privateKey, $message->getNonce());
             if (null === $image) {
                 throw new Exception('decryption of image failed');
             }
             //save file
             $filePath = $outputFolder . '/' . $messageId . '.jpg';
             $f = fopen($filePath, 'w+');
             fwrite($f, $image);
             fclose($f);
             $receiveResult->addFile('image', $filePath);
         }
     } else {
         if ($message instanceof FileMessage) {
             $result = $this->downloadFile($message, $message->getBlobId(), $downloadMessage);
             if (null !== $result && true === $result->isSuccess()) {
                 $file = $this->cryptTool->decryptFile($result->getData(), $this->cryptTool->hex2bin($message->getEncryptionKey()));
                 if (null === $file) {
                     throw new Exception('file decryption failed');
                 }
                 //save file
                 $filePath = $outputFolder . '/' . $messageId . '-' . $message->getFilename();
                 file_put_contents($filePath, $file);
                 $receiveResult->addFile('file', $filePath);
             }
             if (null !== $message->getThumbnailBlobId() && strlen($message->getThumbnailBlobId()) > 0) {
                 $result = $this->downloadFile($message, $message->getThumbnailBlobId(), $downloadMessage);
                 if (null !== $result && true === $result->isSuccess()) {
                     $file = $this->cryptTool->decryptFileThumbnail($result->getData(), $this->cryptTool->hex2bin($message->getEncryptionKey()));
                     if (null === $file) {
                         throw new Exception('thumbnail decryption failed');
                     }
                     //save file
                     $filePath = $outputFolder . '/' . $messageId . '-thumbnail-' . $message->getFilename();
                     file_put_contents($filePath, $file);
                     $receiveResult->addFile('thumbnail', $filePath);
                 }
             }
         }
     }
     return $receiveResult;
 }