Changing how messages are fetched and marked as read
This commit is contained in:
parent
29ec45e690
commit
931a8b7f6c
4 changed files with 36 additions and 14 deletions
|
|
@ -15,6 +15,7 @@ export enum EmailClientStatus {
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class EmailClient {
|
export class EmailClient {
|
||||||
public readonly imapClient: Imap
|
public readonly imapClient: Imap
|
||||||
|
private readonly mailboxName: string
|
||||||
private mailbox?: Imap.Box
|
private mailbox?: Imap.Box
|
||||||
private status: EmailClientStatus
|
private status: EmailClientStatus
|
||||||
|
|
||||||
|
|
@ -25,6 +26,7 @@ export class EmailClient {
|
||||||
@Inject(ConfigService)
|
@Inject(ConfigService)
|
||||||
private readonly configService: ConfigService,
|
private readonly configService: ConfigService,
|
||||||
) {
|
) {
|
||||||
|
this.mailboxName = this.configService.getOrThrow<string>('EMAIL_MAILBOX')
|
||||||
this.imapClient = new Imap({
|
this.imapClient = new Imap({
|
||||||
host: this.configService.getOrThrow('EMAIL_HOST'),
|
host: this.configService.getOrThrow('EMAIL_HOST'),
|
||||||
port: this.configService.get('EMAIL_PORT', 993),
|
port: this.configService.get('EMAIL_PORT', 993),
|
||||||
|
|
@ -90,8 +92,10 @@ export class EmailClient {
|
||||||
)
|
)
|
||||||
|
|
||||||
if (newMessages > 0) {
|
if (newMessages > 0) {
|
||||||
const startingMessage = totalMessages - newMessages + 1 // starting message is inclusive
|
const emails = await this.fetchMailsFrom(
|
||||||
const emails = await this.fetchMails(`${startingMessage}`, '*')
|
totalMessages - (numMessages - 1),
|
||||||
|
)
|
||||||
|
this.loggerService.debug(`Fetched ${emails.length} emails`)
|
||||||
callback(emails)
|
callback(emails)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -102,8 +106,7 @@ export class EmailClient {
|
||||||
throw new Error('Not ready to listen')
|
throw new Error('Not ready to listen')
|
||||||
}
|
}
|
||||||
|
|
||||||
const mailbox = this.configService.get<string>('EMAIL_MAILBOX', 'INBOX')
|
this.imapClient.openBox(this.mailboxName, (error, mailbox) => {
|
||||||
this.imapClient.openBox(mailbox, (error, mailbox) => {
|
|
||||||
if (error) {
|
if (error) {
|
||||||
this.loggerService.error('Error opening mailbox', {
|
this.loggerService.error('Error opening mailbox', {
|
||||||
...error,
|
...error,
|
||||||
|
|
@ -171,17 +174,13 @@ export class EmailClient {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
public async fetchMails(startingMessageId: string, endingMessageId: string) {
|
public async fetchMailsFrom(startingMessageSeqNo: number) {
|
||||||
this.loggerService.debug(
|
this.loggerService.debug(
|
||||||
`Fetching mails ${startingMessageId}:${endingMessageId}`,
|
`Fetching mails starting from ${startingMessageSeqNo}`,
|
||||||
)
|
)
|
||||||
const fetcher = this.imapClient.fetch(
|
const fetcher = this.imapClient.seq.fetch(`${startingMessageSeqNo}:*`, {
|
||||||
`${startingMessageId}:${endingMessageId}`,
|
|
||||||
{
|
|
||||||
bodies: '',
|
bodies: '',
|
||||||
markSeen: true,
|
})
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
return new Promise<Email[]>((res, rej) => {
|
return new Promise<Email[]>((res, rej) => {
|
||||||
const generateEmailPromises: Promise<Email>[] = []
|
const generateEmailPromises: Promise<Email>[] = []
|
||||||
|
|
@ -198,6 +197,18 @@ export class EmailClient {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async markMailsSeen(messageIds: string[]) {
|
||||||
|
this.loggerService.debug('Marking mails as seen', { messageIds })
|
||||||
|
return new Promise<void>((res, rej) => {
|
||||||
|
this.imapClient.addFlags(messageIds.join(','), ['\\Seen'], (error) => {
|
||||||
|
if (error != null) {
|
||||||
|
rej(error)
|
||||||
|
}
|
||||||
|
res()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
private setupDefaultListeners() {
|
private setupDefaultListeners() {
|
||||||
this.imapClient.on('ready', () => {
|
this.imapClient.on('ready', () => {
|
||||||
this.loggerService.debug('email client ready')
|
this.loggerService.debug('email client ready')
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@ export class EmailProvider {
|
||||||
}
|
}
|
||||||
|
|
||||||
private async handleReceivedEmails(emails: Email[]) {
|
private async handleReceivedEmails(emails: Email[]) {
|
||||||
this.emailsQueue.addBulk(
|
await this.emailsQueue.addBulk(
|
||||||
emails.map((email) => ({ name: email.id, data: email })),
|
emails.map((email) => ({ name: email.id, data: email })),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -27,4 +27,8 @@ export class EmailProvider {
|
||||||
public registerEmailListener() {
|
public registerEmailListener() {
|
||||||
this.emailClient.listen((emails) => this.handleReceivedEmails(emails))
|
this.emailClient.listen((emails) => this.handleReceivedEmails(emails))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async readEmails(emails: Email[]) {
|
||||||
|
await this.emailClient.markMailsSeen(emails.map((e) => e.id))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
import { BullModule } from '@nestjs/bull'
|
import { BullModule } from '@nestjs/bull'
|
||||||
import { Module } from '@nestjs/common'
|
import { Module } from '@nestjs/common'
|
||||||
|
import { EmailModule } from 'src/email/module'
|
||||||
import { ReservationsModule } from 'src/reservations/module'
|
import { ReservationsModule } from 'src/reservations/module'
|
||||||
|
|
||||||
import { EMAILS_QUEUE_NAME } from '../email/config'
|
import { EMAILS_QUEUE_NAME } from '../email/config'
|
||||||
|
|
@ -13,6 +14,7 @@ import { WaitingListService } from './service'
|
||||||
ReservationsModule,
|
ReservationsModule,
|
||||||
BullModule.registerQueue({ name: EMAILS_QUEUE_NAME }),
|
BullModule.registerQueue({ name: EMAILS_QUEUE_NAME }),
|
||||||
BullModule.registerQueue({ name: RESERVATIONS_QUEUE_NAME }),
|
BullModule.registerQueue({ name: RESERVATIONS_QUEUE_NAME }),
|
||||||
|
EmailModule,
|
||||||
],
|
],
|
||||||
providers: [WaitingListService],
|
providers: [WaitingListService],
|
||||||
exports: [WaitingListService],
|
exports: [WaitingListService],
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
import { InjectQueue, Process, Processor } from '@nestjs/bull'
|
import { InjectQueue, Process, Processor } from '@nestjs/bull'
|
||||||
import { Inject } from '@nestjs/common'
|
import { Inject } from '@nestjs/common'
|
||||||
import { Job, Queue } from 'bull'
|
import { Job, Queue } from 'bull'
|
||||||
|
import { EmailProvider } from 'src/email/provider'
|
||||||
import { ReservationsService } from 'src/reservations/service'
|
import { ReservationsService } from 'src/reservations/service'
|
||||||
|
|
||||||
import dayjs from '../common/dayjs'
|
import dayjs from '../common/dayjs'
|
||||||
|
|
@ -31,6 +32,9 @@ export class WaitingListService {
|
||||||
@Inject(ReservationsService)
|
@Inject(ReservationsService)
|
||||||
private readonly reservationsService: ReservationsService,
|
private readonly reservationsService: ReservationsService,
|
||||||
|
|
||||||
|
@Inject(EmailProvider)
|
||||||
|
private readonly emailProvider: EmailProvider,
|
||||||
|
|
||||||
@Inject(LoggerService)
|
@Inject(LoggerService)
|
||||||
private readonly loggerService: LoggerService,
|
private readonly loggerService: LoggerService,
|
||||||
) {}
|
) {}
|
||||||
|
|
@ -46,6 +50,7 @@ export class WaitingListService {
|
||||||
|
|
||||||
if (!this.isRelevantEmail) return
|
if (!this.isRelevantEmail) return
|
||||||
|
|
||||||
|
await this.emailProvider.readEmails([email])
|
||||||
await this.handleWaitingListEmail(email)
|
await this.handleWaitingListEmail(email)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue