[local-sync] Use mimelib to parse contacts

Summary:
Because of the way we were attempting to parse contacts from
From/To/Cc/Bcc headers by converting them to JSON with a regex, we were
erroneously breaking contacts that contained commas in quoted names into
multiple contacts. This could result in things like parsing multiple
addresses for the From: header, incorrectly!

To resolve the problem, replace our homegrown logic with mimelib's
seemingly excellent parseAddresses(), which handles this and a myriad of
other cases correctly.

Fixes: T7370

Test Plan: unit tests included

Reviewers: mark

Reviewed By: mark

Differential Revision: https://phab.nylas.com/D3565
This commit is contained in:
Christine Spang 2016-12-29 10:56:00 -08:00
parent 952349ee72
commit 40c7b09e27
2 changed files with 36 additions and 6 deletions

View file

@ -1,5 +1,5 @@
const LocalDatabaseConnector = require('../src/shared/local-database-connector');
const {parseFromImap, extractSnippet} = require('../src/shared/message-factory');
const {parseFromImap, extractSnippet, extractContacts} = require('../src/shared/message-factory');
const {forEachJSONFixture, forEachHTMLAndTXTFixture, ACCOUNT_ID} = require('./helpers');
xdescribe('MessageFactory', function MessageFactorySpecs() {
@ -85,6 +85,21 @@ const snippetTestCases = [{
},
]
const contactsTestCases = [{
purpose: "not erroneously split contact names on commas",
// NOTE: inputs must be in same format as output by mimelib.parseHeader
input: ['"Little Bo Peep, The Hill" <bopeep@example.com>'],
output: [{name: "Little Bo Peep, The Hill", email: "bopeep@example.com"}],
}, {
purpose: "extract two separate contacts, removing quotes properly & respecing unicode",
input: ['AppleBees Zé <a@example.com>, "Tiger Zen" b@example.com'],
output: [
{name: 'AppleBees Zé', email: 'a@example.com'},
{name: 'Tiger Zen', email: 'b@example.com'},
],
},
]
describe('MessageFactoryHelpers', function MessageFactoryHelperSpecs() {
describe('extractSnippet (basic)', () => {
snippetTestCases.forEach(({purpose, plainBody, htmlBody, snippet}) => {
@ -102,4 +117,12 @@ describe('MessageFactoryHelpers', function MessageFactoryHelperSpecs() {
});
});
});
describe('extractContacts (basic)', () => {
contactsTestCases.forEach(({purpose, input, output}) => {
it(`should ${purpose}`, () => {
const parsedContacts = extractContacts(input);
expect(parsedContacts).toEqual(output);
});
});
});
});

View file

@ -23,14 +23,20 @@ function extractContacts(input) {
if (!input || input.length === 0 || !input[0]) {
return [];
}
const s = `["${input[0].replace(/"/g, '\\"').replace(/, /g, '", "')}"]`;
const values = JSON.parse(s);
const values = mimelib.parseAddresses(input[0]);
if (!values || values.length === 0 || !input[0]) {
return [];
}
return values.map(v => {
const parsed = mimelib.parseAddresses(v)
if (!parsed || parsed.length === 0) {
if (!v || v.length === 0) {
return null
}
const {name, address: email} = parsed.pop()
const {name, address: email} = v;
// contacts without an email address are worthless, especially when
// extracted from emails
if (!email) {
return null;
}
return {name, email}
})
.filter(c => c != null)
@ -319,6 +325,7 @@ module.exports = {
buildForSend,
parseFromImap,
extractSnippet,
extractContacts,
stripTrackingLinksFromBody,
buildTrackingBodyForRecipient,
replaceMessageIdInBodyTrackingLinks,