132 lines
3.7 KiB
TypeScript
132 lines
3.7 KiB
TypeScript
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<string>('MAIL_USER'),
|
|
password: this.configService.get<string>('MAIL_PASSWORD'),
|
|
host: this.configService.get<string>('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.');
|
|
});
|
|
});
|
|
}
|
|
}
|