UNPKG

postal-mime

Version:

Email parser for Node.js and browser environments

258 lines (255 loc) 8.43 kB
"use strict"; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); var decode_strings_exports = {}; __export(decode_strings_exports, { blobToArrayBuffer: () => blobToArrayBuffer, decodeBase64: () => decodeBase64, decodeParameterValueContinuations: () => decodeParameterValueContinuations, decodeURIComponentWithCharset: () => decodeURIComponentWithCharset, decodeWord: () => decodeWord, decodeWords: () => decodeWords, getDecoder: () => getDecoder, getHex: () => getHex, textEncoder: () => textEncoder }); module.exports = __toCommonJS(decode_strings_exports); const textEncoder = new TextEncoder(); const base64Chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; const base64Lookup = new Uint8Array(256); for (let i = 0; i < base64Chars.length; i++) { base64Lookup[base64Chars.charCodeAt(i)] = i; } function decodeBase64(base64) { let bufferLength = Math.ceil(base64.length / 4) * 3; const len = base64.length; let p = 0; if (base64.length % 4 === 3) { bufferLength--; } else if (base64.length % 4 === 2) { bufferLength -= 2; } else if (base64[base64.length - 1] === "=") { bufferLength--; if (base64[base64.length - 2] === "=") { bufferLength--; } } const arrayBuffer = new ArrayBuffer(bufferLength); const bytes = new Uint8Array(arrayBuffer); for (let i = 0; i < len; i += 4) { let encoded1 = base64Lookup[base64.charCodeAt(i)]; let encoded2 = base64Lookup[base64.charCodeAt(i + 1)]; let encoded3 = base64Lookup[base64.charCodeAt(i + 2)]; let encoded4 = base64Lookup[base64.charCodeAt(i + 3)]; bytes[p++] = encoded1 << 2 | encoded2 >> 4; bytes[p++] = (encoded2 & 15) << 4 | encoded3 >> 2; bytes[p++] = (encoded3 & 3) << 6 | encoded4 & 63; } return arrayBuffer; } function getDecoder(charset) { charset = charset || "utf8"; let decoder; try { decoder = new TextDecoder(charset); } catch (err) { decoder = new TextDecoder("windows-1252"); } return decoder; } async function blobToArrayBuffer(blob) { if ("arrayBuffer" in blob) { return await blob.arrayBuffer(); } const fr = new FileReader(); return new Promise((resolve, reject) => { fr.onload = function(e) { resolve(e.target.result); }; fr.onerror = function(e) { reject(fr.error); }; fr.readAsArrayBuffer(blob); }); } function getHex(c) { if (c >= 48 && c <= 57 || c >= 97 && c <= 102 || c >= 65 && c <= 70) { return String.fromCharCode(c); } return false; } function decodeWord(charset, encoding, str) { let splitPos = charset.indexOf("*"); if (splitPos >= 0) { charset = charset.substr(0, splitPos); } encoding = encoding.toUpperCase(); let byteStr; if (encoding === "Q") { str = str.replace(/=\s+([0-9a-fA-F])/g, "=$1").replace(/[_\s]/g, " "); let buf = textEncoder.encode(str); let encodedBytes = []; for (let i = 0, len = buf.length; i < len; i++) { let c = buf[i]; if (i <= len - 2 && c === 61) { let c1 = getHex(buf[i + 1]); let c2 = getHex(buf[i + 2]); if (c1 && c2) { let c3 = parseInt(c1 + c2, 16); encodedBytes.push(c3); i += 2; continue; } } encodedBytes.push(c); } byteStr = new ArrayBuffer(encodedBytes.length); let dataView = new DataView(byteStr); for (let i = 0, len = encodedBytes.length; i < len; i++) { dataView.setUint8(i, encodedBytes[i]); } } else if (encoding === "B") { byteStr = decodeBase64(str.replace(/[^a-zA-Z0-9\+\/=]+/g, "")); } else { byteStr = textEncoder.encode(str); } return getDecoder(charset).decode(byteStr); } function decodeWords(str) { let joinString = true; let done = false; while (!done) { let result = (str || "").toString().replace( /(=\?([^?]+)\?[Bb]\?([^?]*)\?=)\s*(?==\?([^?]+)\?[Bb]\?[^?]*\?=)/g, (match, left, chLeft, encodedLeftStr, chRight) => { if (!joinString) { return match; } if (chLeft === chRight && encodedLeftStr.length % 4 === 0 && !/=$/.test(encodedLeftStr)) { return left + "__\0JOIN\0__"; } return match; } ).replace( /(=\?([^?]+)\?[Qq]\?[^?]*\?=)\s*(?==\?([^?]+)\?[Qq]\?[^?]*\?=)/g, (match, left, chLeft, chRight) => { if (!joinString) { return match; } if (chLeft === chRight) { return left + "__\0JOIN\0__"; } return match; } ).replace(/(\?=)?__\x00JOIN\x00__(=\?([^?]+)\?[QqBb]\?)?/g, "").replace(/(=\?[^?]+\?[QqBb]\?[^?]*\?=)\s+(?==\?[^?]+\?[QqBb]\?[^?]*\?=)/g, "$1").replace( /=\?([\w_\-*]+)\?([QqBb])\?([^?]*)\?=/g, (m, charset, encoding, text) => decodeWord(charset, encoding, text) ); if (joinString && result.indexOf("\uFFFD") >= 0) { joinString = false; } else { return result; } } } function decodeURIComponentWithCharset(encodedStr, charset) { charset = charset || "utf-8"; let encodedBytes = []; for (let i = 0; i < encodedStr.length; i++) { let c = encodedStr.charAt(i); if (c === "%" && /^[a-f0-9]{2}/i.test(encodedStr.substr(i + 1, 2))) { let byte = encodedStr.substr(i + 1, 2); i += 2; encodedBytes.push(parseInt(byte, 16)); } else if (c.charCodeAt(0) > 126) { c = textEncoder.encode(c); for (let j = 0; j < c.length; j++) { encodedBytes.push(c[j]); } } else { encodedBytes.push(c.charCodeAt(0)); } } const byteStr = new ArrayBuffer(encodedBytes.length); const dataView = new DataView(byteStr); for (let i = 0, len = encodedBytes.length; i < len; i++) { dataView.setUint8(i, encodedBytes[i]); } return getDecoder(charset).decode(byteStr); } function decodeParameterValueContinuations(header) { let paramKeys = /* @__PURE__ */ new Map(); Object.keys(header.params).forEach((key) => { let match = key.match(/\*((\d+)\*?)?$/); if (!match) { return; } let actualKey = key.substr(0, match.index).toLowerCase(); let nr = Number(match[2]) || 0; let paramVal; if (!paramKeys.has(actualKey)) { paramVal = { charset: false, values: [] }; paramKeys.set(actualKey, paramVal); } else { paramVal = paramKeys.get(actualKey); } let value = header.params[key]; if (nr === 0 && match[0].charAt(match[0].length - 1) === "*" && (match = value.match(/^([^']*)'[^']*'(.*)$/))) { paramVal.charset = match[1] || "utf-8"; value = match[2]; } paramVal.values.push({ nr, value }); delete header.params[key]; }); paramKeys.forEach((paramVal, key) => { header.params[key] = decodeURIComponentWithCharset( paramVal.values.sort((a, b) => a.nr - b.nr).map((a) => a.value).join(""), paramVal.charset ); }); } // Annotate the CommonJS export names for ESM import in node: 0 && (module.exports = { blobToArrayBuffer, decodeBase64, decodeParameterValueContinuations, decodeURIComponentWithCharset, decodeWord, decodeWords, getDecoder, getHex, textEncoder }); // Make default export work naturally with require() if (module.exports.default) { var defaultExport = module.exports.default; var namedExports = {}; for (var key in module.exports) { if (key !== 'default' && key !== '__esModule') { namedExports[key] = module.exports[key]; } } module.exports = defaultExport; Object.assign(module.exports, namedExports); // Preserve __esModule and .default for bundler/transpiler interop Object.defineProperty(module.exports, '__esModule', { value: true }); module.exports.default = defaultExport; }