TNEF Parser for Node.js
node-tnef is a Node.js library designed to parse Transport Neutral Encapsulation Format (TNEF) files, commonly encountered as `winmail.dat` attachments in emails. This proprietary Microsoft format is often sent by Outlook users but is not natively understood by other email clients. The library extracts embedded content and attachments from these files, addressing a niche but persistent interoperability problem. It offers both a command-line interface for direct file or directory parsing and a programmatic API for use within Node.js projects, primarily through its `parse` (for file paths) and `parseBuffer` (for in-memory buffers) methods. The current stable version is 1.4.0. The package maintains an ad-hoc release cadence, focusing on bug fixes and feature enhancements, such as the addition of `parseBuffer` in version 1.3.0 and the removal of the `bluebird` dependency in 1.4.0.
Common errors
-
Error: Cannot find module 'bluebird'
cause An application (or an older version of node-tnef) implicitly or explicitly expected `bluebird` to be available, but it was removed in v1.4.0 or not installed.fixFor `node-tnef` v1.4.0 and later, `bluebird` is no longer a dependency. If your project still requires `bluebird`, install it explicitly: `npm install bluebird`. -
TypeError: tnef.parse is not a function
cause This error often occurs when attempting to use ESM `import { parse } from 'node-tnef'` or similar destructuring, but the module primarily exposes an object via CommonJS `module.exports` or properties on `module.exports`.fixEnsure you are using the CommonJS `require` syntax and accessing methods as properties: `const tnef = require('node-tnef'); tnef.parse(...);` -
Error: callback is not a function
cause The `parse` or `parseBuffer` method was called without providing a valid callback function as its second argument, or the provided argument was not a function.fixAlways provide a callback function in the format `(err, content) => { ... }` as the second argument to `tnef.parse` and `tnef.parseBuffer`. -
file does not contain the TNEF signature
cause The input file specified to `tnef.parse` (or a file within a directory scanned by the CLI) was not a valid TNEF file. The library detected that the file did not begin with the expected TNEF magic number.fixVerify that the file you are attempting to parse is indeed a TNEF-encoded file (e.g., typically named `winmail.dat`). The library will skip non-TNEF files without throwing a programmatic error, but logs this message to the console.
Warnings
- gotcha The library utilizes a callback-based asynchronous API (`(err, content) => { ... }`) for its `parse` and `parseBuffer` methods. Modern Node.js development often favors Promises or async/await syntax. Developers expecting Promise-based functions will need to wrap the callback-based methods or adapt their code accordingly.
- breaking In version 1.4.0, the `bluebird` promise library was removed as a dependency. While primarily an internal change for promise management, if any consuming application had an implicit reliance on `bluebird` being present or its specific promise behavior when interacting with `node-tnef`'s internals, this could lead to unexpected behavior.
- gotcha When processing files or directories, `node-tnef` explicitly checks for the TNEF signature. If a file does not contain this signature, the parser will log a message to the console and skip the file without throwing an error in the programmatic API. Users should implement their own validation if specific error handling for non-TNEF files is required.
Install
-
npm install node-tnef -
yarn add node-tnef -
pnpm add node-tnef
Imports
- tnef
import tnef from 'node-tnef'
const tnef = require('node-tnef') - tnef.parse
import { parse } from 'node-tnef'const tnef = require('node-tnef'); tnef.parse('/path/to/winmail.dat', (err, content) => { /* ... */ }); - tnef.parseBuffer
import { parseBuffer } from 'node-tnef'const tnef = require('node-tnef'); tnef.parseBuffer(yourBuffer, (err, content) => { /* ... */ });
Quickstart
const tnef = require('node-tnef');
const fs = require('fs');
const path = require('path');
// A minimal, valid TNEF signature prefix for demonstration.
// A real winmail.dat file would be much larger and complex.
const dummyTnefBuffer = Buffer.from(
'\x22\x34\x71\x9A\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00',
'binary'
);
tnef.parseBuffer(dummyTnefBuffer, (err, content) => {
if (err) {
console.error('Error parsing TNEF buffer:', err);
return;
}
if (content && content.length > 0) {
console.log(`Found ${content.length} attachment(s).`);
const firstAttachment = content[0];
console.log('First attachment title:', firstAttachment.Title);
// Example: Writing the attachment data to a file
const outputPath = path.join(__dirname, firstAttachment.Title || 'extracted_attachment.bin');
fs.writeFile(outputPath, firstAttachment.Data, (writeErr) => {
if (writeErr) {
console.error('Error writing attachment to file:', writeErr);
} else {
console.log(`Attachment written to: ${outputPath}`);
}
});
} else {
console.log('No attachments or content found in TNEF buffer.');
}
});