rename send mail functions

This commit is contained in:
Hongbo Wu
2024-04-05 12:16:28 +08:00
parent c37b31dcb6
commit 8af2bb076c
9 changed files with 61 additions and 66 deletions

View File

@ -1,26 +1,37 @@
import { env } from '../env'
import { sendWithMailJet } from '../services/send_emails'
import { Merge } from '../util'
import { logger } from '../utils/logger'
import { sendEmail } from '../utils/sendEmail'
export const SEND_CONFIRMATION_EMAIL_JOB = 'send-confirmation-email'
export const SEND_EMAIL_JOB = 'send-email'
export interface SendConfirmationEmailData {
emailAddress: string
link: string
templateData: Record<string, any>
}
type ContentType = { html: string } | { text: string } | { templateId: string }
export type SendEmailJobData = Merge<
{
emailAddress: string
subject?: string
html?: string
text?: string
templateId?: string
dynamicTemplateData?: Record<string, any>
},
ContentType
>
export const sendConfirmationEmail = async (
data: SendConfirmationEmailData
) => {
if (process.env.USE_MAILJET) {
return sendWithMailJet(data.emailAddress, data.link)
export const sendEmailJob = async (data: SendEmailJobData) => {
if (process.env.USE_MAILJET && data.dynamicTemplateData) {
return sendWithMailJet(data.emailAddress, data.dynamicTemplateData.link)
}
if (!data.html && !data.text && !data.templateId) {
logger.error('no email content provided', data)
return false
}
return sendEmail({
...data,
from: env.sender.message,
to: data.emailAddress,
templateId: env.sendgrid.confirmationTemplateId,
dynamicTemplateData: data.templateData,
})
}

View File

@ -36,10 +36,7 @@ import {
import { refreshAllFeeds } from './jobs/rss/refreshAllFeeds'
import { refreshFeed } from './jobs/rss/refreshFeed'
import { savePageJob } from './jobs/save_page'
import {
sendConfirmationEmail,
SEND_CONFIRMATION_EMAIL_JOB,
} from './jobs/send_email'
import { sendEmailJob, SEND_EMAIL_JOB } from './jobs/send_email'
import {
syncReadPositionsJob,
SYNC_READ_POSITIONS_JOB_NAME,
@ -161,8 +158,8 @@ export const createWorker = (connection: ConnectionOptions) =>
return processYouTubeTranscript(job.data)
case EXPORT_ALL_ITEMS_JOB_NAME:
return exportAllItems(job.data)
case SEND_CONFIRMATION_EMAIL_JOB:
return sendConfirmationEmail(job.data)
case SEND_EMAIL_JOB:
return sendEmailJob(job.data)
default:
logger.warning(`[queue-processor] unhandled job: ${job.name}`)
}

View File

@ -41,7 +41,7 @@ import {
} from '../../generated/graphql'
import { userRepository } from '../../repository/user'
import { createUser } from '../../services/create_user'
import { sendVerificationEmail } from '../../services/send_emails'
import { sendAccountChangeEmail } from '../../services/send_emails'
import { softDeleteUser } from '../../services/user'
import { userDataToUser } from '../../utils/helpers'
import { validateUsername } from '../../utils/usernamePolicy'
@ -358,7 +358,7 @@ export const updateEmailResolver = authorized<
return { email }
}
const result = await sendVerificationEmail({
const result = await sendAccountChangeEmail({
id: user.id,
name: user.name,
email,

View File

@ -23,7 +23,7 @@ import { userRepository } from '../../repository/user'
import { isErrorWithCode } from '../../resolvers'
import { createUser } from '../../services/create_user'
import {
sendConfirmationEmail,
sendNewAccountVerificationEmail,
sendPasswordResetEmail,
} from '../../services/send_emails'
import { analytics } from '../../utils/analytics'
@ -440,7 +440,7 @@ export function authRouter() {
}
if (user.status === StatusType.Pending && user.email) {
await sendConfirmationEmail({
await sendNewAccountVerificationEmail({
id: user.id,
email: user.email,
name: user.name,

View File

@ -1,7 +1,7 @@
/* eslint-disable @typescript-eslint/restrict-template-expressions */
import { StatusType } from '../../../entity/user'
import { userRepository } from '../../../repository/user'
import { sendConfirmationEmail } from '../../../services/send_emails'
import { sendNewAccountVerificationEmail } from '../../../services/send_emails'
import { comparePassword } from '../../../utils/auth'
import { logger } from '../../../utils/logger'
import { decodeAppleToken } from '../apple_auth'
@ -56,7 +56,7 @@ export async function createMobileEmailSignInResponse(
}
if (user.status === StatusType.Pending && user.email) {
await sendConfirmationEmail({
await sendNewAccountVerificationEmail({
id: user.id,
email: user.email,
name: user.name,

View File

@ -16,7 +16,7 @@ import { IntercomClient } from '../utils/intercom'
import { logger } from '../utils/logger'
import { validateUsername } from '../utils/usernamePolicy'
import { addPopularReadsForNewUser } from './popular_reads'
import { sendConfirmationEmail } from './send_emails'
import { sendNewAccountVerificationEmail } from './send_emails'
export const MAX_RECORDS_LIMIT = 1000
@ -142,7 +142,7 @@ export const createUser = async (input: {
})
if (input.pendingConfirmation) {
await sendConfirmationEmail(user)
await sendNewAccountVerificationEmail(user)
}
return [user, profile]

View File

@ -1,15 +1,14 @@
import mailjet from 'node-mailjet'
import { env } from '../env'
import { generateVerificationToken } from '../utils/auth'
import { enqueueConfirmationEmail } from '../utils/createTask'
import { enqueueSendEmail } from '../utils/createTask'
import { logger } from '../utils/logger'
import { sendEmail } from '../utils/sendEmail'
export const sendConfirmationEmail = async (user: {
export const sendNewAccountVerificationEmail = async (user: {
id: string
name: string
email: string
}) => {
}): Promise<boolean> => {
// generate confirmation link
const token = generateVerificationToken({ id: user.id })
const link = `${env.client.url}/auth/confirm-email/${token}`
@ -19,11 +18,13 @@ export const sendConfirmationEmail = async (user: {
link,
}
await enqueueConfirmationEmail({
const result = await enqueueSendEmail({
emailAddress: user.email,
link,
templateData: dynamicTemplateData,
dynamicTemplateData: dynamicTemplateData,
templateId: env.sendgrid.confirmationTemplateId,
})
return !!result
}
export const sendWithMailJet = async (
@ -64,7 +65,7 @@ export const sendWithMailJet = async (
return true
}
export const sendVerificationEmail = async (user: {
export const sendAccountChangeEmail = async (user: {
id: string
name: string
email: string
@ -78,16 +79,13 @@ export const sendVerificationEmail = async (user: {
link,
}
if (process.env.USE_MAILJET) {
return sendWithMailJet(user.email, link)
}
return sendEmail({
from: env.sender.message,
to: user.email,
const result = await enqueueSendEmail({
emailAddress: user.email,
dynamicTemplateData: dynamicTemplateData,
templateId: env.sendgrid.verificationTemplateId,
dynamicTemplateData,
})
return !!result
}
export const sendPasswordResetEmail = async (user: {
@ -104,14 +102,11 @@ export const sendPasswordResetEmail = async (user: {
link,
}
if (process.env.USE_MAILJET) {
return sendWithMailJet(user.email, link)
}
return sendEmail({
from: env.sender.message,
to: user.email,
const result = await enqueueSendEmail({
emailAddress: user.email,
dynamicTemplateData: dynamicTemplateData,
templateId: env.sendgrid.resetPasswordTemplateId,
dynamicTemplateData,
})
return !!result
}

View File

@ -35,10 +35,7 @@ import {
REFRESH_ALL_FEEDS_JOB_NAME,
REFRESH_FEED_JOB_NAME,
} from '../jobs/rss/refreshAllFeeds'
import {
SendConfirmationEmailData,
SEND_CONFIRMATION_EMAIL_JOB,
} from '../jobs/send_email'
import { SendEmailJobData, SEND_EMAIL_JOB } from '../jobs/send_email'
import { SYNC_READ_POSITIONS_JOB_NAME } from '../jobs/sync_read_positions'
import { TriggerRuleJobData, TRIGGER_RULE_JOB_NAME } from '../jobs/trigger_rule'
import {
@ -73,7 +70,7 @@ export const getJobPriority = (jobName: string): number => {
case UPDATE_LABELS_JOB:
case UPDATE_HIGHLIGHT_JOB:
case SYNC_READ_POSITIONS_JOB_NAME:
case SEND_CONFIRMATION_EMAIL_JOB:
case SEND_EMAIL_JOB:
return 1
case TRIGGER_RULE_JOB_NAME:
case CALL_WEBHOOK_JOB_NAME:
@ -844,20 +841,15 @@ export const enqueueExportItem = async (jobData: ExportItemJobData) => {
})
}
export const enqueueConfirmationEmail = async (
jobData: SendConfirmationEmailData
) => {
export const enqueueSendEmail = async (jobData: SendEmailJobData) => {
const queue = await getBackendQueue()
if (!queue) {
return undefined
}
return queue.add(SEND_CONFIRMATION_EMAIL_JOB, jobData, {
return queue.add(SEND_EMAIL_JOB, jobData, {
attempts: 1, // only try once
priority: getJobPriority(SEND_CONFIRMATION_EMAIL_JOB),
jobId: `${SEND_CONFIRMATION_EMAIL_JOB}_${jobData.emailAddress}_${JOB_VERSION}`, // deduplication
removeOnComplete: true,
removeOnFail: true,
priority: getJobPriority(SEND_EMAIL_JOB),
})
}

View File

@ -5,7 +5,7 @@ import sinon from 'sinon'
import sinonChai from 'sinon-chai'
import { Filter } from '../../src/entity/filter'
import { StatusType, User } from '../../src/entity/user'
import { SendConfirmationEmailData } from '../../src/jobs/send_email'
import { SendTemplatedEmailData } from '../../src/jobs/send_email'
import { authTrx, getRepository } from '../../src/repository'
import { findProfile } from '../../src/services/profile'
import { deleteUser } from '../../src/services/user'
@ -97,7 +97,7 @@ describe('create user', () => {
context('create a user with pending confirmation', () => {
const name = 'pendingUser'
let fake: (
jobData: SendConfirmationEmailData
jobData: SendTemplatedEmailData
) => Promise<Job<any, any, string> | undefined>
context('when email sends successfully', () => {