import { extractVerifyCodeLANGTONS, verifyCode } from '@/ultils'; import { ConfigService } from '@nestjs/config'; import { EventEmitter2 } from '@nestjs/event-emitter'; import { WebSocketGateway } from '@nestjs/websockets'; import * as Imap from 'imap'; import { Server, Socket } from 'socket.io'; import { WebBidsService } from '../web-bids.service'; import { Like } from 'typeorm'; import { Event } from '../../utils/events'; import { plainToClass } from 'class-transformer'; import { WebBid } from '../../entities/wed-bid.entity'; @WebSocketGateway({ namespace: 'admin-bid-ws', cors: { origin: '*', methods: ['GET', 'POST'], credentials: true, }, }) export class ImapService { private imap: Imap; server: Server; constructor( private readonly configService: ConfigService, private readonly webBidsService: WebBidsService, private eventEmitter: EventEmitter2, ) { this.imap = new Imap({ user: this.configService.get('MAIL_USER'), password: this.configService.get('MAIL_PASSWORD'), host: this.configService.get('MAIL_SERVER'), port: 993, tls: true, tlsOptions: { rejectUnauthorized: false }, }); } async connectIMAP() { this.imap.once('ready', () => { console.log('📥 IMAP Connected. Listening for new emails...'); this.openInbox(); }); this.imap.on('error', (err) => { console.error('❌ IMAP Error:', err); }); this.imap.on('end', () => { console.log('📴 IMAP Connection Ended'); setTimeout(() => this.connectIMAP(), 5000); }); this.imap.connect(); } private openInbox() { this.imap.openBox('INBOX', false, (err, box) => { if (err) { console.error('❌ Error opening inbox:', err); return; } console.log('📬 INBOX opened, waiting for new emails...'); // Lắng nghe email mới this.imap.on('mail', (numNewMsgs: number) => { console.log(`📩 New email received! (${numNewMsgs} new messages)`); this.fetchLatestEmail(); }); }); } private fetchLatestEmail() { this.imap.search(['UNSEEN'], (err, results) => { if (err || !results.length) { console.log('📭 No new unread emails.'); return; } const fetchOptions = { bodies: '', struct: true }; const f = this.imap.fetch(results.slice(-1), fetchOptions); // Lấy email mới nhất f.on('message', (msg, seqno) => { console.log(`📥 Fetching email #${seqno}`); let emailContent = ''; let header = ''; msg.on('body', (stream) => { stream.on('data', (chunk) => { emailContent += chunk.toString(); }); stream.on('end', async () => { const result = verifyCode(emailContent); if (!result) { throw new Error('fetchLatestEmail: Name or Code is empty'); } const { code, name } = result; const webBid = await this.webBidsService.webBidRepo.findOne({ where: { origin_url: Like(`%${name.toLocaleLowerCase()}%`) }, }); if (!webBid) { throw new Error('Not found web bid'); } // send message event this.eventEmitter.emit(Event.verifyCode(webBid), { code, name, web_bid: plainToClass(WebBid, webBid), }); }); }); }); f.on('error', (err) => { console.error('❌ Fetch error:', err); }); f.on('end', () => { console.log('✅ Done fetching emails.'); }); }); } }