All files / src/features/mail/providers nodemailer.provider.ts

81.81% Statements 18/22
89.47% Branches 17/19
100% Functions 2/2
81.81% Lines 18/22

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65              10x   10x                   2x 2x 2x 2x 2x 2x   2x 1x 1x       1x               2x 2x           1x               2x 2x 1x              
import { Injectable, Logger } from '@nestjs/common'
import * as nodemailer from 'nodemailer'
import { ConfigService } from '@nestjs/config'
import { MailProvider, MailConfig } from './mail-provider.interface'
 
@Injectable()
export class NodemailerProvider implements MailProvider {
    private readonly logger = new Logger(NodemailerProvider.name)
 
    constructor(private readonly configService: ConfigService) {}
 
    async send(
        to: string,
        subject: string,
        template: string,
        context: Record<string, any>,
        attachments?: { filename: string; content: Buffer }[],
        config?: MailConfig,
    ): Promise<void> {
        const host = config?.host || this.configService.get<string>('SMTP_HOST')
        const port = config?.port || this.configService.get<number>('SMTP_PORT') || 587
        const secure = config?.secure ?? port === 465
        const user = config?.auth?.user || this.configService.get<string>('SMTP_USER')
        const pass = config?.auth?.pass || this.configService.get<string>('SMTP_PASS')
        const from = config?.from || this.configService.get<string>('SMTP_FROM')
 
        if (!host) {
            this.logger.error('SMTP configuration missing (Host). Cannot send email.')
            throw new Error('SMTP configuration missing')
        }
 
        // Create transporter
        const transporter = nodemailer.createTransport({
            host,
            port,
            secure,
            auth: user ? { user, pass } : undefined,
        })
 
        // Verify connection config
        try {
            await transporter.verify()
        } catch (error) {
            this.logger.error('SMTP Connection failed', error)
            throw error
        }
 
        const mailOptions = {
            from: from || user, // Default to auth user if from is not set
            to,
            subject,
            html: template,
            attachments,
        }
 
        try {
            const info = await transporter.sendMail(mailOptions)
            this.logger.log(`Message sent: ${info.messageId}`)
        } catch (error) {
            this.logger.error('Error sending email via SMTP', error)
            throw error
        }
    }
}