mirror of
https://github.com/hcengineering/platform.git
synced 2025-05-06 15:35:28 +00:00
UBERF-9577: Fix using default from address in emails (#8163)
Signed-off-by: Artem Savchenko <armisav@gmail.com>
This commit is contained in:
parent
14a6a3a108
commit
427ef5905b
@ -35,6 +35,7 @@ describe('Config', () => {
|
||||
process.env.SMTP_HOST = 'smtp.example.com'
|
||||
process.env.SMTP_PORT = '587'
|
||||
process.env.SMTP_USERNAME = 'user'
|
||||
process.env.SMTP_PASSWORD = undefined
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||
const loadedConfig = require('../config').default
|
||||
|
@ -22,12 +22,15 @@ jest.mock('../mail', () => ({
|
||||
sendMessage: jest.fn()
|
||||
}))
|
||||
}))
|
||||
jest.mock('../config', () => ({}))
|
||||
jest.mock('../config', () => ({
|
||||
source: 'noreply@example.com'
|
||||
}))
|
||||
|
||||
describe('handleSendMail', () => {
|
||||
let req: Request
|
||||
let res: Response
|
||||
let sendMailMock: jest.Mock
|
||||
let mailClient: MailClient
|
||||
|
||||
beforeEach(() => {
|
||||
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
||||
@ -44,7 +47,8 @@ describe('handleSendMail', () => {
|
||||
send: jest.fn()
|
||||
} as unknown as Response
|
||||
|
||||
sendMailMock = (new MailClient().sendMessage as jest.Mock).mockResolvedValue({})
|
||||
mailClient = new MailClient()
|
||||
sendMailMock = (mailClient.sendMessage as jest.Mock).mockResolvedValue({})
|
||||
})
|
||||
|
||||
it('should return 400 if text is missing', async () => {
|
||||
@ -84,4 +88,45 @@ describe('handleSendMail', () => {
|
||||
|
||||
expect(res.send).toHaveBeenCalled() // Check that a response is still sent
|
||||
})
|
||||
|
||||
it('should use source from config if from is not provided', async () => {
|
||||
await handleSendMail(mailClient, req, res)
|
||||
|
||||
expect(sendMailMock).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
from: 'noreply@example.com', // Verify that the default source from config is used
|
||||
to: 'test@example.com',
|
||||
subject: 'Test Subject',
|
||||
text: 'Hello, world!'
|
||||
})
|
||||
)
|
||||
})
|
||||
|
||||
it('should use from if it is provided', async () => {
|
||||
req.body.from = 'test.from@example.com'
|
||||
await handleSendMail(mailClient, req, res)
|
||||
|
||||
expect(sendMailMock).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
from: 'test.from@example.com', // Verify that the from is used
|
||||
to: 'test@example.com',
|
||||
subject: 'Test Subject',
|
||||
text: 'Hello, world!'
|
||||
})
|
||||
)
|
||||
})
|
||||
|
||||
it('should send to multiple addresses', async () => {
|
||||
req.body.to = ['test1@example.com', 'test2@example.com']
|
||||
await handleSendMail(mailClient, req, res)
|
||||
|
||||
expect(sendMailMock).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
from: 'noreply@example.com',
|
||||
to: ['test1@example.com', 'test2@example.com'], // Verify that multiple addresses are passed
|
||||
subject: 'Test Subject',
|
||||
text: 'Hello, world!'
|
||||
})
|
||||
)
|
||||
})
|
||||
})
|
||||
|
@ -26,10 +26,12 @@ export class MailClient {
|
||||
|
||||
async sendMessage (message: SendMailOptions): Promise<void> {
|
||||
this.transporter.sendMail(message, (err, info) => {
|
||||
const messageInfo = `(from: ${message.from as string}, to: ${message.to as string})`
|
||||
if (err !== null) {
|
||||
console.error('Failed to send email: ', err.message)
|
||||
console.error(`Failed to send email ${messageInfo}: `, err.message)
|
||||
console.log('Failed message details: ', message)
|
||||
} else {
|
||||
console.log(`Email request ${info?.messageId} sent: ${info?.response}`)
|
||||
console.log(`Email request ${messageInfo} sent: ${info?.response}`)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -15,6 +15,7 @@
|
||||
|
||||
import { type SendMailOptions } from 'nodemailer'
|
||||
import { Request, Response } from 'express'
|
||||
import Mail from 'nodemailer/lib/mailer'
|
||||
|
||||
import config from './config'
|
||||
import { createServer, listen } from './server'
|
||||
@ -55,19 +56,36 @@ export const main = async (): Promise<void> => {
|
||||
|
||||
export async function handleSendMail (client: MailClient, req: Request, res: Response): Promise<void> {
|
||||
// Skip auth check, since service should be internal
|
||||
const message: SendMailOptions = req.body
|
||||
if (message?.text === undefined) {
|
||||
const { from, to, subject, text, html, attachments } = req.body
|
||||
const fromAddress = from ?? config.source
|
||||
if (text === undefined) {
|
||||
res.status(400).send({ err: "'text' is missing" })
|
||||
return
|
||||
}
|
||||
if (message?.subject === undefined) {
|
||||
if (subject === undefined) {
|
||||
res.status(400).send({ err: "'subject' is missing" })
|
||||
return
|
||||
}
|
||||
if (message?.to === undefined) {
|
||||
if (to === undefined) {
|
||||
res.status(400).send({ err: "'to' is missing" })
|
||||
return
|
||||
}
|
||||
if (fromAddress === undefined) {
|
||||
res.status(400).send({ err: "'from' is missing" })
|
||||
return
|
||||
}
|
||||
const message: SendMailOptions = {
|
||||
from: fromAddress,
|
||||
to,
|
||||
subject,
|
||||
text
|
||||
}
|
||||
if (html !== undefined) {
|
||||
message.html = html
|
||||
}
|
||||
if (attachments !== undefined) {
|
||||
message.attachments = getAttachments(attachments)
|
||||
}
|
||||
try {
|
||||
await client.sendMessage(message)
|
||||
} catch (err) {
|
||||
@ -76,3 +94,27 @@ export async function handleSendMail (client: MailClient, req: Request, res: Res
|
||||
|
||||
res.send()
|
||||
}
|
||||
|
||||
function getAttachments (attachments: any): Mail.Attachment[] | undefined {
|
||||
if (attachments === undefined || attachments === null) {
|
||||
return undefined
|
||||
}
|
||||
if (!Array.isArray(attachments)) {
|
||||
console.error('attachments is not array')
|
||||
return undefined
|
||||
}
|
||||
return attachments.map((a) => {
|
||||
const attachment: Mail.Attachment = {
|
||||
content: a.content,
|
||||
contentType: a.contentType,
|
||||
path: a.path,
|
||||
filename: a.filename,
|
||||
cid: a.cid,
|
||||
encoding: a.encoding,
|
||||
contentTransferEncoding: a.contentTransferEncoding,
|
||||
headers: a.headers,
|
||||
raw: a.raw
|
||||
}
|
||||
return attachment
|
||||
})
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user