{"record":{"id":"f9218d764ac24302","repo":"deepset-ai/haystack","slug":"the-msg-file-is-encrypted-and-cannot-be-read","errorCode":null,"errorMessage":"The MSG file is encrypted and cannot be read.","messagePattern":"The MSG file is encrypted and cannot be read\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"haystack/components/converters/msg.py","lineNumber":91,"sourceCode":"        \"\"\"\n        recip_str = \"\"\n        if recip.name != \"\":\n            recip_str += f\"{recip.name} \"\n        if recip.email_address != \"\":\n            recip_str += f\"{recip.email_address}\"\n        return recip_str\n\n    def _convert(self, file_content: io.BytesIO) -> tuple[str, list[ByteStream]]:\n        \"\"\"\n        Converts the MSG file content into text and extracts any attachments.\n\n        :param file_content: The MSG file content as a binary stream.\n        :returns: A tuple containing the extracted email text and a list of ByteStream objects for attachments.\n        :raises ValueError: If the MSG file is encrypted and cannot be read.\n        \"\"\"\n        msg = Message.load(file_content)\n        if self._is_encrypted(msg):\n            raise ValueError(\"The MSG file is encrypted and cannot be read.\")\n\n        txt = \"\"\n\n        # Sender\n        if msg.sender is not None:\n            txt += f\"From: {msg.sender}\\n\"\n\n        # To\n        recipients_str = \",\".join(self._create_recipient_str(r) for r in msg.recipients)\n        if recipients_str != \"\":\n            txt += f\"To: {recipients_str}\\n\"\n\n        # CC\n        cc_header = msg.message_headers.get(\"Cc\") or msg.message_headers.get(\"CC\")\n        if cc_header is not None:\n            txt += f\"Cc: {cc_header}\\n\"\n\n        # BCC","sourceCodeStart":73,"sourceCodeEnd":109,"githubUrl":"https://github.com/deepset-ai/haystack/blob/e318778c9bf60a1963e3b5f451359655dd696c30/haystack/components/converters/msg.py#L73-L109","documentation":"MSGToDocument._convert detects whether the loaded MSG (Outlook .msg) file is encrypted via _is_encrypted(msg); encrypted MSG files cannot be parsed by the extract-msg backend, so the component raises ValueError to signal the file is unreadable rather than returning garbage.","triggerScenarios":"Calling MSGToDocument.run() on a ByteStream whose content is an encrypted/DRM-protected Outlook .msg file; Message.load succeeds structurally but _is_encrypted returns True.","commonSituations":"Processing corporate mailboxes with Information Rights Management (IRM/DRM) protected emails; batch-converting archived .msg files where some are S/MIME encrypted.","solutions":["Obtain a decrypted copy of the .msg file before conversion","Skip the encrypted file and log/flag it in your pipeline (catch ValueError around run)","Ask the sender to resend the email without encryption/DRM protection"],"exampleFix":"// before\ntext, attachments = converter.run(sources=[encrypted_stream])\n// after\ntry:\n    text, attachments = converter.run(sources=[stream])\nexcept ValueError:\n    skipped.append(stream)  # handle encrypted file separately","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try:\n    text, attachments = msg_converter.run(sources=[stream])\nexcept ValueError as e:\n    if \"encrypted\" in str(e):\n        log.warning(\"Skipping encrypted MSG: %s\", stream.meta.get(\"file_name\"))\n    else:\n        raise","preventionTips":["Pre-scan .msg corpora for encryption flags before batch conversion","Request unencrypted/DRM-free copies for ingestion pipelines","Isolate per-file conversion in try/except so one encrypted file doesn't halt a batch"],"tags":["python","haystack","msg-converter","encryption","email"],"backgroundTag":"encrypted-file-unreadable","analyzedSha":"e318778c9bf60a1963e3b5f451359655dd696c30","analyzedAt":"2026-08-30T11:45:20.711Z","schemaVersion":2},"datasetVersion":"2026-08-30T13:17:10.514Z"}