Add support to the case when from address is in Name <address> format
This commit is contained in:
@ -13,6 +13,7 @@ import {
|
||||
getTitleFromEmailSubject,
|
||||
isProbablyArticle,
|
||||
isProbablyNewsletter,
|
||||
parseEmailAddress,
|
||||
} from '../../utils/parser'
|
||||
import { saveNewsletterEmail } from '../../services/save_newsletter_email'
|
||||
import { saveEmail } from '../../services/save_email'
|
||||
@ -75,6 +76,7 @@ export function emailsServiceRouter() {
|
||||
}
|
||||
const user = newsletterEmail.user
|
||||
const ctx = { pubsub: createPubSubClient(), uid: user.id }
|
||||
const parsedFrom = parseEmailAddress(data.from)
|
||||
|
||||
if (await isProbablyNewsletter(data.html)) {
|
||||
logger.info('handling as newsletter', data)
|
||||
@ -83,7 +85,7 @@ export function emailsServiceRouter() {
|
||||
email: data.to,
|
||||
title: data.subject,
|
||||
content: data.html,
|
||||
author: data.from,
|
||||
author: parsedFrom.name,
|
||||
url: (await findNewsletterUrl(data.html)) || generateUniqueUrl(),
|
||||
unsubMailTo: data.unsubMailTo,
|
||||
unsubHttpUrl: data.unsubHttpUrl,
|
||||
@ -95,11 +97,11 @@ export function emailsServiceRouter() {
|
||||
return
|
||||
}
|
||||
|
||||
if (await isProbablyArticle(data.from, data.subject)) {
|
||||
if (await isProbablyArticle(parsedFrom.address, data.subject)) {
|
||||
logger.info('handling as article', data)
|
||||
await saveEmail(ctx, {
|
||||
title: getTitleFromEmailSubject(data.subject),
|
||||
author: data.from,
|
||||
author: parsedFrom.name,
|
||||
url: generateUniqueUrl(),
|
||||
originalContent: data.html,
|
||||
})
|
||||
|
||||
@ -19,6 +19,7 @@ import { getRepository } from '../entity/utils'
|
||||
import { User } from '../entity/user'
|
||||
import { ILike } from 'typeorm'
|
||||
import { v4 as uuid } from 'uuid'
|
||||
import addressparser from 'addressparser'
|
||||
|
||||
const logger = buildLogger('utils.parse')
|
||||
|
||||
@ -567,3 +568,14 @@ export const getTitleFromEmailSubject = (subject: string) => {
|
||||
const title = subject.replace(ARTICLE_PREFIX, '')
|
||||
return title.trim()
|
||||
}
|
||||
|
||||
export const parseEmailAddress = (from: string): addressparser.EmailAddress => {
|
||||
// get author name from email
|
||||
// e.g. 'Jackson Harper from Omnivore App <jacksonh@substack.com>'
|
||||
// or 'Mike Allen <mike@axios.com>'
|
||||
const parsed = addressparser(from)
|
||||
if (parsed.length > 0) {
|
||||
return parsed[0]
|
||||
}
|
||||
return { name: from, address: from }
|
||||
}
|
||||
|
||||
@ -64,7 +64,7 @@ export const deleteTestUser = async (name: string) => {
|
||||
await AppDataSource.createQueryBuilder()
|
||||
.delete()
|
||||
.from(User)
|
||||
.where({ email: `${name}@fake.com` })
|
||||
.where({ email: `${name}@omnivore.app` })
|
||||
.execute()
|
||||
}
|
||||
|
||||
@ -77,7 +77,7 @@ export const createTestUser = async (
|
||||
const [newUser] = await createUser({
|
||||
provider: 'GOOGLE',
|
||||
sourceUserId: 'fake-user-id-' + name,
|
||||
email: `${name}@fake.com`,
|
||||
email: `${name}@omnivore.app`,
|
||||
username: name,
|
||||
bio: `i am ${name}`,
|
||||
name: name,
|
||||
@ -93,7 +93,7 @@ export const createUserWithoutProfile = async (name: string): Promise<User> => {
|
||||
return getRepository(User).save({
|
||||
source: 'GOOGLE',
|
||||
sourceUserId: 'fake-user-id-' + name,
|
||||
email: `${name}@fake.com`,
|
||||
email: `${name}@omnivore.app`,
|
||||
name: name,
|
||||
})
|
||||
}
|
||||
|
||||
@ -28,11 +28,11 @@ describe('Newsletters API', () => {
|
||||
// create test newsletter emails
|
||||
const newsletterEmail1 = await createTestNewsletterEmail(
|
||||
user,
|
||||
'Test_email_address_1@fake-email.com'
|
||||
'Test_email_address_1@omnivore.app'
|
||||
)
|
||||
const newsletterEmail2 = await createTestNewsletterEmail(
|
||||
user,
|
||||
'Test_email_address_2@fake-email.com'
|
||||
'Test_email_address_2@omnivore.app'
|
||||
)
|
||||
newsletterEmails = [newsletterEmail1, newsletterEmail2]
|
||||
})
|
||||
|
||||
@ -47,7 +47,7 @@ describe('auth router', () => {
|
||||
before(() => {
|
||||
password = validPassword
|
||||
username = 'Some_username'
|
||||
email = `${username}@fake.com`
|
||||
email = `${username}@omnivore.app`
|
||||
name = 'Some name'
|
||||
})
|
||||
|
||||
@ -397,9 +397,7 @@ describe('auth router', () => {
|
||||
|
||||
it('redirects to forgot-password page with success message', async () => {
|
||||
const res = await emailResetPasswordReq(email).expect(302)
|
||||
expect(res.header.location).to.endWith(
|
||||
'/auth/reset-sent'
|
||||
)
|
||||
expect(res.header.location).to.endWith('/auth/reset-sent')
|
||||
})
|
||||
})
|
||||
|
||||
@ -434,9 +432,7 @@ describe('auth router', () => {
|
||||
|
||||
it('redirects to email-login page with error code PENDING_VERIFICATION', async () => {
|
||||
const res = await emailResetPasswordReq(email).expect(302)
|
||||
expect(res.header.location).to.endWith(
|
||||
'/auth/reset-sent'
|
||||
)
|
||||
expect(res.header.location).to.endWith('/auth/reset-sent')
|
||||
})
|
||||
})
|
||||
})
|
||||
@ -448,9 +444,7 @@ describe('auth router', () => {
|
||||
|
||||
it('redirects to forgot-password page with error code USER_NOT_FOUND', async () => {
|
||||
const res = await emailResetPasswordReq(email).expect(302)
|
||||
expect(res.header.location).to.endWith(
|
||||
'/auth/reset-sent'
|
||||
)
|
||||
expect(res.header.location).to.endWith('/auth/reset-sent')
|
||||
})
|
||||
})
|
||||
})
|
||||
@ -501,9 +495,7 @@ describe('auth router', () => {
|
||||
const res = await resetPasswordRequest(token, 'new_password').expect(
|
||||
302
|
||||
)
|
||||
expect(res.header.location).to.contain(
|
||||
'/api/client/auth?tok'
|
||||
)
|
||||
expect(res.header.location).to.contain('/api/client/auth?tok')
|
||||
})
|
||||
|
||||
it('resets password', async () => {
|
||||
|
||||
@ -12,7 +12,7 @@ import { getPageById } from '../../src/elastic/pages'
|
||||
|
||||
describe('PDF attachments Router', () => {
|
||||
const username = 'fakeUser'
|
||||
const newsletterEmail = 'fakeEmail@fake-email.com'
|
||||
const newsletterEmail = 'fakeEmail@omnivore.app'
|
||||
|
||||
let user: User
|
||||
let authToken: string
|
||||
|
||||
@ -9,6 +9,7 @@ import {
|
||||
getTitleFromEmailSubject,
|
||||
isProbablyArticle,
|
||||
isProbablyNewsletter,
|
||||
parseEmailAddress,
|
||||
parsePageMetadata,
|
||||
parsePreparedContent,
|
||||
} from '../../src/utils/parser'
|
||||
@ -179,3 +180,13 @@ describe('getTitleFromEmailSubject', () => {
|
||||
expect(getTitleFromEmailSubject(subject)).to.eql(title)
|
||||
})
|
||||
})
|
||||
|
||||
describe('parseEmailAddress', () => {
|
||||
const email = 'Tester <tester@omnivore.app>'
|
||||
|
||||
it('returns the name and address', () => {
|
||||
const { name, address } = parseEmailAddress(email)
|
||||
expect(name).to.eql('Tester')
|
||||
expect(address).to.eql('tester@omnivore.app')
|
||||
})
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user