{"id":16156,"library":"nodemailer-fetch","title":"Nodemailer HTTP Fetcher","description":"nodemailer-fetch is a focused utility library designed to efficiently fetch HTTP URL contents. While primarily created to complement the Nodemailer ecosystem by providing a mechanism to retrieve remote content for email templates or attachments, it serves as a standalone HTTP client for general-purpose requests. The current stable version is 2.1.0. It generally follows a stable, on-demand release cadence typical for a mature utility module. Its key differentiators include robust handling of redirects (up to 5 by default), automatic gzip decompression, comprehensive cookie management with domain specificity, and built-in support for basic authentication, though with a notable caveat regarding redirects. It offers configurable TLS options and allows for custom HTTP methods (GET, POST), headers, and request bodies, making it flexible for various data fetching scenarios.","status":"active","version":"2.1.0","language":"javascript","source_language":"en","source_url":"https://github.com/nodemailer/nodemailer-fetch","tags":["javascript","nodemailer","http"],"install":[{"cmd":"npm install nodemailer-fetch","lang":"bash","label":"npm"},{"cmd":"yarn add nodemailer-fetch","lang":"bash","label":"yarn"},{"cmd":"pnpm add nodemailer-fetch","lang":"bash","label":"pnpm"}],"dependencies":[],"imports":[{"note":"The package is CommonJS-only and does not provide an ESM export. Direct `import` statements will result in a runtime error without a suitable transpilation step.","wrong":"import fetch from 'nodemailer-fetch';","symbol":"fetch","correct":"const fetch = require('nodemailer-fetch');"}],"quickstart":{"code":"const fetch = require('nodemailer-fetch');\n\n// Example 1: Basic GET request and pipe response to stdout\nconsole.log('Fetching a public URL and piping response to stdout...');\nfetch('https://jsonplaceholder.typicode.com/posts/1')\n    .then(response => {\n        if (!response || response.statusCode >= 400) {\n            throw new Error(`HTTP Error: ${response ? response.statusCode : 'No response'}`);\n        }\n        console.log(`\nStatus Code: ${response.statusCode}`);\n        console.log('Headers:', response.headers);\n        console.log('Body:');\n        return response;\n    })\n    .then(response => {\n        response.pipe(process.stdout);\n        response.on('end', () => console.log('\\n--- Basic GET fetch complete ---'));\n    })\n    .catch(error => console.error('Error during basic GET fetch:', error.message));\n\n// Example 2: POST request with custom body, headers, and timeout\nconsole.log('\\nSending a POST request with custom options...');\nfetch('https://jsonplaceholder.typicode.com/posts', {\n    method: 'POST',\n    body: {\n        title: 'foo',\n        body: 'bar',\n        userId: 1\n    },\n    contentType: 'application/json', // Override default x-www-form-urlencoded\n    headers: {\n        'Accept': 'application/json',\n        'User-Agent': 'NodemailerFetchDemo/1.0'\n    },\n    timeout: 5000, // 5 seconds timeout for the connection\n    allowErrorResponse: true // Process response even if status code is non-2xx\n})\n.then(response => {\n    if (!response) {\n        throw new Error('No response received for POST request');\n    }\n    console.log(`\nPOST Status Code: ${response.statusCode}`);\n    return new Promise((resolve, reject) => {\n        let data = '';\n        response.on('data', chunk => data += chunk);\n        response.on('end', () => {\n            try {\n                resolve(JSON.parse(data));\n            } catch (e) {\n                reject(new Error(`Failed to parse JSON response: ${data.substring(0, 100)}...`));\n            }\n        });\n        response.on('error', reject);\n    });\n})\n.then(json => {\n    console.log('POST Response Body:', json);\n    console.log('--- Custom POST fetch complete ---');\n})\n.catch(error => console.error('Error during custom POST fetch:', error.message));","lang":"javascript","description":"Demonstrates basic HTTP GET and more complex POST requests, including piping the response, handling custom headers, body serialization, and setting timeouts."},"warnings":[{"fix":"Ensure the initial URL does not redirect, or handle authentication for redirected requests manually if the server supports session-based authentication.","message":"Basic authentication credentials are lost after the first HTTP redirect. If your target URL involves redirects and requires basic auth, the authentication will not be re-sent to the redirected location.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"Be mindful of cookie attributes (domain, secure flag) when dealing with redirects or mixed HTTP/HTTPS content. If cookies are critical across domains, consider alternative session management or re-sending them explicitly.","message":"Cookies are domain-specific and are not passed to different domains during redirects. Additionally, HTTPS-only cookies will not be sent to HTTP URLs, even within the same domain.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"Set the `tls` option with appropriate `rejectUnauthorized: true` (or similar) settings to enforce stricter SSL validation, especially for sensitive data or production usage. Consult Node.js TLS documentation for detailed options.","message":"By default, `nodemailer-fetch` allows invalid SSL certificates. This can pose a security risk in production environments as it disables critical security checks.","severity":"gotcha","affected_versions":">=1.0.0"}],"env_vars":null,"last_verified":"2026-04-21T00:00:00.000Z","next_check":"2026-07-20T00:00:00.000Z","problems":[{"fix":"Change your import statement from `import fetch from 'nodemailer-fetch';` to `const fetch = require('nodemailer-fetch');`. If your project is ESM-only, you might need to use dynamic `import('nodemailer-fetch')` or reconfigure your build system to handle CJS modules.","cause":"Attempting to use `import` syntax (ES Modules) with `nodemailer-fetch`, which is a CommonJS module.","error":"Error [ERR_REQUIRE_ESM]: require() of ES Module ... not supported. Instead change the require of ... to a dynamic import()"},{"fix":"Increase the `timeout` option value (in milliseconds) if the server typically takes longer to respond, or check network connectivity and firewall settings between your application and the target server.","cause":"The HTTP request timed out before a response was received. This could be due to network issues, a slow server, or an overly aggressive timeout setting.","error":"Error: ETIMEDOUT"},{"fix":"If you expect and need to process non-successful HTTP responses, set the `allowErrorResponse: true` option in your fetch call. Otherwise, ensure the target URL and server logic are correct.","cause":"The remote server responded with a non-2xx status code (e.g., 404 Not Found, 500 Internal Server Error) and `allowErrorResponse` option was not set to `true`.","error":"Error: HTTP Error: 4xx (or 5xx)"}],"ecosystem":"npm"}