mirror of
https://github.com/hcengineering/platform.git
synced 2025-05-07 16:07:24 +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_HOST = 'smtp.example.com'
|
||||||
process.env.SMTP_PORT = '587'
|
process.env.SMTP_PORT = '587'
|
||||||
process.env.SMTP_USERNAME = 'user'
|
process.env.SMTP_USERNAME = 'user'
|
||||||
|
process.env.SMTP_PASSWORD = undefined
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||||
const loadedConfig = require('../config').default
|
const loadedConfig = require('../config').default
|
||||||
|
@ -22,12 +22,15 @@ jest.mock('../mail', () => ({
|
|||||||
sendMessage: jest.fn()
|
sendMessage: jest.fn()
|
||||||
}))
|
}))
|
||||||
}))
|
}))
|
||||||
jest.mock('../config', () => ({}))
|
jest.mock('../config', () => ({
|
||||||
|
source: 'noreply@example.com'
|
||||||
|
}))
|
||||||
|
|
||||||
describe('handleSendMail', () => {
|
describe('handleSendMail', () => {
|
||||||
let req: Request
|
let req: Request
|
||||||
let res: Response
|
let res: Response
|
||||||
let sendMailMock: jest.Mock
|
let sendMailMock: jest.Mock
|
||||||
|
let mailClient: MailClient
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
||||||
@ -44,7 +47,8 @@ describe('handleSendMail', () => {
|
|||||||
send: jest.fn()
|
send: jest.fn()
|
||||||
} as unknown as Response
|
} 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 () => {
|
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
|
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> {
|
async sendMessage (message: SendMailOptions): Promise<void> {
|
||||||
this.transporter.sendMail(message, (err, info) => {
|
this.transporter.sendMail(message, (err, info) => {
|
||||||
|
const messageInfo = `(from: ${message.from as string}, to: ${message.to as string})`
|
||||||
if (err !== null) {
|
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 {
|
} 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 { type SendMailOptions } from 'nodemailer'
|
||||||
import { Request, Response } from 'express'
|
import { Request, Response } from 'express'
|
||||||
|
import Mail from 'nodemailer/lib/mailer'
|
||||||
|
|
||||||
import config from './config'
|
import config from './config'
|
||||||
import { createServer, listen } from './server'
|
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> {
|
export async function handleSendMail (client: MailClient, req: Request, res: Response): Promise<void> {
|
||||||
// Skip auth check, since service should be internal
|
// Skip auth check, since service should be internal
|
||||||
const message: SendMailOptions = req.body
|
const { from, to, subject, text, html, attachments } = req.body
|
||||||
if (message?.text === undefined) {
|
const fromAddress = from ?? config.source
|
||||||
|
if (text === undefined) {
|
||||||
res.status(400).send({ err: "'text' is missing" })
|
res.status(400).send({ err: "'text' is missing" })
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (message?.subject === undefined) {
|
if (subject === undefined) {
|
||||||
res.status(400).send({ err: "'subject' is missing" })
|
res.status(400).send({ err: "'subject' is missing" })
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (message?.to === undefined) {
|
if (to === undefined) {
|
||||||
res.status(400).send({ err: "'to' is missing" })
|
res.status(400).send({ err: "'to' is missing" })
|
||||||
return
|
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 {
|
try {
|
||||||
await client.sendMessage(message)
|
await client.sendMessage(message)
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
@ -76,3 +94,27 @@ export async function handleSendMail (client: MailClient, req: Request, res: Res
|
|||||||
|
|
||||||
res.send()
|
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