{"id":28462581,"url":"https://github.com/tutao/oxmsg","last_synced_at":"2025-07-01T04:32:54.279Z","repository":{"id":45027129,"uuid":"328675524","full_name":"tutao/oxmsg","owner":"tutao","description":"Write Microsoft .msg Outlook Item files.","archived":false,"fork":false,"pushed_at":"2024-01-30T12:32:37.000Z","size":2894,"stargazers_count":13,"open_issues_count":2,"forks_count":6,"subscribers_count":15,"default_branch":"master","last_synced_at":"2025-06-07T04:32:04.977Z","etag":null,"topics":["email","msg","outlook"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/tutao.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2021-01-11T13:38:37.000Z","updated_at":"2025-03-30T10:02:08.000Z","dependencies_parsed_at":"2022-09-05T09:40:30.620Z","dependency_job_id":null,"html_url":"https://github.com/tutao/oxmsg","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/tutao/oxmsg","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tutao%2Foxmsg","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tutao%2Foxmsg/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tutao%2Foxmsg/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tutao%2Foxmsg/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/tutao","download_url":"https://codeload.github.com/tutao/oxmsg/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tutao%2Foxmsg/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":262897594,"owners_count":23381450,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["email","msg","outlook"],"created_at":"2025-06-07T04:30:38.173Z","updated_at":"2025-07-01T04:32:54.264Z","avatar_url":"https://github.com/tutao.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# oxmsg\n\nwrite Microsoft .msg Outlook Item files.\n\n## MSG Outlook Items\nThese are compound files in cfb format, which is a simplified \nfilesystem-in-a-file with directories (called storages) and files (called streams).\n\nmsg can contain outlook appointments and emails, they consist of a property stream in the top-level storage and several\nsub-storages (ie for attachments).\n\nStreams contain either raw data or a list of Properties of 16 bytes each. \nProperties consist of a 2 byte type (binary, boolean, long etc), 2 byte id (usage), 4 bytes of flags and 8 bytes of value.\nProperty tags (the first 4 bytes of a property) are defined in `lib/property_tags.js`.\n\n## MsgKit\n[MsgKit](https://github.com/Sicos1977/MsgKit) is the C# library oxmsg was based on. \n\n### Emails\nWhen creating a new Email instance, oxmsg will prepare the data structure to store all attributes, \nlike a list of attachments, a list of recipients, and so on. These can be filled by adding the items to the Email object.\n\nThe final .msg will be created by calling .msg() on the Email, at which point the Email object will serialize itself into \na cfb compound file provided by [`cfb`](https://www.npmjs.com/package/cfb), which is then written to an Uint8Array.\nExample usage in examples/node.js.\n\n### Appointments\nMsgKit also supports exporting Outlook Appointments to msg, but those parts are not translated yet.\n\n## TODO\n- The library currently works in node, but could be made to work in the browser if it's shrunk and the dependencies that rely on node Buffers are replaced (mainly the parsers in lib/mime/header/ that use iconv-lite). BigInt would need to be polyfilled and bigint literals removed\n- it would probably be good to generate/provide an `index.d.ts` type definition file, which should not be too hard since the actual API surface is tiny.\n- The library has the capability to parse email headers if that should be necessary (`lib/mime/header/`), but that's not\ndone yet.\n- There's also code to read .msg files into an Email object that's not useful yet\n\nThe next steps would include using the library to export mails and figure out if the api makes sense and if the timestamps match expectations.\n\n## Docs \u0026 Tools\n\n- [OxMsg Spec](https://interoperability.blob.core.windows.net/files/MS-OXMSG/%5bMS-OXMSG%5d.pdf)\n- [CFB Spec](https://winprotocoldoc.blob.core.windows.net/productionwindowsarchives/MS-CFB/%5bMS-CFB%5d.pdf)\n\n### CFB viewer\n[online cfb viewer](https://oss.sheetjs.com/cfb-editor/#/cfb-editor/)\n\nThis online tool (made by the developers of the `cfb` library) shows the contents of a .msg file, consisting of all storages with their names, and streams with their contents (in hex and ASCII).\n\n### Comparer\n`examples/comparer.js` is a small utility that takes two cfb files and shows the differences between them. It will show streams/storages that are contained in only one of them, and if the element is contained in both but has different contents, it will show the difference.\n\nExample (run with `-a` after the files to compare to show identical elements as well): \n```\n$ node examples/comparer.js test/testOut_attach.msg test/msgKitOut_attach.msg -a\n\nMISSING: 4 Root Entry/Sh33tJ5 not in /home/nils/Projects/repositories/oxmsg/test/msgKitOut_attach.msg\ntag: undefined\n0000: 37 32 36 32\n7262\n\nSAME: size: 38 Root Entry/__substg1.0_0E1D001F\ntag: PR_NORMALIZED_SUBJECT_W\n\nDIFFERENCE: 72:72 Root Entry/__substg1.0_0FFF0102 type 2\ntag: PR_ENTRYID\ntest/testOut_attach.msg                               || test/msgKitOut_attach.msg\nno tag                                                || no tag                                               \n0000: 65 00 65 00 36 00 62 00 30 00 34 00 35 00 62 00 || 64 00 35 00 66 00 62 00 36 00 38 00 61 00 35 00\nno tag                                                || no tag                                               \n0010: 2d 00 61 00 31 00 64 00 63 00 2d 00 34 00 64 00 || 2d 00 30 00 37 00 37 00 66 00 2d 00 34 00 63 00\nno tag                                                || no tag                                               \n0020: 38 00 62 00 2d 00 38 00 34 00 31 00 65 00 2d 00 || 36 00 66 00 2d 00 38 00 66 00 66 00 31 00 2d 00\nno tag                                                || no tag                                               \n0030: 63 00 34 00 35 00 36 00 38 00 39 00 63 00 37 00 || 38 00 61 00 34 00 38 00 35 00 32 00 39 00 37 00\nno tag                                                || no tag                                               \n0040: 63 00 36 00 36 00 33 00                         || 30 00 63 00 31 00 61 00\nee6b045b-a1dc-4d8b-841e-c45689c7c663\nd5fb68a5-077f-4c6f-8ff1-8a4852970c1a\n\nDIFFERENCE: 644:644 Root Entry/__properties_version1.0 type 2\ntag: undefined\ntest/testOut_attach.msg                               || test/msgKitOut_attach.msg\nPR_CLIENT_SUBMIT_TIME                                 || PR_CLIENT_SUBMIT_TIME                                \n00c0: 40 00 39 00 06 00 00 00 00 00 00 00 00 00 00 00 || 40 00 39 00 06 00 00 00 00 3f cf 4e 90 4d d2 01\nPR_CREATION_TIME                                      || PR_CREATION_TIME                                     \n0140: 40 00 07 30 06 00 00 00 00 00 00 00 00 00 00 00 || 40 00 07 30 06 00 00 00 9c 93 95 53 cc ce d6 01\nPR_LAST_MODIFICATION_TIME                             || PR_LAST_MODIFICATION_TIME                            \n0150: 40 00 08 30 06 00 00 00 00 00 00 00 00 00 00 00 || 40 00 08 30 06 00 00 00 9c 93 95 53 cc ce d6 01\nno tag                                                || no tag                                               \n0270: 03 00 08 0e 06 00 00 00 00 00 00 00 00 00 00 00 || 03 00 08 0e 06 00 00 00 64 fa 03 00 00 00 00 00\n4848\n\n    ????\n        @9???7((=p(@00? \n```\nThis is part of the result of comparing MsgKit Output and oxmsg output with the same contents.\n- It's reporting that the stream `Root Entry/Sh33tJ` is in the oxmsg output, but not added by MsgKit (that's a \"maker's mark\" added by the devs of `cfb` that doesn't impact functionality). The `4` means that the stream contains 4 bytes, `tag: undefined` means that there's no meaningful part of a .msg file associated with the stream name and `0000: 37 32 36 32` | `7262` are the contents of the stream in hex and ascii. `type 2` just means it's a stream and not a storage.\n- The stream `Root Entry/__substg1.0_0E1D001F` is contained in both files and identical. Its name is associated with the property tag `PR_NORMALIZED_SUBJECT_W` (which can be searched in the code to find out about it) and 38 bytes long.\n- `Root Entry/__substg1.0_0FFF0102` is contained in both, but different. `72:72` means that both streams are 72 bytes long (if they don't have the same length, it's likely that the content listing below won't line up). The name is associated with `PR_ENTRYID` which, if looked up in `lib/property_tags.js`, contains binary data (a GUID in ascii, to be precise, which should be different).\n- `Root Entry/__properties_version1.0` is the top-level properties stream, which doesn't have an associated property tag. It contains several different properties that are different. The `PR_CLIENT_SUBMIT_TIME` property at offset `00c0` is different between the two files (`oxmsg` set it to 0), as is the creation time and the last modification time. The property at `0270` is a checksum at the end of the stream.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftutao%2Foxmsg","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftutao%2Foxmsg","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftutao%2Foxmsg/lists"}