Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 22 additions & 1 deletion index.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
* @property {string} encoding Content-Transfer-Encoding
* @property {string} Body Encoded content
* @property {Array<string>} Headers Encoded headers
* @property {MIME} MIME Mime property
*/

/**
Expand All @@ -39,6 +40,7 @@
* @property {Date} date Mail Date header
* @property {Date} deliveryDate Mail Delivery-Date header
* @property {Array<Attachment>} attachments List of mail attachments
* @property {Attachment} Content The main mail content
* @property {string} Created Mail Created property
* @property {MIME} MIME Mail Mime property
*/
Expand Down Expand Up @@ -173,6 +175,25 @@ function decode(str, encoding, charset) {
return require('iconv-lite').decode(buffer, charset)
}

/**
* Recursively gathers the attachments of both the passed mail object
* and recursively of its attachment parts.
*
* @param {object} entry MailHog mail or Attachment object
* @returns {Array<Attachment>} List of mail attachments parts
*/
function getMimePartsRecursively(entry) {
if (!entry.MIME) {
return []
}
let results = []
for (const part of entry.MIME.Parts) {
results.push(part)
results = results.concat(getMimePartsRecursively(part))
}
return results
}

/**
* Returns the content part matching the given content-type regular expression.
*
Expand All @@ -182,7 +203,7 @@ function decode(str, encoding, charset) {
*/
function getContent(mail, typeRegExp) {
let parts = [mail.Content]
if (mail.MIME) parts = parts.concat(mail.MIME.Parts)
parts = parts.concat(getMimePartsRecursively(mail))
for (const part of parts) {
const type = (part.Headers['Content-Type'] || '').toString()
if (typeRegExp.test(type)) {
Expand Down
39 changes: 32 additions & 7 deletions index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,26 @@ describe('multipart', function () {
})
})

describe('multipart hierarchical', function () {
it('parses quoted-printable encoded text content', async function () {
const result = await mailhog.latestTo('[email protected]')
assert.strictEqual(
result.text,
'Some Test Message Text',
'Parses sub-level text part'
)
})

it('parses quoted-printable encoded HTML content', async function () {
const result = await mailhog.latestTo('[email protected]')
assert.strictEqual(
result.html,
'Some Test Message HTML',
'Parses sub-level html part'
)
})
})

describe('charset', function () {
it('parses mail with utf8 charset', async function () {
const result = await mailhog.latestTo('[email protected]')
Expand Down Expand Up @@ -297,31 +317,36 @@ describe('headers', function () {
describe('messages', function () {
it('retrieve mails', async function () {
const result = await mailhog.messages()
assert.strictEqual(result.count, 4, 'Returns all emails')
assert.strictEqual(result.count, 5, 'Returns all emails')
assert.strictEqual(
result.items[0].subject,
'Mail with hierarchical mime content',
'Returns the decoded mail Subject header for the fifth mail in the set'
)
assert.strictEqual(
result.items[1].subject,
'Mail without charset',
'Returns the decoded mail Subject header for the first mail in the set'
)
assert.strictEqual(
result.items[1].subject,
result.items[2].subject,
'ISO-8859-1',
'Returns the decoded mail Subject header for the second mail in the set'
)
assert.strictEqual(
result.items[2].subject,
result.items[3].subject,
'日本',
'Returns the decoded mail Subject header for the third mail in the set'
)
assert.strictEqual(
result.items[3].subject,
result.items[4].subject,
'üäö',
'Returns the decoded mail Subject header for the fourth mail in the set'
)
})

it('limit the messages range', async function () {
const result = await mailhog.messages(3, 1)
const result = await mailhog.messages(4, 1)
assert.strictEqual(result.count, 1, 'Returns a set for the given range')
assert.strictEqual(
result.items[0].subject,
Expand Down Expand Up @@ -469,7 +494,7 @@ describe('releaseMessage', function () {
const listResult = await mailhog.messages()
assert.strictEqual(
listResult.count,
5,
6,
'Number of mails stored has increased by 1'
)
})
Expand All @@ -496,7 +521,7 @@ describe('deleteMessage', function () {
const listResult = await mailhog.messages()
assert.strictEqual(
listResult.count,
3,
4,
'Number of mails stored has decreased by 1'
)
})
Expand Down
33 changes: 33 additions & 0 deletions mail/05.eml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
Content-Type: multipart/mixed; boundary="===============7426108140616550474=="
Date: Tue, 17 May 2022 11:12:22 +0000
From: [email protected]
MIME-Version: 1.0
Message-ID: <165278594245.265.1843128869165443175@09814d7d4841>
Received: from [123.4.5.6] by mailhog.example (MailHog)
id [email protected]; Tue, 17 May 2022 11:12:22 +0000
Return-Path: <[email protected]>
Subject: Mail with hierarchical mime content
To: [email protected]

--===============7426108140616550474==
Content-Type: multipart/alternative;
boundary="===============1607218409922029753=="
MIME-Version: 1.0

--===============1607218409922029753==
Content-Type: text/plain; charset="utf-8"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit

Some Test Message Text

--===============1607218409922029753==
Content-Type: text/html; charset="utf-8"
MIME-Version: 1.0
Content-Transfer-Encoding: 8bit

Some Test Message HTML

--===============1607218409922029753==--

--===============7426108140616550474==--