├── .eslintrc ├── .gitattributes ├── .github ├── FUNDING.yml └── workflows │ ├── release.yaml │ └── test.yml ├── .gitignore ├── .ncurc.js ├── .npmignore ├── .prettierrc.js ├── CHANGELOG.md ├── Gruntfile.js ├── LICENSE ├── README.md ├── bench ├── bench.sh ├── parse.js └── passthrough.js ├── examples ├── emailtojson.js ├── nodemailer.eml ├── pipe.js ├── simple-async.js ├── simple-options.js ├── simple.eml └── simple.js ├── index.js ├── lib ├── mail-parser.js ├── simple-parser.js └── stream-hash.js ├── package-lock.json ├── package.json └── test ├── cpanel-test.js ├── delivery-status-test.js ├── fixtures ├── base64encodedroot.eml ├── decoderended.eml ├── delivery-status.eml ├── htmllargecallstack.eml ├── large_text.eml ├── mixed.eml ├── nested.eml ├── nodemailer.eml ├── outofmemory.eml └── spam.eml ├── flowed-test.js ├── issue-221-test.js ├── issue-272-test.js ├── issue-337-test.js ├── long-references-test.js ├── mail-parser-test.js ├── rfc822-headers-only-test.js └── simple-parser-test.js /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["nodemailer", "prettier"], 3 | "parserOptions": { 4 | "ecmaVersion": 2017 5 | }, 6 | "rules": { 7 | "no-useless-concat": 0 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | *.js text eol=lf -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: [andris9] # enable once enrolled 4 | custom: ['https://www.paypal.me/nodemailer'] 5 | -------------------------------------------------------------------------------- /.github/workflows/release.yaml: -------------------------------------------------------------------------------- 1 | on: 2 | push: 3 | branches: 4 | - master 5 | 6 | permissions: 7 | contents: write 8 | pull-requests: write 9 | id-token: write 10 | 11 | name: release 12 | jobs: 13 | release-please: 14 | runs-on: ubuntu-latest 15 | steps: 16 | - uses: google-github-actions/release-please-action@v3 17 | id: release 18 | with: 19 | release-type: node 20 | package-name: ${{vars.NPM_MODULE_NAME}} 21 | pull-request-title-pattern: 'chore${scope}: release ${version} [skip-ci]' 22 | # The logic below handles the npm publication: 23 | - uses: actions/checkout@v3 24 | # these if statements ensure that a publication only occurs when 25 | # a new release is created: 26 | if: ${{ steps.release.outputs.release_created }} 27 | - uses: actions/setup-node@v3 28 | with: 29 | node-version: 18 30 | registry-url: 'https://registry.npmjs.org' 31 | if: ${{ steps.release.outputs.release_created }} 32 | - run: npm ci 33 | if: ${{ steps.release.outputs.release_created }} 34 | - run: npm publish --provenance --access public 35 | env: 36 | NODE_AUTH_TOKEN: ${{secrets.NPM_TOKEN}} 37 | if: ${{ steps.release.outputs.release_created }} 38 | -------------------------------------------------------------------------------- /.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | name: Run tests 2 | 3 | on: 4 | push: 5 | pull_request: 6 | 7 | jobs: 8 | test: 9 | strategy: 10 | matrix: 11 | node: [18.x, 20.x, 21.x] 12 | os: [ubuntu-latest] 13 | runs-on: ${{ matrix.os }} 14 | steps: 15 | - uses: actions/checkout@v3 16 | - name: Use Node.js ${{ matrix.node }} 17 | uses: actions/setup-node@v3 18 | with: 19 | node-version: ${{ matrix.node }} 20 | - run: npm install 21 | - run: npm test 22 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .DS_Store 3 | npm-debug.log 4 | .npmrc 5 | 6 | -------------------------------------------------------------------------------- /.ncurc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | upgrade: true, 3 | reject: [ 4 | // api changes, check and fix 5 | 'eslint', 6 | 'grunt-eslint', 7 | 'eslint-config-prettier' 8 | ] 9 | }; 10 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | bench 2 | examples 3 | test 4 | .eslintrc 5 | .travis.yml 6 | Gruntfile.js 7 | -------------------------------------------------------------------------------- /.prettierrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | printWidth: 160, 3 | tabWidth: 4, 4 | singleQuote: true, 5 | endOfLine: 'lf', 6 | trailingComma: 'none', 7 | arrowParens: 'avoid' 8 | }; 9 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | ## [3.7.3](https://github.com/nodemailer/mailparser/compare/v3.7.2...v3.7.3) (2025-05-20) 4 | 5 | 6 | ### Bug Fixes 7 | 8 | * Bumped deps ([9e084f9](https://github.com/nodemailer/mailparser/commit/9e084f9f265ddcfbf8ad3a3e68fc0645d4eb9d1d)) 9 | 10 | ## [3.7.2](https://github.com/nodemailer/mailparser/compare/v3.7.1...v3.7.2) (2024-11-29) 11 | 12 | 13 | ### Bug Fixes 14 | 15 | * **deps:** Bumped deps to fix issue with missing whitespace ([92884d0](https://github.com/nodemailer/mailparser/commit/92884d0619efa77042ecc35fbc887e93a59e5a93)) 16 | 17 | ## [3.7.1](https://github.com/nodemailer/mailparser/compare/v3.7.0...v3.7.1) (2024-04-25) 18 | 19 | 20 | ### Bug Fixes 21 | 22 | * **deps:** Replaced 'punycode' with 'punycode.js' module ([4a15157](https://github.com/nodemailer/mailparser/commit/4a15157dc9a815aa0e756d9e6ae0e8631842c447)) 23 | 24 | ## [3.7.0](https://github.com/nodemailer/mailparser/compare/v3.6.9...v3.7.0) (2024-04-01) 25 | 26 | 27 | ### Features 28 | 29 | * **events:** Emit a new headerLines event to gain access the raw headers ([#364](https://github.com/nodemailer/mailparser/issues/364)) ([d33d7ec](https://github.com/nodemailer/mailparser/commit/d33d7ec4b8e32a4eb7a9a664cec5fdb545c274af)) 30 | 31 | ## [3.6.9](https://github.com/nodemailer/mailparser/compare/v3.6.8...v3.6.9) (2024-02-29) 32 | 33 | 34 | ### Bug Fixes 35 | 36 | * **deps:** Bumped deps ([db842ad](https://github.com/nodemailer/mailparser/commit/db842addd36e2fe94d0c4b466da80719a36f47ac)) 37 | 38 | ## [3.6.8](https://github.com/nodemailer/mailparser/compare/v3.6.7...v3.6.8) (2024-02-29) 39 | 40 | 41 | ### Bug Fixes 42 | 43 | * **punycode:** Fixes [#355](https://github.com/nodemailer/mailparser/issues/355) Deprecation warning of the punycode module ([#356](https://github.com/nodemailer/mailparser/issues/356)) ([0f35330](https://github.com/nodemailer/mailparser/commit/0f35330c87d715d38e8c853ae6c2f64d098b971d)) 44 | 45 | ## [3.6.7](https://github.com/nodemailer/mailparser/compare/v3.6.6...v3.6.7) (2024-02-01) 46 | 47 | 48 | ### Bug Fixes 49 | 50 | * :arrow_up: update nodemailer dependency to resolve security issue GHSA-9h6g-pr28-7cqp ([#357](https://github.com/nodemailer/mailparser/issues/357)) ([8bc4225](https://github.com/nodemailer/mailparser/commit/8bc42251fca6f538ece599f0a5bebe09b0aeff4f)) 51 | 52 | ## [3.6.6](https://github.com/nodemailer/mailparser/compare/v3.6.5...v3.6.6) (2024-01-04) 53 | 54 | 55 | ### Bug Fixes 56 | 57 | * **deploy:** added auto-deployment ([d6eb56f](https://github.com/nodemailer/mailparser/commit/d6eb56fe09fe8b415e5bbf2e53704f6788ca0fee)) 58 | * Fix produced text address list string according to rfc 2822 ([#340](https://github.com/nodemailer/mailparser/issues/340)) ([6bae600](https://github.com/nodemailer/mailparser/commit/6bae600a3f4a0452ee7ca43634a11939de7bcc6d)) 59 | * **test:** updated test matrix (18, 20, 21) ([a2ba9c2](https://github.com/nodemailer/mailparser/commit/a2ba9c236dcd7f990c9d53a386ffaa5b564181b3)) 60 | -------------------------------------------------------------------------------- /Gruntfile.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | module.exports = function(grunt) { 4 | // Project configuration. 5 | grunt.initConfig({ 6 | eslint: { 7 | all: ['lib/**/*.js', 'test/**/*.js', 'examples/**/*.js', 'Gruntfile.js'] 8 | }, 9 | 10 | nodeunit: { 11 | all: ['test/**/*-test.js'] 12 | } 13 | }); 14 | 15 | // Load the plugin(s) 16 | grunt.loadNpmTasks('grunt-eslint'); 17 | grunt.loadNpmTasks('grunt-contrib-nodeunit'); 18 | 19 | // Tasks 20 | grunt.registerTask('default', ['eslint', 'nodeunit']); 21 | }; 22 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2020 - 2021 Andris Reinman 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 11 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 12 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 13 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 14 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 15 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 16 | SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # mailparser 2 | 3 | ![Nodemailer](https://raw.githubusercontent.com/nodemailer/nodemailer/master/assets/nm_logo_200x136.png) 4 | 5 | Advanced email parser for Node.js. Everything is handled as a stream which should make it able to parse even very large messages (100MB+) with relatively low overhead. 6 | 7 | ## Looking for a front-end solution? 8 | 9 | _mailparser_ is Node.js only library, so you can't use it reliably in the front-end or bundle with WebPack. If you do need a solution to parse emails in the front-end then use [PostalMime](https://www.npmjs.com/package/postal-mime). 10 | 11 | ## Installation 12 | 13 | First install the module from npm: 14 | 15 | ``` 16 | $ npm install mailparser 17 | ``` 18 | 19 | next import the `mailparser` object into your script: 20 | 21 | ```js 22 | const mailparser = require('mailparser'); 23 | ``` 24 | 25 | ## Usage 26 | 27 | See [mailparser homepage](https://nodemailer.com/extras/mailparser/) for documentation and terms. 28 | 29 | ### License 30 | 31 | Licensed under MIT 32 | -------------------------------------------------------------------------------- /bench/bench.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | MESSAGES=20000 4 | 5 | MESSAGES=$MESSAGES node passthrough.js 6 | MESSAGES=$MESSAGES node parse.js 7 | -------------------------------------------------------------------------------- /bench/parse.js: -------------------------------------------------------------------------------- 1 | /* eslint no-console: 0 */ 2 | 3 | 'use strict'; 4 | 5 | const MailParser = require('../index.js').MailParser; 6 | const randomMessage = require('random-message'); 7 | const messages = Number(process.env.MESSAGES) || 10000; 8 | 9 | const Transform = require('stream').Transform; 10 | 11 | const messagesRoot = '/Users/andris/Projects/nodemailer/Gmail/Messages'; 12 | let processed = 0; 13 | let startTime = Date.now(); 14 | let bytes = 0; 15 | 16 | class Counter extends Transform { 17 | constructor() { 18 | super(); 19 | this.bytes = 0; 20 | } 21 | _transform(chunk, encoding, done) { 22 | this.bytes += chunk.length; 23 | done(null, chunk); 24 | } 25 | _flush(done) { 26 | bytes += this.bytes; 27 | done(); 28 | } 29 | } 30 | 31 | let processNext = () => { 32 | if (++processed >= messages) { 33 | let time = (Date.now() - startTime) / 1000; 34 | let avg = Math.round(processed / time); 35 | console.log( 36 | 'Done. %s messages [%s MB] processed in %s s. with average of %s messages/sec [%s MB/s]', 37 | processed, 38 | Math.round(bytes / (1024 * 1024)), 39 | time, 40 | avg, 41 | Math.round(bytes / (1024 * 1024) / time) 42 | ); 43 | return; 44 | } 45 | 46 | let parser = new MailParser(); 47 | parser.on('readable', () => { 48 | let data; 49 | while ((data = parser.read()) !== null) { 50 | if (data.type === 'attachment') { 51 | data.content.on('data', () => false); 52 | data.content.on('end', data.release); 53 | } 54 | } 55 | }); 56 | 57 | parser.on('end', () => { 58 | parser = false; 59 | setImmediate(processNext); 60 | }); 61 | 62 | parser.on('error', err => { 63 | console.log(err); 64 | }); 65 | 66 | //randomMessage.get(messagesRoot, (processed * 0x10000).toString(16)).pipe(require('fs').createWriteStream('test.eml')); 67 | 68 | randomMessage 69 | .get(messagesRoot, (processed * 0x10000).toString(16)) 70 | .pipe(new Counter()) 71 | .pipe(parser); 72 | }; 73 | 74 | console.log('Streaming %s random messages through MailParser', messages); 75 | processNext(); 76 | -------------------------------------------------------------------------------- /bench/passthrough.js: -------------------------------------------------------------------------------- 1 | /* eslint no-console:0 */ 2 | 3 | 'use strict'; 4 | 5 | const PassThrough = require('stream').PassThrough; 6 | const randomMessage = require('random-message'); 7 | const messages = Number(process.env.MESSAGES) || 10000; 8 | 9 | const messagesRoot = '/Users/andris/Projects/nodemailer/Gmail/Messages'; 10 | let processed = 0; 11 | let startTime = Date.now(); 12 | let bytes = 0; 13 | 14 | let processNext = () => { 15 | if (++processed >= messages) { 16 | let time = (Date.now() - startTime) / 1000; 17 | let avg = Math.round(processed / time); 18 | console.log( 19 | 'Done. %s messages [%s MB] processed in %s s. with average of %s messages/sec [%s MB/s]', 20 | processed, 21 | Math.round(bytes / (1024 * 1024)), 22 | time, 23 | avg, 24 | Math.round(bytes / (1024 * 1024) / time) 25 | ); 26 | return; 27 | } 28 | 29 | let stream = new PassThrough(); 30 | 31 | stream.on('readable', () => { 32 | let chunk; 33 | while ((chunk = stream.read()) !== null) { 34 | bytes += chunk.length; 35 | } 36 | }); 37 | 38 | stream.on('end', () => { 39 | stream = false; 40 | setImmediate(processNext); 41 | }); 42 | 43 | randomMessage.get(messagesRoot, (processed * 0x10000).toString(16)).pipe(stream); 44 | }; 45 | 46 | console.log('Streaming %s random messages through a plain PassThrough', messages); 47 | processNext(); 48 | -------------------------------------------------------------------------------- /examples/emailtojson.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | if (process.argv.length < 3) { 4 | process.stdout.write('USAGE: nodejs emailtojson.js filename'); 5 | process.stdout.write('Example: nodejs emailtojson.js emailfile.eml'); 6 | return; 7 | } 8 | 9 | const fs = require('fs'); 10 | const MailParser = require('../lib/mail-parser'); 11 | 12 | const mailpath = process.argv[2]; 13 | 14 | let parser = new MailParser(); 15 | let input = fs.createReadStream(mailpath); 16 | let mailobj = { 17 | attachments: [], 18 | text: {} 19 | }; 20 | 21 | parser.on('headers', headers => { 22 | let headerObj = {}; 23 | for (let [k, v] of headers) { 24 | // We don’t escape the key '__proto__' 25 | // which can cause problems on older engines 26 | headerObj[k] = v; 27 | } 28 | 29 | mailobj.headers = headerObj; 30 | }); 31 | 32 | parser.on('data', data => { 33 | if (data.type === 'attachment') { 34 | mailobj.attachments.push(data); 35 | data.content.on('readable', () => data.content.read()); 36 | data.content.on('end', () => data.release()); 37 | } else { 38 | mailobj.text = data; 39 | } 40 | }); 41 | 42 | parser.on('end', () => { 43 | process.stdout.write(JSON.stringify(mailobj, (k, v) => (k === 'content' || k === 'release' ? undefined : v), 3)); 44 | }); 45 | input.pipe(parser); 46 | -------------------------------------------------------------------------------- /examples/nodemailer.eml: -------------------------------------------------------------------------------- 1 | Delivered-To: andris.reinman@gmail.com 2 | Received: by 10.28.50.2 with SMTP id y2csp233403wmy; 3 | Thu, 13 Oct 2016 04:39:49 -0700 (PDT) 4 | X-Received: by 10.25.37.18 with SMTP id l18mr9511740lfl.88.1476358789184; 5 | Thu, 13 Oct 2016 04:39:49 -0700 (PDT) 6 | Return-Path: 7 | Received: from srs1.zonevs.eu (srs1.zonevs.eu. [217.146.68.191]) 8 | by mx.google.com with ESMTPS id l202si1012799lfg.293.2016.10.13.04.39.49 9 | for 10 | (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); 11 | Thu, 13 Oct 2016 04:39:49 -0700 (PDT) 12 | Received-SPF: pass (google.com: best guess record for domain of srs0=63fc=v7=kreata.ee=andris@srs1.zonevs.eu designates 217.146.68.191 as permitted sender) client-ip=217.146.68.191; 13 | Authentication-Results: mx.google.com; 14 | dkim=pass header.i=@srs1.zonevs.eu; 15 | spf=pass (google.com: best guess record for domain of srs0=63fc=v7=kreata.ee=andris@srs1.zonevs.eu designates 217.146.68.191 as permitted sender) smtp.mailfrom=SRS0=63fc=V7=kreata.ee=andris@srs1.zonevs.eu; 16 | dmarc=fail (p=NONE dis=NONE) header.from=kreata.ee 17 | DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=srs1.zonevs.eu; 18 | q=dns/txt; s=oct2016; bh=xKHKChGY0vTH8NsecmXwA0OqbinKOXeQbaC2UYp2BAM=; 19 | h=from:subject:date:message-id:to:mime-version:content-type; 20 | b=Ve18ogdCAG+7WZYkJPOewe1hKjhN4k9unz7bVHMXd6+1CQDRUkLCArQZJzSKxkM481nzXfjFn 21 | bI8qOuQL8mRk/8fAjYhxLgnr/3SyVIOhCnXxjdQkRzgouZyl42hqD0gIaCxu9uodtQrp2pbKvyl 22 | e+3sG+LhcdJmsPguOfILn14j+irinPSWrospC8PBIDTsUwO8DCyPqSlOADbW0B6TRUHWMf4XUX4 23 | W8TH61H1ZI3Xu3k0bvX7rsGHZjsy8dcshcnfYENLCLep8fsQMaB15EErc3RXycBX7CBd0iU1l50 24 | pYpUFd6bZehCF0ipTOgA7IJ7ZPafaH0YTU8wRntXOwbg== 25 | Received: from host29.guest.zone.eu [217.146.66.6] 26 | by srs1.zonevs.eu (ZoneMTA Forwarder) with ESMTP id 157bdd754f70005750.002 27 | for ; 28 | Thu, 13 Oct 2016 11:39:48 +0000 29 | Content-Type: multipart/mixed; 30 | boundary="----sinikael-?=_1-14763587882000.8241290969717285" 31 | X-Laziness-Level: 1000 32 | From: Andris Kreata 33 | To: Andris Reinman , andris.reinman@gmail.com 34 | Subject: Nodemailer is unicode friendly =?UTF-8?Q?=E2=9C=94?= 35 | (1476358788189) 36 | Message-ID: <012d606e-3550-2d94-b566-6cd996de88e3@kreata.ee> 37 | X-Mailer: nodemailer (2.6.0; +http://nodemailer.com/; 38 | SMTP/2.7.2[client:2.12.0]) 39 | Date: Thu, 13 Oct 2016 11:39:48 +0000 40 | MIME-Version: 1.0 41 | X-Zone-Spam-Resolution: no action 42 | X-Zone-Spam-Status: No, score=0.408099, required=15, tests=[MIME_GOOD=-0.1, 43 | R_MISSING_CHARSET=2.5, DMARC_POLICY_SOFTFAIL=0.1, MIME_UNKNOWN=0.1, 44 | R_DKIM_NA=0, BAYES_HAM=-2.1919] 45 | X-Original-Sender: andris@kreata.ee 46 | X-Zone-Forwarded-For: andris@kreata.ee 47 | X-Zone-Forwarded-To: andris.reinman@gmail.com 48 | 49 | ------sinikael-?=_1-14763587882000.8241290969717285 50 | Content-Type: multipart/alternative; 51 | boundary="----sinikael-?=_2-14763587882000.8241290969717285" 52 | 53 | ------sinikael-?=_2-14763587882000.8241290969717285 54 | Content-Type: text/plain 55 | Content-Transfer-Encoding: 7bit 56 | 57 | Hello to myself! http://www.nodemailer.com/ 58 | ------sinikael-?=_2-14763587882000.8241290969717285 59 | Content-Type: text/watch-html 60 | Content-Transfer-Encoding: 7bit 61 | 62 | Hello to myself 63 | ------sinikael-?=_2-14763587882000.8241290969717285 64 | Content-Type: multipart/related; type="text/html"; 65 | boundary="----sinikael-?=_5-14763587882000.8241290969717285" 66 | 67 | ------sinikael-?=_5-14763587882000.8241290969717285 68 | Content-Type: text/html 69 | Content-Transfer-Encoding: quoted-printable 70 | 71 |

Hello to myself

Here's = 72 | a nyan cat for you as an embedded attachment:

74 | ------sinikael-?=_5-14763587882000.8241290969717285 75 | Content-Type: image/png; name=image.png 76 | Content-ID: 77 | Content-Disposition: attachment; filename=image.png 78 | Content-Transfer-Encoding: base64 79 | 80 | iVBORw0KGgoAAAANSUhEUgAAABAAAAAQAQMAAAAlPW0iAAAABlBMVEUAAAD///+l2Z/dAAAAM0lE 81 | QVR4nGP4/5/h/1+G/58ZDrAz3D/McH8yw83NDDeNGe4Ug9C9zwz3gVLMDA/A6P9/AFGGFyjOXZtQ 82 | AAAAAElFTkSuQmCC 83 | ------sinikael-?=_5-14763587882000.8241290969717285 84 | Content-Type: image/gif; name="nyan cat =?UTF-8?Q?=E2=9C=94=2Egif?=" 85 | Content-ID: 86 | Content-Disposition: attachment; 87 | filename*0*=utf-8''nyan%20cat%20%E2%9C%94.gif 88 | Content-Transfer-Encoding: base64 89 | 90 | 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 570 | 1Yyw8Iy+SAjcCE3euFPgyFXroI2Pd3XgdI5pl45nNWCwaFPuqE3w2DnXmAl0RRnRqHtC6F8C+GAx 571 | I45Sp1ZOU1zrF1+7NHNQZJCzhpD1CFqdyAAMqUsOiQn7GDf9+FMKWZGclC/692rARjLyOEEdqVQf 572 | KYtWKJBatWJJE3UZlZJpIl34UH0iOXswCQwbSTY0uSU2SX1j9QU9SJAxCZFp0n7QVRlBaXWr/6gu 573 | GXkJPakkSjlc49ha8LNpINlbO9mLm1CVt9VZMhkLTfl+8JeLIteVXsmP52dJgCWWSKkJZYlokgSM 574 | WKeWazl339d7YWkjJykKcxlk9yhzeJmX7eZziNcEW0eMn4WVveZrW5lcRmmYAtGWyccEi0mPthCY 575 | lil2aCl0k0mZfNeZWgkFU4kJQblbT3mXoSmahUeaiQkArJULZllsdilGremaBwSbJDYFs7kGxFd8 576 | n9lthSmarFeX3kBcFImYdjec0RKV7HacjeWbyumY0kl+zslKxUmZ13l91MkRqUldq4mbJKk6ujkJ 577 | 3YmddVOdtEmXfBmZipebrpme05cp+zWYcf/ikghYnjr1jYzZV3v5Xe3FXtlZAheZAtAJImO5WLyJ 578 | GfrlXuOJYTkJPNvZNwsqQgE6IQ9KoLcpodcFZL9mnv6pmSDGcxyKKvcZoaugn/jHn1DFjP/ZXRl6 579 | HRuaX/ipYB+aZZCGb+gYoww6o8tRo4NTjtiVoxQqn/oYl2wJpM8FXifKkkhwoCiQoAdyoZnFpIf3 580 | RUTKT4KpomDook93nruJpVm6QFvKf7XJdFQaYfRZprBzoyrglCG3pszVpm7qoHCKoGmap05VoXlp 581 | p3eqJ3x6AnLaoVsIplonpoAaqKTipQDonq1nqF8aov2pm4vKqG0njSsKqd6ZKtVYkNvgHMH/ialo 582 | VKBDxanqiSqfepShCma1SaoiZqqFqqrrhmM+amSoCqsjJqt7amO1SmS3OmWXqqt4wqu5mm2e+qvf 583 | oKTfMKrECkaSSoDH+mQ8qhXBaiev+qylGq3016vDo6zYwKzY4KwIkWnMqT11dqxnmYyP2qXfWq1u 584 | ca0zQa4HYa4bpzz2aqKAtmzeR6a3hqimdVqj5q90lq7DGhX52nGZyq/zdK4CCrDahVkD67CIkbAJ 585 | d2AWm3ErJ5TWRbE06qeiRj3ZChIZq3JoVLI6t7FEoK4bywSrOqIlQa8GgbIqgbEG26DTya5shrM+ 586 | RqkvqlgTe6+KQbMURrQLe5MNK7QP67Nh/wq0IsuyJHuzBAs4Rquy/eqxQQqyEBW0+uom2vamuJZs 587 | +4q0kJSVvcm0iQqX8tp1I4t+3SCek/e2R8ux8GG24Adq4EoJpwkiMpuqXwC3m9dsf8ewZfuYtrmj 588 | JemXVjpsbSuc5AC4TGq4kAmQdSu5aoakGvmXbAu1bvu31xa5Yju4ZFu5oXu3HpK3k7C3B9K36yq3 589 | /xq4X5uYzBa7roa2AYuN62hArIusrntsqFa6stsI8VGapwuvmbu4RzdCB6etYPFxpqpKluuWmCuV 590 | mmsyN9dCzNu8MAellXJviUt410tC2fsVzsut0XcoL4tZ4btB4xsV5QufMuK9IsqI63tB7f+7FO/L 591 | vYkiv5UKvsr7bverFPmrs/YWQahbp//LbwHsEwOsqf5nwMabb/XbQNPXcgrbsik7EQ1MuawJsfQV 592 | MqqLngl8cZc7tY7btcSLwi8HdOYbcFp7HyE8pj7ycRU8txastCy0vQRMdtNbIzE8wQlUwxt7wyqs 593 | I+b2vEJBp1FWvSY3wihXwlhba1F8uFi7wcLXwbYbsRnzw06Mc1CMw7Y1xfVZsxRhxcrHlT2soExs 594 | c12MvV9cxKarsWMrxxJhxoQLlS9cHjEMCm06hBhMt6hEiPOrCXvsqiYcm5D3xzeTj4S8xhjTxz+o 595 | yIhFjQdcyLlzyGf7e5IceB4MimdHokb/xLNhbHybbFmUHMGWYMnHI8qTe3uljEmn/L0PubbWy8pS 596 | TMpzfMeB3MmniLutOm22TMWunMujS5iMB1KfnLswuwy7S6xnmi15Byia2My6+szYEs1zMs2Nu8DW 597 | fC3YfCbazLkLzLv6i3dlt0WTSM2w2s3W8s24EM4HW6bs7MLHrHfpvM0BPM98ErdfYIh1KIbfVDT8 598 | 7AX+7HgAHdCLDLuUV9AJddBSKi8D3QUM3dAOPaGTDLqiMdF7WNFGetFTXM8aHYgc7YXyp9DdENIo 599 | XU9I7NFg7LcEndIw/TArjcWYPMojfdMVpM/jsrs43dOjotPiwtM+PdQZCtQ83J1EndRw/+zSDsxL 600 | Qq3UUE3GntnC8PLUUZ3Ul1nMb4XPyHnVPZ3VgLzVudp8LDvTRyrGb8zBUSjKRt10ZknWYNnU5hDX 601 | cj2pNc3Uau3Ub7192WrWrnTXkbrDp1pbbe1Be4196ge/rIbW0huZ2ueob3fYzJPY5bwLdJ3Xh8rW 602 | g2rOY83XZU3VRXDZV7zWgE3Ogi3QB9gB/dcq/xenqd2Qr+1grU0msz2lsZ1LtY0Bqx0quU0vSijW 603 | hgK9vb0hwy3cT1iUwd0nBfjAv92ixz2Sz42mk6Kdzd2u0T2Qyc2ltw1B1e3a3Y3b263by83a4e3b 604 | 2f2F6J3e6r3e7N3e7v3e8B3f8j3f9CZd3/Z93/id3/q93/zd3/793wAe4AI+4ARe4AZ+4Aie4Aq+ 605 | 4NqUAAA7 606 | ------sinikael-?=_5-14763587882000.8241290969717285-- 607 | 608 | ------sinikael-?=_2-14763587882000.8241290969717285-- 609 | 610 | ------sinikael-?=_1-14763587882000.8241290969717285 611 | Content-Type: text/plain; name=notes.txt 612 | Content-Disposition: attachment; filename=notes.txt 613 | Content-Transfer-Encoding: 7bit 614 | 615 | Some notes about this e-mail 616 | ------sinikael-?=_1-14763587882000.8241290969717285-- 617 | -------------------------------------------------------------------------------- /examples/pipe.js: -------------------------------------------------------------------------------- 1 | /* eslint no-console:0 */ 2 | 3 | 'use strict'; 4 | 5 | const util = require('util'); 6 | const fs = require('fs'); 7 | const MailParser = require('../lib/mail-parser.js'); 8 | 9 | let parser = new MailParser(); 10 | let input = fs.createReadStream(__dirname + '/nodemailer.eml'); 11 | 12 | let attachments = []; 13 | 14 | input.pipe(parser); 15 | 16 | parser.on('headers', headers => { 17 | console.log(util.inspect(headers, false, 22)); 18 | }); 19 | 20 | parser.on('data', data => { 21 | if (data.type === 'text') { 22 | Object.keys(data).forEach(key => { 23 | console.log(key); 24 | console.log('----'); 25 | console.log(data[key]); 26 | }); 27 | } 28 | 29 | if (data.type === 'attachment') { 30 | attachments.push(data); 31 | data.chunks = []; 32 | data.chunklen = 0; 33 | let size = 0; 34 | Object.keys(data).forEach(key => { 35 | if (typeof data[key] !== 'object' && typeof data[key] !== 'function') { 36 | console.log('%s: %s', key, JSON.stringify(data[key])); 37 | } 38 | }); 39 | data.content.on('readable', () => { 40 | let chunk; 41 | while ((chunk = data.content.read()) !== null) { 42 | size += chunk.length; 43 | data.chunks.push(chunk); 44 | data.chunklen += chunk.length; 45 | } 46 | }); 47 | 48 | data.content.on('end', () => { 49 | data.buf = Buffer.concat(data.chunks, data.chunklen); 50 | console.log('%s: %s B', 'size', size); 51 | // attachment needs to be released before next chunk of 52 | // message data can be processed 53 | data.release(); 54 | }); 55 | } 56 | }); 57 | 58 | parser.on('end', () => { 59 | console.log('READY'); 60 | 61 | parser.updateImageLinks( 62 | (attachment, done) => done(false, 'data:' + attachment.contentType + ';base64,' + attachment.buf.toString('base64')), 63 | (err, html) => { 64 | if (err) { 65 | console.log(err); 66 | } 67 | if (html) { 68 | console.log(html); 69 | } 70 | } 71 | ); 72 | }); 73 | -------------------------------------------------------------------------------- /examples/simple-async.js: -------------------------------------------------------------------------------- 1 | /* eslint no-console:0 */ 2 | 3 | 'use strict'; 4 | 5 | const util = require('util'); 6 | const fs = require('fs'); 7 | const simpleParser = require('../lib/simple-parser.js'); 8 | 9 | async function main() { 10 | let mail = await simpleParser(fs.createReadStream(__dirname + '/simple.eml')); 11 | console.log(util.inspect(mail, false, 22)); 12 | } 13 | 14 | main().catch(err => { 15 | console.log(err); 16 | }); 17 | -------------------------------------------------------------------------------- /examples/simple-options.js: -------------------------------------------------------------------------------- 1 | /* eslint no-console:0 */ 2 | 3 | 'use strict'; 4 | 5 | const util = require('util'); 6 | const fs = require('fs'); 7 | const simpleParser = require('../lib/simple-parser.js'); 8 | 9 | async function main() { 10 | let mail = await simpleParser(fs.createReadStream(__dirname + '/nodemailer.eml'), { 11 | skipImageLinks: true, // do not convert CID attachments to data URL images 12 | skipHtmlToText: false, // generate plaintext from HTML if needed 13 | skipTextToHtml: false, // generate HTML from plaintext if needed 14 | skipTextLinks: true, // do not linkify links in plaintext content 15 | formatDateString: date => date.toUTCString() // format date in RFC822 embedded HTML head section 16 | }); 17 | 18 | console.log(util.inspect(mail, false, 22)); 19 | } 20 | 21 | main().catch(err => { 22 | console.log(err); 23 | }); 24 | -------------------------------------------------------------------------------- /examples/simple.eml: -------------------------------------------------------------------------------- 1 | From: andris@kreata.ee 2 | To: andris.reinman@gmail.com 3 | Subject: test 4 | Date: Sun, 8 Jan 2017 20:37:44 +0200 5 | 6 | Hello world! 7 | -------------------------------------------------------------------------------- /examples/simple.js: -------------------------------------------------------------------------------- 1 | /* eslint no-console:0 */ 2 | 3 | 'use strict'; 4 | 5 | const util = require('util'); 6 | const fs = require('fs'); 7 | const simpleParser = require('../lib/simple-parser.js'); 8 | 9 | let input = fs.createReadStream(process.argv[2] || __dirname + '/simple.eml'); 10 | 11 | simpleParser(input, { 12 | skipHtmlToText: true, 13 | skipImageLinks: true, 14 | skipTextToHtml: true, 15 | skipTextLinks: true, 16 | keepDeliveryStatus: true, 17 | keepCidLinks: true 18 | //ignoreEmbedded: true 19 | }) 20 | .then(mail => { 21 | console.log(util.inspect(mail, false, 22)); 22 | }) 23 | .catch(err => { 24 | console.log(err); 25 | }); 26 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const MailParser = require('./lib/mail-parser'); 4 | const simpleParser = require('./lib/simple-parser'); 5 | 6 | module.exports = { 7 | MailParser, 8 | simpleParser 9 | }; 10 | -------------------------------------------------------------------------------- /lib/mail-parser.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const mailsplit = require('mailsplit'); 4 | const libmime = require('libmime'); 5 | const addressparser = require('nodemailer/lib/addressparser'); 6 | const Transform = require('stream').Transform; 7 | const Splitter = mailsplit.Splitter; 8 | const punycode = require('punycode.js'); 9 | const FlowedDecoder = require('mailsplit/lib/flowed-decoder'); 10 | const StreamHash = require('./stream-hash'); 11 | const iconv = require('iconv-lite'); 12 | const { htmlToText } = require('html-to-text'); 13 | const he = require('he'); 14 | const linkify = require('linkify-it')(); 15 | const tlds = require('tlds'); 16 | const encodingJapanese = require('encoding-japanese'); 17 | 18 | linkify 19 | .tlds(tlds) // Reload with full tlds list 20 | .tlds('onion', true) // Add unofficial `.onion` domain 21 | .add('git:', 'http:') // Add `git:` ptotocol as "alias" 22 | .add('ftp:', null) // Disable `ftp:` ptotocol 23 | .set({ fuzzyIP: true, fuzzyLink: true, fuzzyEmail: true }); 24 | 25 | // twitter linkifier from 26 | // https://github.com/markdown-it/linkify-it#example-2-add-twitter-mentions-handler 27 | linkify.add('@', { 28 | validate(text, pos, self) { 29 | let tail = text.slice(pos); 30 | 31 | if (!self.re.twitter) { 32 | self.re.twitter = new RegExp('^([a-zA-Z0-9_]){1,15}(?!_)(?=$|' + self.re.src_ZPCc + ')'); 33 | } 34 | if (self.re.twitter.test(tail)) { 35 | // Linkifier allows punctuation chars before prefix, 36 | // but we additionally disable `@` ("@@mention" is invalid) 37 | if (pos >= 2 && tail[pos - 2] === '@') { 38 | return false; 39 | } 40 | return tail.match(self.re.twitter)[0].length; 41 | } 42 | return 0; 43 | }, 44 | normalize(match) { 45 | match.url = 'https://twitter.com/' + match.url.replace(/^@/, ''); 46 | } 47 | }); 48 | 49 | class IconvDecoder extends Transform { 50 | constructor(Iconv, charset) { 51 | super(); 52 | 53 | // Iconv throws error on ks_c_5601-1987 when it is mapped to EUC-KR 54 | // https://github.com/bnoordhuis/node-iconv/issues/169 55 | if (charset.toLowerCase() === 'ks_c_5601-1987') { 56 | charset = 'CP949'; 57 | } 58 | this.stream = new Iconv(charset, 'UTF-8//TRANSLIT//IGNORE'); 59 | 60 | this.inputEnded = false; 61 | this.endCb = false; 62 | 63 | this.stream.on('error', err => this.emit('error', err)); 64 | this.stream.on('data', chunk => this.push(chunk)); 65 | this.stream.on('end', () => { 66 | this.inputEnded = true; 67 | if (typeof this.endCb === 'function') { 68 | this.endCb(); 69 | } 70 | }); 71 | } 72 | 73 | _transform(chunk, encoding, done) { 74 | this.stream.write(chunk); 75 | done(); 76 | } 77 | 78 | _flush(done) { 79 | this.endCb = done; 80 | this.stream.end(); 81 | } 82 | } 83 | 84 | class JPDecoder extends Transform { 85 | constructor(charset) { 86 | super(); 87 | 88 | this.charset = charset; 89 | this.chunks = []; 90 | this.chunklen = 0; 91 | } 92 | 93 | _transform(chunk, encoding, done) { 94 | if (typeof chunk === 'string') { 95 | chunk = Buffer.from(chunk, encoding); 96 | } 97 | 98 | this.chunks.push(chunk); 99 | this.chunklen += chunk.length; 100 | done(); 101 | } 102 | 103 | _flush(done) { 104 | let input = Buffer.concat(this.chunks, this.chunklen); 105 | try { 106 | let output = encodingJapanese.convert(input, { 107 | to: 'UNICODE', // to_encoding 108 | from: this.charset, // from_encoding 109 | type: 'string' 110 | }); 111 | if (typeof output === 'string') { 112 | output = Buffer.from(output); 113 | } 114 | this.push(output); 115 | } catch (err) { 116 | // keep as is on errors 117 | this.push(input); 118 | } 119 | 120 | done(); 121 | } 122 | } 123 | 124 | class MailParser extends Transform { 125 | constructor(config) { 126 | super({ 127 | readableObjectMode: true, 128 | writableObjectMode: false 129 | }); 130 | 131 | this.options = config || {}; 132 | this.splitter = new Splitter(config); 133 | this.finished = false; 134 | this.waitingEnd = false; 135 | 136 | this.headers = false; 137 | this.headerLines = false; 138 | 139 | this.endReceived = false; 140 | this.reading = false; 141 | this.hasFailed = false; 142 | 143 | this.tree = false; 144 | this.curnode = false; 145 | this.waitUntilAttachmentEnd = false; 146 | this.attachmentCallback = false; 147 | 148 | this.hasHtml = false; 149 | this.hasText = false; 150 | 151 | this.text = false; 152 | this.html = false; 153 | this.textAsHtml = false; 154 | 155 | this.attachmentList = []; 156 | 157 | this.boundaries = []; 158 | 159 | this.textTypes = ['text/plain', 'text/html'].concat(!this.options.keepDeliveryStatus ? 'message/delivery-status' : []); 160 | 161 | this.decoder = this.getDecoder(); 162 | 163 | this.splitter.on('readable', () => { 164 | if (this.reading) { 165 | return false; 166 | } 167 | this.readData(); 168 | }); 169 | 170 | this.splitter.on('end', () => { 171 | this.endReceived = true; 172 | if (!this.reading) { 173 | this.endStream(); 174 | } 175 | }); 176 | 177 | this.splitter.on('error', err => { 178 | this.hasFailed = true; 179 | if (typeof this.waitingEnd === 'function') { 180 | return this.waitingEnd(err); 181 | } 182 | this.emit('error', err); 183 | }); 184 | 185 | this.libmime = new libmime.Libmime({ Iconv: this.options.Iconv }); 186 | } 187 | 188 | getDecoder() { 189 | if (this.options.Iconv) { 190 | const Iconv = this.options.Iconv; 191 | // create wrapper 192 | return { 193 | decodeStream(charset) { 194 | return new IconvDecoder(Iconv, charset); 195 | } 196 | }; 197 | } else { 198 | return { 199 | decodeStream(charset) { 200 | charset = (charset || 'ascii').toString().trim().toLowerCase(); 201 | if (/^jis|^iso-?2022-?jp|^EUCJP/i.test(charset)) { 202 | // special case not supported by iconv-lite 203 | return new JPDecoder(charset); 204 | } 205 | 206 | return iconv.decodeStream(charset); 207 | } 208 | }; 209 | } 210 | } 211 | 212 | readData() { 213 | if (this.hasFailed) { 214 | return false; 215 | } 216 | this.reading = true; 217 | let data = this.splitter.read(); 218 | if (data === null) { 219 | this.reading = false; 220 | if (this.endReceived) { 221 | this.endStream(); 222 | } 223 | return; 224 | } 225 | 226 | this.processChunk(data, err => { 227 | if (err) { 228 | if (typeof this.waitingEnd === 'function') { 229 | return this.waitingEnd(err); 230 | } 231 | return this.emit('error', err); 232 | } 233 | setImmediate(() => this.readData()); 234 | }); 235 | } 236 | 237 | endStream() { 238 | this.finished = true; 239 | 240 | if (this.curnode && this.curnode.decoder) { 241 | this.curnode.decoder.end(); 242 | } 243 | if (typeof this.waitingEnd === 'function') { 244 | this.waitingEnd(); 245 | } 246 | } 247 | 248 | _transform(chunk, encoding, done) { 249 | if (!chunk || !chunk.length) { 250 | return done(); 251 | } 252 | 253 | if (this.splitter.write(chunk) === false) { 254 | return this.splitter.once('drain', () => { 255 | done(); 256 | }); 257 | } else { 258 | return done(); 259 | } 260 | } 261 | 262 | _flush(done) { 263 | setImmediate(() => this.splitter.end()); 264 | if (this.finished) { 265 | return this.cleanup(done); 266 | } 267 | this.waitingEnd = () => { 268 | this.cleanup(() => { 269 | done(); 270 | }); 271 | }; 272 | } 273 | 274 | cleanup(done) { 275 | let finish = () => { 276 | try { 277 | let t = this.getTextContent(); 278 | this.push(t); 279 | } catch (err) { 280 | return this.emit('error', err); 281 | } 282 | 283 | done(); 284 | }; 285 | 286 | if (this.curnode && this.curnode.decoder && this.curnode.decoder.readable && !this.decoderEnded) { 287 | (this.curnode.contentStream || this.curnode.decoder).once('end', () => { 288 | finish(); 289 | }); 290 | this.curnode.decoder.end(); 291 | } else { 292 | setImmediate(() => { 293 | finish(); 294 | }); 295 | } 296 | } 297 | 298 | processHeaders(lines) { 299 | let headers = new Map(); 300 | (lines || []).forEach(line => { 301 | let key = line.key; 302 | let value = ((this.libmime.decodeHeader(line.line) || {}).value || '').toString().trim(); 303 | value = Buffer.from(value, 'binary').toString(); 304 | switch (key) { 305 | case 'content-type': 306 | case 'content-disposition': 307 | case 'dkim-signature': 308 | value = this.libmime.parseHeaderValue(value); 309 | if (value.value) { 310 | value.value = this.libmime.decodeWords(value.value); 311 | } 312 | Object.keys((value && value.params) || {}).forEach(key => { 313 | try { 314 | value.params[key] = this.libmime.decodeWords(value.params[key]); 315 | } catch (E) { 316 | // ignore, keep as is 317 | } 318 | }); 319 | break; 320 | case 'date': { 321 | let dateValue = new Date(value); 322 | if (isNaN(dateValue)) { 323 | // date parsing failed :S 324 | dateValue = new Date(); 325 | } 326 | value = dateValue; 327 | break; 328 | } 329 | case 'subject': 330 | try { 331 | value = this.libmime.decodeWords(value); 332 | } catch (E) { 333 | // ignore, keep as is 334 | } 335 | break; 336 | case 'references': 337 | try { 338 | value = this.libmime.decodeWords(value); 339 | } catch (E) { 340 | // ignore 341 | } 342 | value = value.split(/\s+/).map(this.ensureMessageIDFormat); 343 | break; 344 | case 'message-id': 345 | case 'in-reply-to': 346 | try { 347 | value = this.libmime.decodeWords(value); 348 | } catch (E) { 349 | // ignore 350 | } 351 | value = this.ensureMessageIDFormat(value); 352 | break; 353 | case 'priority': 354 | case 'x-priority': 355 | case 'x-msmail-priority': 356 | case 'importance': 357 | key = 'priority'; 358 | value = this.parsePriority(value); 359 | break; 360 | case 'from': 361 | case 'to': 362 | case 'cc': 363 | case 'bcc': 364 | case 'sender': 365 | case 'reply-to': 366 | case 'delivered-to': 367 | case 'return-path': 368 | case 'disposition-notification-to': 369 | value = addressparser(value); 370 | this.decodeAddresses(value); 371 | value = { 372 | value, 373 | html: this.getAddressesHTML(value), 374 | text: this.getAddressesText(value) 375 | }; 376 | break; 377 | } 378 | 379 | // handle list-* keys 380 | if (key.substr(0, 5) === 'list-') { 381 | value = this.parseListHeader(key.substr(5), value); 382 | key = 'list'; 383 | } 384 | 385 | if (value) { 386 | if (!headers.has(key)) { 387 | headers.set(key, [].concat(value || [])); 388 | } else if (Array.isArray(value)) { 389 | headers.set(key, headers.get(key).concat(value)); 390 | } else { 391 | headers.get(key).push(value); 392 | } 393 | } 394 | }); 395 | 396 | // keep only the first value 397 | let singleKeys = [ 398 | 'message-id', 399 | 'content-id', 400 | 'from', 401 | 'sender', 402 | 'in-reply-to', 403 | 'reply-to', 404 | 'subject', 405 | 'date', 406 | 'content-disposition', 407 | 'content-type', 408 | 'content-transfer-encoding', 409 | 'priority', 410 | 'mime-version', 411 | 'content-description', 412 | 'precedence', 413 | 'errors-to', 414 | 'disposition-notification-to' 415 | ]; 416 | 417 | headers.forEach((value, key) => { 418 | if (Array.isArray(value)) { 419 | if (singleKeys.includes(key) && value.length) { 420 | headers.set(key, value[value.length - 1]); 421 | } else if (value.length === 1) { 422 | headers.set(key, value[0]); 423 | } 424 | } 425 | 426 | if (key === 'list') { 427 | // normalize List-* headers 428 | let listValue = {}; 429 | [].concat(value || []).forEach(val => { 430 | Object.keys(val || {}).forEach(listKey => { 431 | listValue[listKey] = val[listKey]; 432 | }); 433 | }); 434 | headers.set(key, listValue); 435 | } 436 | }); 437 | 438 | return headers; 439 | } 440 | 441 | parseListHeader(key, value) { 442 | let addresses = addressparser(value); 443 | let response = {}; 444 | let data = addresses 445 | .map(address => { 446 | if (/^https?:/i.test(address.name)) { 447 | response.url = address.name; 448 | } else if (address.name) { 449 | response.name = address.name; 450 | } 451 | if (/^mailto:/.test(address.address)) { 452 | response.mail = address.address.substr(7); 453 | } else if (address.address && address.address.indexOf('@') < 0) { 454 | response.id = address.address; 455 | } else if (address.address) { 456 | response.mail = address.address; 457 | } 458 | if (Object.keys(response).length) { 459 | return response; 460 | } 461 | return false; 462 | }) 463 | .filter(address => address); 464 | if (data.length) { 465 | return { 466 | [key]: response 467 | }; 468 | } 469 | return false; 470 | } 471 | 472 | parsePriority(value) { 473 | value = value.toLowerCase().trim(); 474 | if (!isNaN(parseInt(value, 10))) { 475 | // support "X-Priority: 1 (Highest)" 476 | value = parseInt(value, 10) || 0; 477 | if (value === 3) { 478 | return 'normal'; 479 | } else if (value > 3) { 480 | return 'low'; 481 | } else { 482 | return 'high'; 483 | } 484 | } else { 485 | switch (value) { 486 | case 'non-urgent': 487 | case 'low': 488 | return 'low'; 489 | case 'urgent': 490 | case 'high': 491 | return 'high'; 492 | } 493 | } 494 | return 'normal'; 495 | } 496 | 497 | ensureMessageIDFormat(value) { 498 | if (!value.length) { 499 | return false; 500 | } 501 | 502 | if (value.charAt(0) !== '<') { 503 | value = '<' + value; 504 | } 505 | 506 | if (value.charAt(value.length - 1) !== '>') { 507 | value += '>'; 508 | } 509 | 510 | return value; 511 | } 512 | 513 | decodeAddresses(addresses) { 514 | let processedAddress = new WeakSet(); 515 | for (let i = 0; i < addresses.length; i++) { 516 | let address = addresses[i]; 517 | address.name = (address.name || '').toString().trim(); 518 | 519 | if (!address.address && /^(=\?([^?]+)\?[Bb]\?[^?]*\?=)(\s*=\?([^?]+)\?[Bb]\?[^?]*\?=)*$/.test(address.name) && !processedAddress.has(address)) { 520 | let parsed = addressparser(this.libmime.decodeWords(address.name)); 521 | if (parsed.length) { 522 | parsed.forEach(entry => { 523 | processedAddress.add(entry); 524 | addresses.push(entry); 525 | }); 526 | } 527 | 528 | // remove current element 529 | addresses.splice(i, 1); 530 | i--; 531 | continue; 532 | } 533 | 534 | if (address.name) { 535 | try { 536 | address.name = this.libmime.decodeWords(address.name); 537 | } catch (E) { 538 | //ignore, keep as is 539 | } 540 | } 541 | if (/@xn--/.test(address.address)) { 542 | try { 543 | address.address = 544 | address.address.substr(0, address.address.lastIndexOf('@') + 1) + 545 | punycode.toUnicode(address.address.substr(address.address.lastIndexOf('@') + 1)); 546 | } catch (E) { 547 | // Not a valid punycode string; keep as is 548 | } 549 | } 550 | if (address.group) { 551 | this.decodeAddresses(address.group); 552 | } 553 | } 554 | } 555 | 556 | createNode(node) { 557 | let contentType = node.contentType; 558 | let disposition = node.disposition; 559 | let encoding = node.encoding; 560 | let charset = node.charset; 561 | 562 | if (!contentType && node.root) { 563 | contentType = 'text/plain'; 564 | } 565 | 566 | let newNode = { 567 | node, 568 | headerLines: node.headers.lines, 569 | headers: this.processHeaders(node.headers.getList()), 570 | contentType, 571 | children: [] 572 | }; 573 | 574 | if (!/^multipart\//i.test(contentType)) { 575 | if (disposition && !['attachment', 'inline'].includes(disposition)) { 576 | disposition = 'attachment'; 577 | } 578 | 579 | if (!disposition && !this.textTypes.includes(contentType)) { 580 | newNode.disposition = 'attachment'; 581 | } else { 582 | newNode.disposition = disposition || 'inline'; 583 | } 584 | 585 | newNode.isAttachment = !this.textTypes.includes(contentType) || newNode.disposition !== 'inline'; 586 | 587 | newNode.encoding = ['quoted-printable', 'base64'].includes(encoding) ? encoding : 'binary'; 588 | 589 | if (charset) { 590 | newNode.charset = charset; 591 | } 592 | 593 | let decoder = node.getDecoder(); 594 | decoder.on('end', () => { 595 | this.decoderEnded = true; 596 | }); 597 | newNode.decoder = decoder; 598 | } 599 | 600 | if (node.root) { 601 | this.headers = newNode.headers; 602 | this.headerLines = newNode.headerLines; 603 | } 604 | 605 | // find location in tree 606 | 607 | if (!this.tree) { 608 | newNode.root = true; 609 | this.curnode = this.tree = newNode; 610 | return newNode; 611 | } 612 | 613 | // immediate child of root node 614 | if (!this.curnode.parent) { 615 | newNode.parent = this.curnode; 616 | this.curnode.children.push(newNode); 617 | this.curnode = newNode; 618 | return newNode; 619 | } 620 | 621 | // siblings 622 | if (this.curnode.parent.node === node.parentNode) { 623 | newNode.parent = this.curnode.parent; 624 | this.curnode.parent.children.push(newNode); 625 | this.curnode = newNode; 626 | return newNode; 627 | } 628 | 629 | // first child 630 | if (this.curnode.node === node.parentNode) { 631 | newNode.parent = this.curnode; 632 | this.curnode.children.push(newNode); 633 | this.curnode = newNode; 634 | return newNode; 635 | } 636 | 637 | // move up 638 | let parentNode = this.curnode; 639 | while ((parentNode = parentNode.parent)) { 640 | if (parentNode.node === node.parentNode) { 641 | newNode.parent = parentNode; 642 | parentNode.children.push(newNode); 643 | this.curnode = newNode; 644 | return newNode; 645 | } 646 | } 647 | 648 | // should never happen, can't detect parent 649 | this.curnode = newNode; 650 | return newNode; 651 | } 652 | 653 | getTextContent() { 654 | let text = []; 655 | let html = []; 656 | let processNode = (alternative, level, node) => { 657 | if (node.showMeta) { 658 | let meta = ['From', 'Subject', 'Date', 'To', 'Cc', 'Bcc'] 659 | .map(fkey => { 660 | let key = fkey.toLowerCase(); 661 | if (!node.headers.has(key)) { 662 | return false; 663 | } 664 | let value = node.headers.get(key); 665 | if (!value) { 666 | return false; 667 | } 668 | return { 669 | key: fkey, 670 | value: Array.isArray(value) ? value[value.length - 1] : value 671 | }; 672 | }) 673 | .filter(entry => entry); 674 | if (this.hasHtml) { 675 | html.push( 676 | '' + 677 | meta 678 | .map(entry => { 679 | let value = entry.value; 680 | switch (entry.key) { 681 | case 'From': 682 | case 'To': 683 | case 'Cc': 684 | case 'Bcc': 685 | value = value.html; 686 | break; 687 | case 'Date': 688 | value = this.options.formatDateString ? this.options.formatDateString(value) : value.toUTCString(); 689 | break; 690 | case 'Subject': 691 | value = '' + he.encode(value) + ''; 692 | break; 693 | default: 694 | value = he.encode(value); 695 | } 696 | 697 | return ''; 698 | }) 699 | .join('\n') + 700 | '
' + he.encode(entry.key) + ':' + value + '
' 701 | ); 702 | } 703 | if (this.hasText) { 704 | text.push( 705 | '\n' + 706 | meta 707 | .map(entry => { 708 | let value = entry.value; 709 | switch (entry.key) { 710 | case 'From': 711 | case 'To': 712 | case 'Cc': 713 | case 'Bcc': 714 | value = value.text; 715 | break; 716 | case 'Date': 717 | value = this.options.formatDateString ? this.options.formatDateString(value) : value.toUTCString(); 718 | break; 719 | } 720 | return entry.key + ': ' + value; 721 | }) 722 | .join('\n') + 723 | '\n' 724 | ); 725 | } 726 | } 727 | if (node.textContent) { 728 | if (node.contentType === 'text/plain') { 729 | text.push(node.textContent); 730 | if (!alternative && this.hasHtml) { 731 | html.push(this.textToHtml(node.textContent)); 732 | } 733 | } else if (node.contentType === 'message/delivery-status' && !this.options.keepDeliveryStatus) { 734 | text.push(node.textContent); 735 | if (!alternative && this.hasHtml) { 736 | html.push(this.textToHtml(node.textContent)); 737 | } 738 | } else if (node.contentType === 'text/html') { 739 | let failedToParseHtml = false; 740 | if ((!alternative && this.hasText) || (node.root && !this.hasText)) { 741 | if (this.options.skipHtmlToText) { 742 | text.push(''); 743 | } else if (node.textContent.length > this.options.maxHtmlLengthToParse) { 744 | this.emit('error', new Error(`HTML too long for parsing ${node.textContent.length} bytes`)); 745 | text.push('Invalid HTML content (too long)'); 746 | failedToParseHtml = true; 747 | } else { 748 | try { 749 | text.push(htmlToText(node.textContent)); 750 | } catch (err) { 751 | this.emit('error', new Error('Failed to parse HTML')); 752 | text.push('Invalid HTML content'); 753 | failedToParseHtml = true; 754 | } 755 | } 756 | } 757 | if (!failedToParseHtml) { 758 | html.push(node.textContent); 759 | } 760 | } 761 | } 762 | alternative = alternative || node.contentType === 'multipart/alternative'; 763 | if (node.children) { 764 | node.children.forEach(subNode => { 765 | processNode(alternative, level + 1, subNode); 766 | }); 767 | } 768 | }; 769 | 770 | processNode(false, 0, this.tree); 771 | 772 | let response = { 773 | type: 'text' 774 | }; 775 | if (html.length) { 776 | this.html = response.html = html.join('
\n'); 777 | } 778 | if (text.length) { 779 | this.text = response.text = text.join('\n'); 780 | this.textAsHtml = response.textAsHtml = text.map(part => this.textToHtml(part)).join('
\n'); 781 | } 782 | return response; 783 | } 784 | 785 | processChunk(data, done) { 786 | let partId = null; 787 | if (data._parentBoundary) { 788 | partId = this._getPartId(data._parentBoundary); 789 | } 790 | switch (data.type) { 791 | case 'node': { 792 | let node = this.createNode(data); 793 | if (node === this.tree) { 794 | ['subject', 'references', 'date', 'to', 'from', 'to', 'cc', 'bcc', 'message-id', 'in-reply-to', 'reply-to'].forEach(key => { 795 | if (node.headers.has(key)) { 796 | this[key.replace(/-([a-z])/g, (m, c) => c.toUpperCase())] = node.headers.get(key); 797 | } 798 | }); 799 | this.emit('headers', node.headers); 800 | 801 | if (node.headerLines) { 802 | this.emit('headerLines', node.headerLines); 803 | } 804 | } 805 | 806 | if (data.contentType === 'message/rfc822' && data.messageNode) { 807 | break; 808 | } 809 | 810 | if (data.parentNode && data.parentNode.contentType === 'message/rfc822') { 811 | node.showMeta = true; 812 | } 813 | 814 | if (node.isAttachment) { 815 | let contentType = node.contentType; 816 | if (node.contentType === 'application/octet-stream' && data.filename) { 817 | contentType = this.libmime.detectMimeType(data.filename) || 'application/octet-stream'; 818 | } 819 | 820 | let attachment = { 821 | type: 'attachment', 822 | content: null, 823 | contentType, 824 | partId, 825 | release: () => { 826 | attachment.release = null; 827 | if (this.waitUntilAttachmentEnd && typeof this.attachmentCallback === 'function') { 828 | setImmediate(this.attachmentCallback); 829 | } 830 | this.attachmentCallback = false; 831 | this.waitUntilAttachmentEnd = false; 832 | } 833 | }; 834 | 835 | let algo = this.options.checksumAlgo || 'md5'; 836 | let hasher = new StreamHash(attachment, algo); 837 | node.decoder.on('error', err => { 838 | hasher.emit('error', err); 839 | }); 840 | 841 | node.decoder.on('readable', () => { 842 | let chunk; 843 | 844 | while ((chunk = node.decoder.read()) !== null) { 845 | hasher.write(chunk); 846 | } 847 | }); 848 | 849 | node.decoder.once('end', () => { 850 | hasher.end(); 851 | }); 852 | 853 | //node.decoder.pipe(hasher); 854 | attachment.content = hasher; 855 | 856 | this.waitUntilAttachmentEnd = true; 857 | if (data.disposition) { 858 | attachment.contentDisposition = data.disposition; 859 | } 860 | 861 | if (data.filename) { 862 | attachment.filename = data.filename; 863 | } 864 | 865 | if (node.headers.has('content-id')) { 866 | attachment.contentId = [].concat(node.headers.get('content-id') || []).shift(); 867 | attachment.cid = attachment.contentId.trim().replace(/^<|>$/g, '').trim(); 868 | // check if the attachment is "related" to text content like an embedded image etc 869 | let parentNode = node; 870 | while ((parentNode = parentNode.parent)) { 871 | if (parentNode.contentType === 'multipart/related') { 872 | attachment.related = true; 873 | } 874 | } 875 | } 876 | 877 | attachment.headers = node.headers; 878 | this.push(attachment); 879 | this.attachmentList.push(attachment); 880 | } else if (node.disposition === 'inline') { 881 | let chunks = []; 882 | let chunklen = 0; 883 | node.contentStream = node.decoder; 884 | 885 | if (node.contentType === 'text/plain') { 886 | this.hasText = true; 887 | } else if (node.contentType === 'text/html') { 888 | this.hasHtml = true; 889 | } else if (node.contentType === 'message/delivery-status' && !this.options.keepDeliveryStatus) { 890 | this.hasText = true; 891 | } 892 | 893 | if (node.node.flowed) { 894 | let contentStream = node.contentStream; 895 | let flowDecoder = new FlowedDecoder({ 896 | delSp: node.node.delSp 897 | }); 898 | contentStream.on('error', err => { 899 | flowDecoder.emit('error', err); 900 | }); 901 | contentStream.pipe(flowDecoder); 902 | node.contentStream = flowDecoder; 903 | } 904 | 905 | let charset = node.charset || 'utf-8'; 906 | //charset = charset || 'windows-1257'; 907 | 908 | if (!['ascii', 'usascii', 'utf8'].includes(charset.toLowerCase().replace(/[^a-z0-9]+/g, ''))) { 909 | try { 910 | let contentStream = node.contentStream; 911 | let decodeStream = this.decoder.decodeStream(charset); 912 | contentStream.on('error', err => { 913 | decodeStream.emit('error', err); 914 | }); 915 | contentStream.pipe(decodeStream); 916 | node.contentStream = decodeStream; 917 | } catch (E) { 918 | // do not decode charset 919 | } 920 | } 921 | 922 | node.contentStream.on('readable', () => { 923 | let chunk; 924 | while ((chunk = node.contentStream.read()) !== null) { 925 | if (typeof chunk === 'string') { 926 | chunk = Buffer.from(chunk); 927 | } 928 | chunks.push(chunk); 929 | chunklen += chunk.length; 930 | } 931 | }); 932 | 933 | node.contentStream.once('end', () => { 934 | node.textContent = Buffer.concat(chunks, chunklen).toString().replace(/\r?\n/g, '\n'); 935 | }); 936 | 937 | node.contentStream.once('error', err => { 938 | this.emit('error', err); 939 | }); 940 | } 941 | 942 | break; 943 | } 944 | 945 | case 'data': 946 | if (this.curnode && this.curnode.decoder) { 947 | this.curnode.decoder.end(); 948 | } 949 | 950 | if (this.waitUntilAttachmentEnd) { 951 | this.attachmentCallback = done; 952 | return; 953 | } 954 | 955 | // multipart message structure 956 | // this is not related to any specific 'node' block as it includes 957 | // everything between the end of some node body and between the next header 958 | //process.stdout.write(data.value); 959 | break; 960 | 961 | case 'body': 962 | if (this.curnode && this.curnode.decoder && this.curnode.decoder.writable) { 963 | if (this.curnode.decoder.write(data.value) === false) { 964 | return this.curnode.decoder.once('drain', done); 965 | } 966 | } 967 | 968 | // Leaf element body. Includes the body for the last 'node' block. You might 969 | // have several 'body' calls for a single 'node' block 970 | //process.stdout.write(data.value); 971 | break; 972 | } 973 | 974 | setImmediate(done); 975 | } 976 | 977 | _getPartId(parentBoundary) { 978 | let boundaryIndex = this.boundaries.findIndex(item => item.name === parentBoundary); 979 | if (boundaryIndex === -1) { 980 | this.boundaries.push({ name: parentBoundary, count: 1 }); 981 | boundaryIndex = this.boundaries.length - 1; 982 | } else { 983 | this.boundaries[boundaryIndex].count++; 984 | } 985 | let partId = '1'; 986 | for (let i = 0; i <= boundaryIndex; i++) { 987 | if (i === 0) partId = this.boundaries[i].count.toString(); 988 | else partId += '.' + this.boundaries[i].count.toString(); 989 | } 990 | return partId; 991 | } 992 | 993 | getAddressesHTML(value) { 994 | let formatSingleLevel = addresses => 995 | addresses 996 | .map(address => { 997 | let str = ''; 998 | if (address.name) { 999 | str += '' + he.encode(address.name) + (address.group ? ': ' : '') + ''; 1000 | } 1001 | if (address.address) { 1002 | let link = '' + he.encode(address.address) + ''; 1003 | if (address.name) { 1004 | str += ' <' + link + '>'; 1005 | } else { 1006 | str += link; 1007 | } 1008 | } 1009 | if (address.group) { 1010 | str += formatSingleLevel(address.group) + ';'; 1011 | } 1012 | return str + ''; 1013 | }) 1014 | .join(', '); 1015 | return formatSingleLevel([].concat(value || [])); 1016 | } 1017 | 1018 | getAddressesText(value) { 1019 | let formatSingleLevel = addresses => 1020 | addresses 1021 | .map(address => { 1022 | let str = ''; 1023 | if (address.name) { 1024 | str += `"${address.name}"` + (address.group ? ': ' : ''); 1025 | } 1026 | if (address.address) { 1027 | let link = address.address; 1028 | if (address.name) { 1029 | str += ' <' + link + '>'; 1030 | } else { 1031 | str += link; 1032 | } 1033 | } 1034 | if (address.group) { 1035 | str += formatSingleLevel(address.group) + ';'; 1036 | } 1037 | return str; 1038 | }) 1039 | .join(', '); 1040 | return formatSingleLevel([].concat(value || [])); 1041 | } 1042 | 1043 | updateImageLinks(replaceCallback, done) { 1044 | if (!this.html) { 1045 | return setImmediate(() => done(null, false)); 1046 | } 1047 | 1048 | let cids = new Map(); 1049 | let html = (this.html || '').toString(); 1050 | 1051 | if (this.options.skipImageLinks) { 1052 | return done(null, html); 1053 | } 1054 | 1055 | html.replace(/\bcid:([^'"\s]{1,256})/g, (match, cid) => { 1056 | for (let i = 0, len = this.attachmentList.length; i < len; i++) { 1057 | if (this.attachmentList[i].cid === cid && /^image\/[\w]+$/i.test(this.attachmentList[i].contentType)) { 1058 | cids.set(cid, { 1059 | attachment: this.attachmentList[i] 1060 | }); 1061 | break; 1062 | } 1063 | } 1064 | return match; 1065 | }); 1066 | 1067 | let cidList = []; 1068 | cids.forEach(entry => { 1069 | cidList.push(entry); 1070 | }); 1071 | 1072 | let pos = 0; 1073 | let processNext = () => { 1074 | if (pos >= cidList.length) { 1075 | html = html.replace(/\bcid:([^'"\s]{1,256})/g, (match, cid) => { 1076 | if (cids.has(cid) && cids.get(cid).url) { 1077 | return cids.get(cid).url; 1078 | } 1079 | return match; 1080 | }); 1081 | 1082 | return done(null, html); 1083 | } 1084 | let entry = cidList[pos++]; 1085 | replaceCallback(entry.attachment, (err, url) => { 1086 | if (err) { 1087 | return setImmediate(() => done(err)); 1088 | } 1089 | entry.url = url; 1090 | setImmediate(processNext); 1091 | }); 1092 | }; 1093 | 1094 | setImmediate(processNext); 1095 | } 1096 | 1097 | textToHtml(str) { 1098 | if (this.options.skipTextToHtml) { 1099 | return ''; 1100 | } 1101 | str = (str || '').toString(); 1102 | let encoded; 1103 | 1104 | let linkified = false; 1105 | if (!this.options.skipTextLinks) { 1106 | try { 1107 | if (linkify.pretest(str)) { 1108 | linkified = true; 1109 | let links = linkify.match(str) || []; 1110 | let result = []; 1111 | let last = 0; 1112 | 1113 | links.forEach(link => { 1114 | if (last < link.index) { 1115 | let textPart = he 1116 | // encode special chars 1117 | .encode(str.slice(last, link.index), { 1118 | useNamedReferences: true 1119 | }); 1120 | result.push(textPart); 1121 | } 1122 | 1123 | result.push(`${link.text}`); 1124 | 1125 | last = link.lastIndex; 1126 | }); 1127 | 1128 | let textPart = he 1129 | // encode special chars 1130 | .encode(str.slice(last), { 1131 | useNamedReferences: true 1132 | }); 1133 | result.push(textPart); 1134 | 1135 | encoded = result.join(''); 1136 | } 1137 | } catch (E) { 1138 | // failed, don't linkify 1139 | } 1140 | } 1141 | 1142 | if (!linkified) { 1143 | encoded = he 1144 | // encode special chars 1145 | .encode(str, { 1146 | useNamedReferences: true 1147 | }); 1148 | } 1149 | 1150 | let text = 1151 | '

' + 1152 | encoded 1153 | .replace(/\r?\n/g, '\n') 1154 | .trim() // normalize line endings 1155 | .replace(/[ \t]+$/gm, '') 1156 | .trim() // trim empty line endings 1157 | .replace(/\n\n+/g, '

') 1158 | .trim() // insert

to multiple linebreaks 1159 | .replace(/\n/g, '
') + // insert
to single linebreaks 1160 | '

'; 1161 | 1162 | return text; 1163 | } 1164 | } 1165 | 1166 | module.exports = MailParser; 1167 | -------------------------------------------------------------------------------- /lib/simple-parser.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const MailParser = require('./mail-parser.js'); 4 | 5 | module.exports = (input, options, callback) => { 6 | if (input === null || input === undefined) { 7 | throw new TypeError('Input cannot be null or undefined.'); 8 | } 9 | 10 | if (!callback && typeof options === 'function') { 11 | callback = options; 12 | options = false; 13 | } 14 | 15 | let promise; 16 | if (!callback) { 17 | promise = new Promise((resolve, reject) => { 18 | callback = callbackPromise(resolve, reject); 19 | }); 20 | } 21 | 22 | options = options || {}; 23 | let keepCidLinks = !!options.keepCidLinks; 24 | 25 | let mail = { 26 | attachments: [] 27 | }; 28 | 29 | let parser = new MailParser(options); 30 | 31 | parser.on('error', err => { 32 | callback(err); 33 | }); 34 | 35 | parser.on('headers', headers => { 36 | mail.headers = headers; 37 | mail.headerLines = parser.headerLines; 38 | }); 39 | 40 | let reading = false; 41 | let reader = () => { 42 | reading = true; 43 | 44 | let data = parser.read(); 45 | 46 | if (data === null) { 47 | reading = false; 48 | return; 49 | } 50 | 51 | if (data.type === 'text') { 52 | Object.keys(data).forEach(key => { 53 | if (['text', 'html', 'textAsHtml'].includes(key)) { 54 | mail[key] = data[key]; 55 | } 56 | }); 57 | } 58 | 59 | if (data.type === 'attachment') { 60 | mail.attachments.push(data); 61 | 62 | let chunks = []; 63 | let chunklen = 0; 64 | data.content.on('readable', () => { 65 | let chunk; 66 | while ((chunk = data.content.read()) !== null) { 67 | chunks.push(chunk); 68 | chunklen += chunk.length; 69 | } 70 | }); 71 | 72 | data.content.on('end', () => { 73 | data.content = Buffer.concat(chunks, chunklen); 74 | data.release(); 75 | reader(); 76 | }); 77 | } else { 78 | reader(); 79 | } 80 | }; 81 | 82 | parser.on('readable', () => { 83 | if (!reading) { 84 | reader(); 85 | } 86 | }); 87 | 88 | parser.on('end', () => { 89 | ['subject', 'references', 'date', 'to', 'from', 'to', 'cc', 'bcc', 'message-id', 'in-reply-to', 'reply-to'].forEach(key => { 90 | if (mail.headers && mail.headers.has(key)) { 91 | mail[key.replace(/-([a-z])/g, (m, c) => c.toUpperCase())] = mail.headers.get(key); 92 | } 93 | }); 94 | 95 | if (keepCidLinks) { 96 | return callback(null, mail); 97 | } 98 | parser.updateImageLinks( 99 | (attachment, done) => done(false, 'data:' + attachment.contentType + ';base64,' + attachment.content.toString('base64')), 100 | (err, html) => { 101 | if (err) { 102 | return callback(err); 103 | } 104 | mail.html = html; 105 | 106 | callback(null, mail); 107 | } 108 | ); 109 | }); 110 | 111 | if (typeof input === 'string') { 112 | parser.end(Buffer.from(input)); 113 | } else if (Buffer.isBuffer(input)) { 114 | parser.end(input); 115 | } else { 116 | input 117 | .once('error', err => { 118 | input.destroy(); 119 | parser.destroy(); 120 | callback(err); 121 | }) 122 | .pipe(parser); 123 | } 124 | 125 | return promise; 126 | }; 127 | 128 | function callbackPromise(resolve, reject) { 129 | return function (...args) { 130 | let err = args.shift(); 131 | if (err) { 132 | reject(err); 133 | } else { 134 | resolve(...args); 135 | } 136 | }; 137 | } 138 | -------------------------------------------------------------------------------- /lib/stream-hash.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const crypto = require('crypto'); 4 | const Transform = require('stream').Transform; 5 | 6 | class StreamHash extends Transform { 7 | constructor(attachment, algo) { 8 | super(); 9 | this.attachment = attachment; 10 | this.algo = (algo || 'md5').toLowerCase(); 11 | this.hash = crypto.createHash(algo); 12 | this.byteCount = 0; 13 | } 14 | 15 | _transform(chunk, encoding, done) { 16 | this.hash.update(chunk); 17 | this.byteCount += chunk.length; 18 | done(null, chunk); 19 | } 20 | 21 | _flush(done) { 22 | this.attachment.checksum = this.hash.digest('hex'); 23 | this.attachment.size = this.byteCount; 24 | done(); 25 | } 26 | } 27 | 28 | module.exports = StreamHash; 29 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "mailparser", 3 | "version": "3.7.3", 4 | "description": "Parse e-mails", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "grunt", 8 | "update": "rm -rf node_modules package-lock.json && ncu -u && npm install" 9 | }, 10 | "author": "Andris Reinman", 11 | "contributors": [ 12 | { 13 | "name": "Peter Salomonsen", 14 | "email": "petersalomonsen@runbox.com", 15 | "url": "https://github.com/petersalomonsen" 16 | } 17 | ], 18 | "license": "MIT", 19 | "dependencies": { 20 | "encoding-japanese": "2.2.0", 21 | "he": "1.2.0", 22 | "html-to-text": "9.0.5", 23 | "iconv-lite": "0.6.3", 24 | "libmime": "5.3.6", 25 | "linkify-it": "5.0.0", 26 | "mailsplit": "5.4.3", 27 | "nodemailer": "7.0.3", 28 | "punycode.js": "2.3.1", 29 | "tlds": "1.259.0" 30 | }, 31 | "devDependencies": { 32 | "ajv": "8.17.1", 33 | "eslint": "8.57.0", 34 | "eslint-config-nodemailer": "1.2.0", 35 | "eslint-config-prettier": "9.1.0", 36 | "grunt": "1.6.1", 37 | "grunt-cli": "1.5.0", 38 | "grunt-contrib-nodeunit": "5.0.0", 39 | "grunt-eslint": "24.3.0", 40 | "iconv": "3.0.1", 41 | "random-message": "1.1.0" 42 | }, 43 | "repository": { 44 | "type": "git", 45 | "url": "https://github.com/nodemailer/mailparser.git" 46 | }, 47 | "bugs": { 48 | "url": "https://github.com/nodemailer/mailparser/issues" 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /test/cpanel-test.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const MailParser = require('..').MailParser; 4 | 5 | exports['Simple with part as rfc822 with bad closing boundary 01'] = test => { 6 | let encodedText = `Delivered-To: xxxx@gmail.com 7 | Date: Wed, 03 Jun 2020 22:50:46 GMT 8 | From: "cPanel on vps17201.sdfsfsd.com" 9 | Message-Id: 10 | Subject: [vps17201.sfsfsdfds.com] cPanel & WHM update failure in upcp script 11 | To: 12 | Mime-Version: 1.0 13 | Content-Type: multipart/mixed; boundary="mixed-Cpanel::Email::Object-28634-1591224646-0.368578683442088" 14 | 15 | --mixed-Cpanel::Email::Object-28634-1591224646-0.368578683442088 16 | Content-Type: multipart/alternative; boundary="alternative-Cpanel::Email::Object-28634-1591224646-0.846610436809971" 17 | 18 | --alternative-Cpanel::Email::Object-28634-1591224646-0.846610436809971 19 | Content-Type: text/plain; charset=utf-8 20 | Content-Transfer-Encoding: quoted-printable 21 | 22 | Test 23 | 24 | --alternative-Cpanel::Email::Object-28634-1591224646-0.846610436809971 25 | Content-Type: multipart/related; boundary="related-Cpanel::Email::Object-28634-1591224646-0.29282857359793" 26 | 27 | --related-Cpanel::Email::Object-28634-1591224646-0.29282857359793 28 | Content-Type: text/html; charset=utf-8 29 | Content-Transfer-Encoding: quoted-printable 30 | 31 | 32 | 33 | --related-Cpanel::Email::Object-28634-1591224646-0.29282857359793 34 | 35 | --related-Cpanel::Email::Object-28634-1591224646-0.29282857359793-- 36 | 37 | --alternative-Cpanel::Email::Object-28634-1591224646-0.846610436809971-- 38 | 39 | --mixed-Cpanel::Email::Object-28634-1591224646-0.368578683442088 40 | Content-Type: text/plain; charset="utf-8"; x-unix-mode=0600; name="update_log.txt" 41 | Content-Disposition: attachment; filename="update_log.txt" 42 | Content-Transfer-Encoding: base64 43 | 44 | Z2xvcA== 45 | --mixed-Cpanel::Email::Object-28634-1591224646-0.368578683442088 46 | `; 47 | let mail = Buffer.from(encodedText, 'utf-8'); 48 | 49 | let mailparser = new MailParser(); 50 | 51 | mailparser.on('data', c => { 52 | if (c && typeof c.release === 'function') { 53 | // stream attachment content to /dev/null 54 | c.content.on('data', () => false); 55 | c.content.on('end', () => c.release()); 56 | } 57 | }); 58 | 59 | mailparser.on('end', () => { 60 | test.equal(mailparser.text, 'Test\n'); 61 | test.done(); 62 | }); 63 | 64 | mailparser.end(mail); 65 | }; 66 | 67 | exports['Simple with part as rfc822 with bad closing boundary 02'] = test => { 68 | let encodedText = `Delivered-To: xxxx@gmail.com 69 | Date: Wed, 03 Jun 2020 22:50:46 GMT 70 | From: "cPanel on vps17201.sdfsfsd.com" 71 | Message-Id: 72 | Subject: [vps17201.sfsfsdfds.com] cPanel & WHM update failure in upcp script 73 | To: 74 | Mime-Version: 1.0 75 | Content-Type: multipart/mixed; boundary="mixed-Cpanel::Email::Object-28634-1591224646-0.368578683442088" 76 | 77 | --mixed-Cpanel::Email::Object-28634-1591224646-0.368578683442088 78 | Content-Type: multipart/alternative; boundary="alternative-Cpanel::Email::Object-28634-1591224646-0.846610436809971" 79 | 80 | --alternative-Cpanel::Email::Object-28634-1591224646-0.846610436809971 81 | Content-Type: text/plain; charset=utf-8 82 | Content-Transfer-Encoding: quoted-printable 83 | 84 | Test 85 | 86 | --alternative-Cpanel::Email::Object-28634-1591224646-0.846610436809971 87 | Content-Type: multipart/related; boundary="related-Cpanel::Email::Object-28634-1591224646-0.29282857359793" 88 | 89 | --related-Cpanel::Email::Object-28634-1591224646-0.29282857359793 90 | Content-Type: text/html; charset=utf-8 91 | Content-Transfer-Encoding: quoted-printable 92 | 93 | 94 | 95 | --related-Cpanel::Email::Object-28634-1591224646-0.29282857359793 96 | 97 | --related-Cpanel::Email::Object-28634-1591224646-0.29282857359793-- 98 | 99 | --alternative-Cpanel::Email::Object-28634-1591224646-0.846610436809971-- 100 | 101 | --mixed-Cpanel::Email::Object-28634-1591224646-0.368578683442088 102 | Content-Type: text/plain; charset="utf-8"; x-unix-mode=0600; name="update_log.txt" 103 | Content-Disposition: attachment; filename="update_log.txt" 104 | Content-Transfer-Encoding: base64 105 | 106 | Z2xvcA== 107 | --mixed-Cpanel::Email::Object-28634-1591224646-0.368578683442088`, 108 | mail = Buffer.from(encodedText, 'utf-8'); 109 | 110 | let mailparser = new MailParser(); 111 | mailparser.end(mail); 112 | mailparser.on('data', c => { 113 | if (c && typeof c.release === 'function') { 114 | // stream attachment content to /dev/null 115 | c.content.on('data', () => false); 116 | c.content.on('end', () => c.release()); 117 | } 118 | }); 119 | mailparser.on('end', () => { 120 | test.equal(mailparser.text, 'Test\n'); 121 | test.done(); 122 | }); 123 | }; 124 | -------------------------------------------------------------------------------- /test/delivery-status-test.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const fs = require('fs'); 4 | const simpleParser = require('..').simpleParser; 5 | 6 | module.exports['Parses message/delivery-status'] = async test => { 7 | let encodedText = fs.readFileSync(__dirname + '/fixtures/delivery-status.eml'); 8 | let mail = Buffer.from(encodedText, 'utf-8'); 9 | let parsed = await simpleParser(mail); 10 | test.ok(parsed.text.indexOf('Status: 5.1.1') >= 0); 11 | test.done(); 12 | }; 13 | -------------------------------------------------------------------------------- /test/fixtures/base64encodedroot.eml: -------------------------------------------------------------------------------- 1 | From: test@example.com 2 | Content-Type: image/png; 3 | name="screenshot.png" 4 | Content-Transfer-Encoding: base64 5 | Content-Disposition: attachment; 6 | filename="screenshot.png" 7 | 8 | iVBORw0KGgoAAAANSUhEUgAAABcAAAAfCAYAAAAMeVbNAAAABHNCSVQICAgIfAhkiAAAABl0 9 | RVh0U29mdHdhcmUAZ25vbWUtc2NyZWVuc2hvdO8Dvz4AAAE7SURBVEiJY/T3dfvPQCPARCuD 10 | Rw0fNXwoGM5rmckwoa+dId2ABau8kGUuw4S+doZkHezyeA2nBqCp4bj9RC7gkGOw8nFjsNdR 11 | prLhHMoMofkpDNZC3xkeXDlOyHBWBnGrYIZQlT8YMpxSghhi8u7BDNbinxlOzexjWHbzB2GX 12 | C6mYMlir4JL9jcSWYzDSFWNgeHec4dQzVgZeXlZChv9muL6olmHmBUyXC1nmMtSFSiEEOIQY 13 | xHgZGBhYLRlyGi0ZGBioGaEw+1+eZli24QLDJ+oa/o7h3WcGBgZOBoZPd28y3PhD1XT+jOH8 14 | jXcMDHwGDB52UgwsDFQ1/A/DnS1rGU69Y2VQ8MllqMtLoHIO/XGTYVlPH8OyY3cZPgspMzAO 15 | 2dofa2qZ0NdDskEFRSUYYjR1+dAN81HDsQIA4N1NJ84wfR8AAAAASUVORK5CYII= 16 | 17 | -------------------------------------------------------------------------------- /test/fixtures/decoderended.eml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nodemailer/mailparser/20c3300e6861a87c8945b9d4cdaffba021953445/test/fixtures/decoderended.eml -------------------------------------------------------------------------------- /test/fixtures/delivery-status.eml: -------------------------------------------------------------------------------- 1 | Delivered-To: xxxxx@gmail.com 2 | Date: Tue, 16 Feb 2021 00:57:06 +0000 3 | From: MAILER-DAEMON@amazonses.com 4 | To: xxxxx@gmail.com 5 | Message-ID: 6 | Subject: Delivery Status Notification (Failure) 7 | MIME-Version: 1.0 8 | Content-Type: multipart/report; 9 | boundary="----=_Part_3532716_1471051372.1613437026471"; 10 | report-type=delivery-status 11 | X-SES-Outgoing: 2021.02.16-0.0.0.0 12 | Feedback-ID: 1.us-east-1.D1mWDvwUtiZJdKFArGKkGBe9wfRCdAX2ofq5lyeEo20=:AmazonSES 13 | 14 | ------=_Part_3532716_1471051372.1613437026471 15 | Content-Type: text/plain; charset=us-ascii 16 | Content-Transfer-Encoding: 7bit 17 | Content-Description: Notification 18 | 19 | An error occurred while trying to deliver the mail to the following recipients: 20 | xxxx@xxxx.com 21 | ------=_Part_3532716_1471051372.1613437026471 22 | Content-Type: message/delivery-status 23 | Content-Transfer-Encoding: 7bit 24 | Content-Description: Delivery Status Notification 25 | 26 | Reporting-MTA: dns; amazonses.com 27 | 28 | Action: failed 29 | Remote-MTA: dns; amazonses.com 30 | Final-Recipient: rfc822; xxxx@xxxx.com 31 | Diagnostic-Code: Amazon SES did not send the message to this address because it is on the suppression list for your account. For more information about removing addresses from the suppression list, see the Amazon SES Developer Guide at https://docs.aws.amazon.com/ses/latest/DeveloperGuide/sending-email-suppression-list.html 32 | Status: 5.1.1 33 | 34 | 35 | ------=_Part_3532716_1471051372.1613437026471 36 | Content-Type: message/rfc822 37 | Content-Description: Undelivered Message 38 | 39 | Received: from xxxx.xxxx (ec2-34-198-5-89.compute-1.amazonaws.com [x.x.x.x]) 40 | by email-smtp.amazonaws.com 41 | with SMTP (SimpleEmailService-d-11MVXUWA9) id aRHDoBiW1yM0CRxRhdPS; 42 | Tue, 16 Feb 2021 00:57:06 +0000 (UTC) 43 | Date: Mon, 15 Feb 2021 17:57:06 -0700 44 | To: not@found.com 45 | From: xx xx 46 | Reply-To: xx xx 47 | Subject: Example Subject 48 | Message-ID: 49 | In-Reply-To: 50 | MIME-Version: 1.0 51 | Content-Type: multipart/alternative; 52 | boundary="b1_UEK9lmOmk2jPQRWgM3Xiqjs7mPRVso71mRP17DZ3qGM" 53 | Content-Transfer-Encoding: 8bit 54 | 55 | This is a multi-part message in MIME format. 56 | --b1_UEK9lmOmk2jPQRWgM3Xiqjs7mPRVso71mRP17DZ3qGM 57 | Content-Type: text/plain; charset=UTF-8 58 | Content-Transfer-Encoding: 8bit 59 | 60 | Hi, 61 | 62 | Message 63 | 64 | --b1_UEK9lmOmk2jPQRWgM3Xiqjs7mPRVso71mRP17DZ3qGM 65 | Content-Type: text/html; charset=UTF-8 66 | Content-Transfer-Encoding: quoted-printable 67 | 68 |
Hi, 69 |
 
70 |
test email
71 |
72 | 73 | --b1_UEK9lmOmk2jPQRWgM3Xiqjs7mPRVso71mRP17DZ3qGM-- 74 | 75 | 76 | ------=_Part_3532716_1471051372.1613437026471-- 77 | -------------------------------------------------------------------------------- /test/fixtures/mixed.eml: -------------------------------------------------------------------------------- 1 | Content-Type: multipart/mixed; 2 | boundary="--=b73b47c7-75f9-4775-93eb-475a43310901" 3 | 4 | 5 | ----=b73b47c7-75f9-4775-93eb-475a43310901 6 | Content-Type: multipart/alternative; 7 | boundary="--=4d3d5f03-fd7a-40f2-ab55-6bd2de649863" 8 | 9 | ----=4d3d5f03-fd7a-40f2-ab55-6bd2de649863 10 | Content-Type: text/plain 11 | Content-Transfer-Encoding: 7bit 12 | 13 | 14 | This e-mail message has been scanned for Viruses and Content and cleared 15 | 16 | ----=4d3d5f03-fd7a-40f2-ab55-6bd2de649863 17 | Content-Type: text/html 18 | Content-Transfer-Encoding: quoted-printable 19 | 20 | 21 | =20 22 | 23 |
24 | This e-mail message has been scanned for Viruses and Content and cleared 25 |
26 | 27 | 28 | ----=4d3d5f03-fd7a-40f2-ab55-6bd2de649863-- 29 | 30 | ----=b73b47c7-75f9-4775-93eb-475a43310901 31 | Content-Type: text/plain; charset="UTF-8" 32 | Content-Transfer-Encoding: quoted-printable 33 | 34 | Good Morning; 35 | 36 | 37 | ----=b73b47c7-75f9-4775-93eb-475a43310901-- 38 | -------------------------------------------------------------------------------- /test/fixtures/nested.eml: -------------------------------------------------------------------------------- 1 | From: u@example.com 2 | Content-Type: multipart/mixed; 3 | boundary="----=_NextPart_000_0D48_01CE140D.19527DD0" 4 | 5 | 6 | ------=_NextPart_000_0D48_01CE140D.19527DD0 7 | Content-Type: multipart/related; 8 | boundary="----=_NextPart_001_0D49_01CE140D.19527DD0" 9 | 10 | 11 | ------=_NextPart_001_0D49_01CE140D.19527DD0 12 | Content-Type: multipart/alternative; 13 | boundary="----=_NextPart_002_0D4A_01CE140D.19527DD0" 14 | 15 | 16 | ------=_NextPart_002_0D4A_01CE140D.19527DD0 17 | Content-Transfer-Encoding: quoted-printable 18 | Content-Type: text/plain; 19 | charset="utf-8" 20 | 21 | 22 | Dear Sir, 23 | 24 | Good evening. 25 | 26 | 27 | 28 | 29 | 30 | ------=_NextPart_002_0D4A_01CE140D.19527DD0 31 | Content-Transfer-Encoding: quoted-printable 32 | Content-Type: text/html; 33 | charset="utf-8" 34 | 35 |

Dear Sir

36 |

Good evening.

37 |

38 | ------=_NextPart_002_0D4A_01CE140D.19527DD0-- 39 | 40 | ------=_NextPart_001_0D49_01CE140D.19527DD0-- 41 | 42 | ------=_NextPart_000_0D48_01CE140D.19527DD0 43 | Content-Type: multipart/alternative; boundary="===============1276485360==" 44 | MIME-Version: 1.0 45 | Content-Disposition: inline 46 | 47 | --===============1276485360== 48 | Content-Type: text/plain; charset="utf-8" 49 | MIME-Version: 1.0 50 | Content-Transfer-Encoding: quoted-printable 51 | 52 | 53 | 54 | The footer 55 | 56 | --===============1276485360== 57 | Content-Type: text/html; charset="utf-8" 58 | MIME-Version: 1.0 59 | Content-Transfer-Encoding: quoted-printable 60 | 61 |

The footer

62 | 63 | --===============1276485360==-- 64 | ------=_NextPart_000_0D48_01CE140D.19527DD0-- 65 | 66 | -------------------------------------------------------------------------------- /test/fixtures/nodemailer.eml: -------------------------------------------------------------------------------- 1 | Delivered-To: andris.reinman@gmail.com 2 | Received: by 10.28.50.2 with SMTP id y2csp233403wmy; 3 | Thu, 13 Oct 2016 04:39:49 -0700 (PDT) 4 | X-Received: by 10.25.37.18 with SMTP id l18mr9511740lfl.88.1476358789184; 5 | Thu, 13 Oct 2016 04:39:49 -0700 (PDT) 6 | Return-Path: 7 | Received: from srs1.zonevs.eu (srs1.zonevs.eu. [217.146.68.191]) 8 | by mx.google.com with ESMTPS id l202si1012799lfg.293.2016.10.13.04.39.49 9 | for 10 | (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); 11 | Thu, 13 Oct 2016 04:39:49 -0700 (PDT) 12 | Received-SPF: pass (google.com: best guess record for domain of srs0=63fc=v7=kreata.ee=andris@srs1.zonevs.eu designates 217.146.68.191 as permitted sender) client-ip=217.146.68.191; 13 | Authentication-Results: mx.google.com; 14 | dkim=pass header.i=@srs1.zonevs.eu; 15 | spf=pass (google.com: best guess record for domain of srs0=63fc=v7=kreata.ee=andris@srs1.zonevs.eu designates 217.146.68.191 as permitted sender) smtp.mailfrom=SRS0=63fc=V7=kreata.ee=andris@srs1.zonevs.eu; 16 | dmarc=fail (p=NONE dis=NONE) header.from=kreata.ee 17 | DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=srs1.zonevs.eu; 18 | q=dns/txt; s=oct2016; bh=xKHKChGY0vTH8NsecmXwA0OqbinKOXeQbaC2UYp2BAM=; 19 | h=from:subject:date:message-id:to:mime-version:content-type; 20 | b=Ve18ogdCAG+7WZYkJPOewe1hKjhN4k9unz7bVHMXd6+1CQDRUkLCArQZJzSKxkM481nzXfjFn 21 | bI8qOuQL8mRk/8fAjYhxLgnr/3SyVIOhCnXxjdQkRzgouZyl42hqD0gIaCxu9uodtQrp2pbKvyl 22 | e+3sG+LhcdJmsPguOfILn14j+irinPSWrospC8PBIDTsUwO8DCyPqSlOADbW0B6TRUHWMf4XUX4 23 | W8TH61H1ZI3Xu3k0bvX7rsGHZjsy8dcshcnfYENLCLep8fsQMaB15EErc3RXycBX7CBd0iU1l50 24 | pYpUFd6bZehCF0ipTOgA7IJ7ZPafaH0YTU8wRntXOwbg== 25 | Received: from host29.guest.zone.eu [217.146.66.6] 26 | by srs1.zonevs.eu (ZoneMTA Forwarder) with ESMTP id 157bdd754f70005750.002 27 | for ; 28 | Thu, 13 Oct 2016 11:39:48 +0000 29 | Content-Type: multipart/mixed; 30 | boundary="----sinikael-?=_1-14763587882000.8241290969717285" 31 | X-Laziness-Level: 1000 32 | From: Andris Kreata 33 | To: Andris Reinman , andris.reinman@gmail.com 34 | Subject: Nodemailer is unicode friendly =?UTF-8?Q?=E2=9C=94?= 35 | (1476358788189) 36 | Message-ID: <012d606e-3550-2d94-b566-6cd996de88e3@kreata.ee> 37 | X-Mailer: nodemailer (2.6.0; +http://nodemailer.com/; 38 | SMTP/2.7.2[client:2.12.0]) 39 | Date: Thu, 13 Oct 2016 11:39:48 +0000 40 | MIME-Version: 1.0 41 | X-Zone-Spam-Resolution: no action 42 | X-Zone-Spam-Status: No, score=0.408099, required=15, tests=[MIME_GOOD=-0.1, 43 | R_MISSING_CHARSET=2.5, DMARC_POLICY_SOFTFAIL=0.1, MIME_UNKNOWN=0.1, 44 | R_DKIM_NA=0, BAYES_HAM=-2.1919] 45 | X-Original-Sender: andris@kreata.ee 46 | X-Zone-Forwarded-For: andris@kreata.ee 47 | X-Zone-Forwarded-To: andris.reinman@gmail.com 48 | 49 | ------sinikael-?=_1-14763587882000.8241290969717285 50 | Content-Type: multipart/alternative; 51 | boundary="----sinikael-?=_2-14763587882000.8241290969717285" 52 | 53 | ------sinikael-?=_2-14763587882000.8241290969717285 54 | Content-Type: text/plain 55 | Content-Transfer-Encoding: 7bit 56 | 57 | Hello to myself! 58 | ------sinikael-?=_2-14763587882000.8241290969717285 59 | Content-Type: text/watch-html 60 | Content-Transfer-Encoding: 7bit 61 | 62 | Hello to myself 63 | ------sinikael-?=_2-14763587882000.8241290969717285 64 | Content-Type: multipart/related; type="text/html"; 65 | boundary="----sinikael-?=_5-14763587882000.8241290969717285" 66 | 67 | ------sinikael-?=_5-14763587882000.8241290969717285 68 | Content-Type: text/html 69 | Content-Transfer-Encoding: quoted-printable 70 | 71 |

Hello to myself

Here's = 72 | a nyan cat for you as an embedded attachment:

74 | ------sinikael-?=_5-14763587882000.8241290969717285 75 | Content-Type: image/png; name=image.png 76 | Content-ID: 77 | Content-Disposition: attachment; filename=image.png 78 | Content-Transfer-Encoding: base64 79 | 80 | iVBORw0KGgoAAAANSUhEUgAAABAAAAAQAQMAAAAlPW0iAAAABlBMVEUAAAD///+l2Z/dAAAAM0lE 81 | QVR4nGP4/5/h/1+G/58ZDrAz3D/McH8yw83NDDeNGe4Ug9C9zwz3gVLMDA/A6P9/AFGGFyjOXZtQ 82 | AAAAAElFTkSuQmCC 83 | ------sinikael-?=_5-14763587882000.8241290969717285 84 | Content-Type: image/gif; name="nyan cat =?UTF-8?Q?=E2=9C=94=2Egif?=" 85 | Content-ID: 86 | Content-Disposition: attachment; 87 | filename*0*=utf-8''nyan%20cat%20%E2%9C%94.gif 88 | Content-Transfer-Encoding: base64 89 | 90 | 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 570 | 1Yyw8Iy+SAjcCE3euFPgyFXroI2Pd3XgdI5pl45nNWCwaFPuqE3w2DnXmAl0RRnRqHtC6F8C+GAx 571 | I45Sp1ZOU1zrF1+7NHNQZJCzhpD1CFqdyAAMqUsOiQn7GDf9+FMKWZGclC/692rARjLyOEEdqVQf 572 | KYtWKJBatWJJE3UZlZJpIl34UH0iOXswCQwbSTY0uSU2SX1j9QU9SJAxCZFp0n7QVRlBaXWr/6gu 573 | GXkJPakkSjlc49ha8LNpINlbO9mLm1CVt9VZMhkLTfl+8JeLIteVXsmP52dJgCWWSKkJZYlokgSM 574 | WKeWazl339d7YWkjJykKcxlk9yhzeJmX7eZziNcEW0eMn4WVveZrW5lcRmmYAtGWyccEi0mPthCY 575 | lil2aCl0k0mZfNeZWgkFU4kJQblbT3mXoSmahUeaiQkArJULZllsdilGremaBwSbJDYFs7kGxFd8 576 | n9lthSmarFeX3kBcFImYdjec0RKV7HacjeWbyumY0kl+zslKxUmZ13l91MkRqUldq4mbJKk6ujkJ 577 | 3YmddVOdtEmXfBmZipebrpme05cp+zWYcf/ikghYnjr1jYzZV3v5Xe3FXtlZAheZAtAJImO5WLyJ 578 | GfrlXuOJYTkJPNvZNwsqQgE6IQ9KoLcpodcFZL9mnv6pmSDGcxyKKvcZoaugn/jHn1DFjP/ZXRl6 579 | HRuaX/ipYB+aZZCGb+gYoww6o8tRo4NTjtiVoxQqn/oYl2wJpM8FXifKkkhwoCiQoAdyoZnFpIf3 580 | RUTKT4KpomDook93nruJpVm6QFvKf7XJdFQaYfRZprBzoyrglCG3pszVpm7qoHCKoGmap05VoXlp 581 | p3eqJ3x6AnLaoVsIplonpoAaqKTipQDonq1nqF8aov2pm4vKqG0njSsKqd6ZKtVYkNvgHMH/ialo 582 | VKBDxanqiSqfepShCma1SaoiZqqFqqrrhmM+amSoCqsjJqt7amO1SmS3OmWXqqt4wqu5mm2e+qvf 583 | oKTfMKrECkaSSoDH+mQ8qhXBaiev+qylGq3016vDo6zYwKzY4KwIkWnMqT11dqxnmYyP2qXfWq1u 584 | ca0zQa4HYa4bpzz2aqKAtmzeR6a3hqimdVqj5q90lq7DGhX52nGZyq/zdK4CCrDahVkD67CIkbAJ 585 | d2AWm3ErJ5TWRbE06qeiRj3ZChIZq3JoVLI6t7FEoK4bywSrOqIlQa8GgbIqgbEG26DTya5shrM+ 586 | RqkvqlgTe6+KQbMURrQLe5MNK7QP67Nh/wq0IsuyJHuzBAs4Rquy/eqxQQqyEBW0+uom2vamuJZs 587 | +4q0kJSVvcm0iQqX8tp1I4t+3SCek/e2R8ux8GG24Adq4EoJpwkiMpuqXwC3m9dsf8ewZfuYtrmj 588 | JemXVjpsbSuc5AC4TGq4kAmQdSu5aoakGvmXbAu1bvu31xa5Yju4ZFu5oXu3HpK3k7C3B9K36yq3 589 | /xq4X5uYzBa7roa2AYuN62hArIusrntsqFa6stsI8VGapwuvmbu4RzdCB6etYPFxpqpKluuWmCuV 590 | mmsyN9dCzNu8MAellXJviUt410tC2fsVzsut0XcoL4tZ4btB4xsV5QufMuK9IsqI63tB7f+7FO/L 591 | vYkiv5UKvsr7bverFPmrs/YWQahbp//LbwHsEwOsqf5nwMabb/XbQNPXcgrbsik7EQ1MuawJsfQV 592 | MqqLngl8cZc7tY7btcSLwi8HdOYbcFp7HyE8pj7ycRU8txastCy0vQRMdtNbIzE8wQlUwxt7wyqs 593 | I+b2vEJBp1FWvSY3wihXwlhba1F8uFi7wcLXwbYbsRnzw06Mc1CMw7Y1xfVZsxRhxcrHlT2soExs 594 | c12MvV9cxKarsWMrxxJhxoQLlS9cHjEMCm06hBhMt6hEiPOrCXvsqiYcm5D3xzeTj4S8xhjTxz+o 595 | yIhFjQdcyLlzyGf7e5IceB4MimdHokb/xLNhbHybbFmUHMGWYMnHI8qTe3uljEmn/L0PubbWy8pS 596 | TMpzfMeB3MmniLutOm22TMWunMujS5iMB1KfnLswuwy7S6xnmi15Byia2My6+szYEs1zMs2Nu8DW 597 | fC3YfCbazLkLzLv6i3dlt0WTSM2w2s3W8s24EM4HW6bs7MLHrHfpvM0BPM98ErdfYIh1KIbfVDT8 598 | 7AX+7HgAHdCLDLuUV9AJddBSKi8D3QUM3dAOPaGTDLqiMdF7WNFGetFTXM8aHYgc7YXyp9DdENIo 599 | XU9I7NFg7LcEndIw/TArjcWYPMojfdMVpM/jsrs43dOjotPiwtM+PdQZCtQ83J1EndRw/+zSDsxL 600 | Qq3UUE3GntnC8PLUUZ3Ul1nMb4XPyHnVPZ3VgLzVudp8LDvTRyrGb8zBUSjKRt10ZknWYNnU5hDX 601 | cj2pNc3Uau3Ub7192WrWrnTXkbrDp1pbbe1Be4196ge/rIbW0huZ2ueob3fYzJPY5bwLdJ3Xh8rW 602 | g2rOY83XZU3VRXDZV7zWgE3Ogi3QB9gB/dcq/xenqd2Qr+1grU0msz2lsZ1LtY0Bqx0quU0vSijW 603 | hgK9vb0hwy3cT1iUwd0nBfjAv92ixz2Sz42mk6Kdzd2u0T2Qyc2ltw1B1e3a3Y3b263by83a4e3b 604 | 2f2F6J3e6r3e7N3e7v3e8B3f8j3f9CZd3/Z93/id3/q93/zd3/793wAe4AI+4ARe4AZ+4Aie4Aq+ 605 | 4NqUAAA7 606 | ------sinikael-?=_5-14763587882000.8241290969717285-- 607 | 608 | ------sinikael-?=_2-14763587882000.8241290969717285-- 609 | 610 | ------sinikael-?=_1-14763587882000.8241290969717285 611 | Content-Type: text/plain; name=notes.txt 612 | Content-Disposition: attachment; filename=notes.txt 613 | Content-Transfer-Encoding: 7bit 614 | 615 | Some notes about this e-mail 616 | ------sinikael-?=_1-14763587882000.8241290969717285-- 617 | -------------------------------------------------------------------------------- /test/fixtures/spam.eml: -------------------------------------------------------------------------------- 1 | X-Account-Key: account3 2 | X-UIDL: 0MLO5q-1a0TUk077q-000a7n 3 | X-Mozilla-Status: 0000 4 | X-Mozilla-Status2: 00000000 5 | X-Mozilla-Keys: 6 | Return-Path: 7 | Received: from rhettbutler.org ([212.170.160.112]) by mx-ha.web.de (mxweb008) 8 | with ESMTP (Nemesis) id 0MLO5q-1a0TUk077q-000a7n for ; Tue, 9 | 24 Nov 2015 01:45:00 +0100 10 | Received: from 200.21.241.94 by 92.63.87.69; Mon, 23 Nov 2015 22:37:26 -0200 11 | Message-ID: 12 | From: "Matilda Klein" 13 | Reply-To: "Matilda Klein" 14 | To: leon.struck@web.de 15 | Subject: 123.042 Euro pro Jahr GRARANTIERT von einer Bank! KOSTENLOS 16 | Date: Tue, 24 Nov 2015 02:35:26 +0200 17 | MIME-Version: 1.0 18 | X-Mailer: Microsoft Outlook, Build 10.0.2627 19 | Content-Type: text/html; 20 | boundary="--Freundliche Grüße" 21 | X-Priority: 3 22 | X-MSMail-Priority: Normal 23 | Envelope-To: 24 | X-UI-Filterresults: unknown:5;V01:K0:/npYJnKKSbM=:utN4/insKH07tTYPrwk+W+2gQg 25 | mQaNAXSsel0eazHK/LkyHHElFyiOorw7/rRGCelDEma+qu0v2sZ5pkfyyJvXKBbE4NTd+yxbU 26 | EFDiiK6ZGPDuOuy82WKa+IMcQ7uVfQTR82fNdWYbMQNKTC85OHlcPIVhzs5+BvSmHzANAR4p2 27 | 0O/V5WT7LB2f9hxr5Pk8OrqsGaLAHm1FdyR668PvzifUR9hvIhscEF/tSz9uYih8F/uygZL5/ 28 | lXpdsszx3JjyGdlr7fkaU/WPlpgvc40OF2bWhk3QNxKX+Pk8buU1TTBArwQfi8oUbvF52nBuq 29 | fpREW1YtRzi1o5fG12J6FrEkFW0vj+OgDwh77z9WdJvAUzJbL7y/x9ywNliyyjVOjtfQ9cUh8 30 | dWlgUQGZkuX7/Xt2+V4cySX9Fhme8P1Dw/OoCAoYaGddQuugiOmNJ9j0y25cOCd7ube/Nu7PE 31 | oNdFOHgY/4A9vcHmS33ensakM9qlgJyi5AyLKZ9gxowfkrN/sB7BcI44acV4TIjD/SB610e3Q 32 | eVyq7kKcfdk1TcfRrUhDhucQ/mwOqaBbtJamKCvCKNqI7dwkSUolX1WaIY97IC7Hheo8zK4t8 33 | xX1Kj6IOExLLJY0zMEsTTw2Xuhi6jFJyYsrQsFbPYm8fzEzO2LQ7DDWi8x/AGTxK8k2vbV7Xg 34 | Pr6XLyK3KpqbZrONqI90MbS6ZGlXDFUzIU3rg61GnYZZS/EXO3jt8R0lmNlorYdWcz8ITH33i 35 | Edtm+jGkK3/DMsvu+Z8Wgb5GPODfIJlZyQQpcseJNcJ7U4uV2usuo54tgV8/3KdnSRadSmtjC 36 | az3QC9LokOBGKGZ0FmCHzYERz7T4lTj5ce2Vj48go+vxOOi7/vDvo10pekQsB/aLZlvqU5GDN 37 | 8tX1OZ3Yeg2dzJ54pRX2tN9FEHyiuSboMuiz+VBDpO3k8bx3aVxfZ5dTjMuSo+MixOvFcGAQR 38 | jxLrVbdxKggeyLilUmh3fvJjBJgTKKHxZq8nL9SFjxZQMGGnklhcDqBhQBFWJBdNEGP7JyVfn 39 | qMiKX7NX/Ufn8r1k7KbKGPxs7qnMyDr4tKd1OkOuqrtycMBU46mSY4qT90X1ujEf+4WYl/X6Z 40 | fCQKUJKANLrRGCZH5RPK5SWYqNvPh/An6G4HcKf+WO4zW8VNgWWQLoR+jB49lRXg3DAG8XGpo 41 | IHomJMoQb9cSD1PWwb+YpuvApZ99ne3/bKP8DtLENeL8XsIUVkXACiXQBXFvJqTrcV4zIBBZx 42 | sJxetksU35kKVhM5KswM8elmvD4BNF5j8HP4MzV5G7cSG85MaFd9GI/0hQuNKhcfxtgEdtuUk 43 | XEmQqSoUN6QX3x7zsrJviULWC+DS+X1sMu87fMUNo2AjnNsGNWAPdOU+rrOQfVFcsKeIM/WdY 44 | zacS2I1ANRLJnyF3PtHURHfuOhfc1QC3M28tzAqONNHPnONac35Okct14PnpXKQSMOkPj745N 45 | 9kRhbBo5UJoRT/+1R10nMuRQPwzP8zQeYvA8a7tA3zBZAf+9i+s2AW2+h1ij6mrUX5cjSbpE5 46 | ai3J1AoAkjWVK2ZGHNMdOZXqGNV1ehYP3NwdK6jrmprRp42iC6kakFhqrrCiKWnYQM2RJxlVb 47 | hN051Y9NSzkBxcQySw6LZoB4swMhiBEJ 48 | 49 | ----Freundliche Grüße 50 | Content-Type: text/html; 51 | Content-Transfer-Encoding: 7Bit 52 | 53 | 54 | 55 | 56 | iqsbyx 57 | 58 | 59 | 60 |

 

61 |

Im Jahre 2007 wurde er als „asozialer Penner“ beschimpft! Er bettelte auf der Straße und lebte unter der Brücke.

62 |

Heute verdient er 35 Millionen Euro pro Jahr, obwohl er nicht mal einen Schulabschluss hat

63 |

Er war hoch verschuldet; doch jetzt hat er ein Vermögen von 100 Millionen Euro!

64 |


Auf dieses Seite zeigt er allen Interessenten, wie er es gemacht hat und wie es JEDER nachmachen kann!

65 |

 

66 |

Er sagte auf dem TV Sender NTV:

67 |

„JEDER kann es nachmachen. Dafür braucht man keinen Schulabschluss oder Erfahrungen in dem Bereich. Im ersten Monat verdienen meine Teilnehmer durchschnittlich 5963,56 Euro mit nur 5 Stunden Einsatz pro Woche“

68 |

 

69 |


Schauen Sie sich hier das Video an und machen Sie es nach!
Es sind nur noch 44 kostenfreie Plätze verfügbar

70 |


>>>VIDEO<<<

71 |

Newsletter abmelden hier klicken

72 |

 

73 | 74 | 75 | 76 | ----Freundliche Grüße-- 77 | 78 | -------------------------------------------------------------------------------- /test/flowed-test.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const simpleParser = require('..').simpleParser; 4 | 5 | module.exports['Quoted printable, DelSp'] = test => { 6 | let encodedText = 'Content-Type: text/plain; format=flowed; delsp=yes\r\nContent-Transfer-Encoding: QUOTED-PRINTABLE\r\n\r\nFoo =\n\nBar =\n\nBaz'; 7 | let mail = Buffer.from(encodedText, 'utf-8'); 8 | 9 | simpleParser(mail, (err, mail) => { 10 | test.ifError(err); 11 | test.ok(mail); 12 | test.equal(mail.text, 'FooBarBaz'); 13 | test.done(); 14 | }); 15 | }; 16 | -------------------------------------------------------------------------------- /test/issue-221-test.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const simpleParser = require('..').simpleParser; 4 | const Iconv = require('iconv').Iconv; 5 | 6 | module.exports['Does it finish?'] = test => { 7 | let source = Buffer.concat([ 8 | Buffer.from( 9 | `From: Mail Delivery Subsystem 10 | To: 11 | MIME-Version: 1.0 12 | Content-Type: multipart/report; report-type=delivery-status; 13 | boundary="w7TItYs4100793.1535568934/foo.invalid.local" 14 | Subject: Returned mail: see transcript for details 15 | Auto-Submitted: auto-generated (failure) 16 | 17 | This is a MIME-encapsulated message 18 | 19 | --w7TItYs4100793.1535568934/foo.invalid.local 20 | Content-Type: message/delivery-status 21 | 22 | Reporting-MTA: dns; foo.invalid.local 23 | Received-From-MTA: DNS; invalid.local 24 | Arrival-Date: Wed, 29 Aug 2018 11:55:34 -0700 25 | 26 | Final-Recipient: RFC822; bar@invalid.local 27 | Action: failed 28 | Status: 5.1.1 29 | 30 | --w7TItYs4100793.1535568934/foo.invalid.local 31 | `.replace(/\n/g, '\r\n') 32 | ) 33 | ]); 34 | 35 | simpleParser(source, { Iconv }, (err, mail) => { 36 | test.ifError(err); 37 | test.ok(mail); 38 | test.ok(mail.headers.get('subject').trim()); 39 | 40 | test.done(); 41 | }); 42 | }; 43 | -------------------------------------------------------------------------------- /test/issue-272-test.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const simpleParser = require('..').simpleParser; 4 | 5 | module.exports['Throws TypeError with input === null'] = async test => { 6 | try { 7 | simpleParser(null); 8 | 9 | throw Error('Error not thrown.'); 10 | } catch (error) { 11 | test.equal(error.constructor.name, 'TypeError'); 12 | } 13 | 14 | test.done(); 15 | }; 16 | 17 | module.exports['Throws TypeError with input === undefined'] = async test => { 18 | try { 19 | simpleParser(undefined); 20 | 21 | throw Error('Error not thrown.'); 22 | } catch (error) { 23 | test.equal(error.constructor.name, 'TypeError'); 24 | } 25 | 26 | test.done(); 27 | }; 28 | 29 | module.exports['Throws TypeError without input'] = async test => { 30 | try { 31 | simpleParser(); 32 | 33 | throw Error('Error not thrown.'); 34 | } catch (error) { 35 | test.equal(error.constructor.name, 'TypeError'); 36 | } 37 | 38 | test.done(); 39 | }; 40 | -------------------------------------------------------------------------------- /test/issue-337-test.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const simpleParser = require('..').simpleParser; 4 | 5 | module.exports['Hangs when Reply-To invalid encoded'] = async test => { 6 | await simpleParser('Content-type: text/plain\r\nReply-To: =?U� -8?B?0=D0=BA=D0=BE=D0=B2?=\n\r\n1234'); 7 | test.done(); 8 | }; 9 | -------------------------------------------------------------------------------- /test/long-references-test.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const MailParser = require('..').MailParser; 4 | 5 | exports['General tests'] = { 6 | 'Simple with part as rfc822 of headers only': test => { 7 | if (Date.now() < 1) { 8 | return test.done(); 9 | } 10 | let encodedText = `Content-Type: text/plain 11 | References: 12 | <831872163.433861.2199124418162.JavaMail.otbatch@blabla.bla.bla.com> 13 | =?utf-8?q?=3CTY1PR0301MB1149CEFEA528CEA0045533B1FBA70=40TY1PR0301MB1149=2Ea?= 14 | =?utf-8?q?pcprd03=2Eprod=2Eoutlook=2Ecom=3E?= 15 | 16 | Hello world`, 17 | mail = Buffer.from(encodedText, 'utf-8'); 18 | 19 | let mailparser = new MailParser(); 20 | mailparser.end(mail); 21 | mailparser.on('data', () => false); 22 | mailparser.on('end', () => { 23 | test.deepEqual(mailparser.headers.get('references'), [ 24 | '<831872163.433861.2199124418162.JavaMail.otbatch@blabla.bla.bla.com>', 25 | '' 26 | ]); 27 | test.done(); 28 | }); 29 | } 30 | }; 31 | -------------------------------------------------------------------------------- /test/rfc822-headers-only-test.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const MailParser = require('..').MailParser; 4 | 5 | exports['General tests'] = { 6 | 'Simple with part as rfc822 of headers only': test => { 7 | if (Date.now() < 1) { 8 | return test.done(); 9 | } 10 | let encodedText = `Content-Type: multipart/mixed; boundary="ABC" 11 | 12 | --ABC 13 | Content-Type: message/rfc822 14 | Content-Disposition: inline 15 | 16 | Content-Type: text/plain; charset=utf-8 17 | Subject: OK 18 | --ABC--`, 19 | mail = Buffer.from(encodedText, 'utf-8'); 20 | 21 | let mailparser = new MailParser(); 22 | mailparser.end(mail); 23 | 24 | mailparser.on('data', data => { 25 | if (data.type === 'attachment') { 26 | data.content.on('data', () => {}); 27 | data.content.on('end', () => data.release()); 28 | } 29 | }); 30 | 31 | mailparser.on('end', () => { 32 | test.equal(mailparser.text, '\nSubject: OK\n'); 33 | test.done(); 34 | }); 35 | } 36 | }; 37 | -------------------------------------------------------------------------------- /test/simple-parser-test.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const simpleParser = require('..').simpleParser; 4 | const fs = require('fs'); 5 | const Iconv = require('iconv').Iconv; 6 | 7 | module.exports['Parse message'] = test => { 8 | simpleParser(fs.createReadStream(__dirname + '/fixtures/nodemailer.eml'), (err, mail) => { 9 | test.ifError(err); 10 | test.ok(mail); 11 | test.equal(mail.attachments.length, 4); 12 | test.equal(mail.attachments[2].checksum, '2822cbcf68de083b96ac3921d0e308a2'); 13 | test.ok(mail.html.indexOf('data:image/png;base64,iVBORw0KGgoAAAANSU') >= 0); 14 | test.equal(mail.subject, 'Nodemailer is unicode friendly ✔ (1476358788189)'); 15 | test.deepEqual(mail.to, { 16 | value: [ 17 | // keep indent 18 | { 19 | address: 'andris+123@kreata.ee', 20 | name: 'Andris Reinman' 21 | }, 22 | { 23 | address: 'andris.reinman@gmail.com', 24 | name: '' 25 | } 26 | ], 27 | html: 'Andris Reinman <andris+123@kreata.ee>, andris.reinman@gmail.com', 28 | text: '"Andris Reinman" , andris.reinman@gmail.com' 29 | }); 30 | test.done(); 31 | }); 32 | }; 33 | 34 | module.exports['Parse message with large plaintext content'] = test => { 35 | simpleParser(fs.createReadStream(__dirname + '/fixtures/large_text.eml'), (err, mail) => { 36 | test.ifError(err); 37 | 38 | test.ok(mail); 39 | test.ok(mail.textAsHtml); 40 | test.ok(mail.text); 41 | test.ok(!mail.html); 42 | 43 | test.done(); 44 | }); 45 | }; 46 | 47 | module.exports['Parse spam message'] = test => { 48 | simpleParser(fs.createReadStream(__dirname + '/fixtures/spam.eml'), (err, mail) => { 49 | test.ifError(err); 50 | test.ok(mail); 51 | test.ok(mail.html.trim()); 52 | test.done(); 53 | }); 54 | }; 55 | 56 | module.exports['Linkify <> enclosed link'] = test => { 57 | let source = `Content-Type: text/plain; charset=utf-8 58 | Subject: linkify test 59 | 60 | abc def @andrisreinman ghi`; 61 | 62 | let expectedTextAsHtml = 63 | '

abc <https://www.gmail.com/> def @andrisreinman ghi

'; 64 | simpleParser(source, (err, mail) => { 65 | test.ifError(err); 66 | test.ok(mail); 67 | 68 | test.equal(mail.textAsHtml.trim(), expectedTextAsHtml); 69 | 70 | test.done(); 71 | }); 72 | }; 73 | 74 | module.exports['Parse using Iconv'] = test => { 75 | let source = Buffer.concat([ 76 | Buffer.from(`Content-Type: text/plain; charset=ISO-2022-JP 77 | Subject: =?ISO-2022-JP?B?GyRCM1g5OzU7PVEwdzgmPSQ4IUYkMnFKczlwGyhC?= 78 | 79 | `), 80 | Buffer.from('GyRCM1g5OzU7PVEwdzgmPSQ4IUYkMnFKczlwGyhC', 'base64') 81 | ]); 82 | 83 | let expected = '学校技術員研修検討会報告'; 84 | 85 | simpleParser(source, { Iconv }, (err, mail) => { 86 | test.ifError(err); 87 | test.ok(mail); 88 | test.equal(mail.headers.get('subject').trim(), expected); 89 | test.equal(mail.text.trim(), expected); 90 | 91 | test.done(); 92 | }); 93 | }; 94 | 95 | module.exports['Parse using encoding-japanese'] = test => { 96 | let source = Buffer.concat([ 97 | Buffer.from(`Content-Type: text/plain; charset=ISO-2022-JP 98 | Subject: =?ISO-2022-JP?B?GyRCM1g5OzU7PVEwdzgmPSQ4IUYkMnFKczlwGyhC?= 99 | 100 | `), 101 | Buffer.from('GyRCM1g5OzU7PVEwdzgmPSQ4IUYkMnFKczlwGyhC', 'base64') 102 | ]); 103 | 104 | let expected = '学校技術員研修検討会報告'; 105 | 106 | simpleParser(source, {}, (err, mail) => { 107 | test.ifError(err); 108 | test.ok(mail); 109 | test.equal(mail.headers.get('subject').trim(), expected); 110 | test.equal(mail.text.trim(), expected); 111 | 112 | test.done(); 113 | }); 114 | }; 115 | 116 | module.exports['Parse encoded address string'] = test => { 117 | let source = Buffer.from( 118 | `From: test@example.com 119 | To: =?utf-8?B?IlJ5ZGVsIiA8UnlkZWxrYWxvdEAxN2d1YWd1YS5jb20+?=, andris@tr.ee 120 | 121 | test` 122 | ); 123 | 124 | simpleParser(source, {}, (err, mail) => { 125 | test.ifError(err); 126 | test.ok(mail); 127 | 128 | test.deepEqual(mail.to.value, [ 129 | { address: 'andris@tr.ee', name: '' }, 130 | { address: 'Rydelkalot@17guagua.com', name: 'Rydel' } 131 | ]); 132 | 133 | test.done(); 134 | }); 135 | }; 136 | 137 | module.exports['Parse encoded content-disposition'] = test => { 138 | let source = Buffer.from( 139 | `Content-Disposition: =?utf-8?Q?inline?= 140 | Subject: test 141 | 142 | test` 143 | ); 144 | 145 | simpleParser(source, {}, (err, mail) => { 146 | test.ifError(err); 147 | test.ok(mail); 148 | 149 | test.equal(mail.text, 'test'); 150 | 151 | test.done(); 152 | }); 153 | }; 154 | /* 155 | module.exports['Parse invalid date'] = test => { 156 | let source = Buffer.from( 157 | `Date: Tue, 06 Jul 2021 19:21:59 CEST 158 | Subject: test 159 | 160 | test` 161 | ); 162 | 163 | simpleParser(source, {}, (err, mail) => { 164 | test.ifError(err); 165 | test.ok(mail); 166 | 167 | test.equal(mail.date.toISOString(), '2021-07-06T17:21:59.000Z'); 168 | 169 | test.done(); 170 | }); 171 | }; 172 | */ 173 | const RFC_2822_date = { 174 | // commented cases where new Date(val) uses local timezone 175 | '01 Apr 2013 20:18:36 -0500': '2013-04-02T01:18:36.000Z', 176 | //' 01/03/2006': '2006-01-03T08:00:00.000Z', 177 | //'03/11/2014 11:44 AM (GMT-06:00)': '2014-03-11T18:44:00.000Z', 178 | // '2008-10-23, 1:52PM CDT' : '2008-10-23T13:42:00.000Z', 179 | '21 Jan 2013 13:03:51 -0600': '2013-01-21T19:03:51.000Z', 180 | //'4 December 2005': '2005-12-04T08:00:00.000Z', 181 | 'Fri, 02 Dec 2011 09:27:26 -0600': '2011-12-02T15:27:26.000Z', 182 | 'Fri, 07 Mar 2008 02:35:23 -0800 (PST)': '2008-03-07T10:35:23.000Z', 183 | 'Fri, 07 Mar 2014 11:01:40 UTC': '2014-03-07T11:01:40.000Z', 184 | 'January 6, 2009 4:44:14 PM CST': '2009-01-06T22:44:14.000Z', 185 | 'Sun, 8 Jan 2017 20:37:44 +0200': '2017-01-08T18:37:44.000Z' 186 | }; 187 | 188 | for (const d in RFC_2822_date) { 189 | module.exports[`Parses email date: ${d}`] = test => { 190 | simpleParser(Buffer.from(`Date: ${d}\r\nSubject: test\r\n\r\ntest`), {}, (err, mail) => { 191 | test.ifError(err); 192 | test.ok(mail); 193 | 194 | test.equal(mail.date.toISOString(), RFC_2822_date[d]); 195 | 196 | test.done(); 197 | }); 198 | }; 199 | } 200 | --------------------------------------------------------------------------------