Changing how messages are fetched and marked as read

This commit is contained in:
Collin Duncan 2023-09-05 13:09:10 +02:00
parent 29ec45e690
commit 931a8b7f6c
No known key found for this signature in database
4 changed files with 36 additions and 14 deletions

View file

@ -15,6 +15,7 @@ export enum EmailClientStatus {
@Injectable()
export class EmailClient {
public readonly imapClient: Imap
private readonly mailboxName: string
private mailbox?: Imap.Box
private status: EmailClientStatus
@ -25,6 +26,7 @@ export class EmailClient {
@Inject(ConfigService)
private readonly configService: ConfigService,
) {
this.mailboxName = this.configService.getOrThrow<string>('EMAIL_MAILBOX')
this.imapClient = new Imap({
host: this.configService.getOrThrow('EMAIL_HOST'),
port: this.configService.get('EMAIL_PORT', 993),
@ -90,8 +92,10 @@ export class EmailClient {
)
if (newMessages > 0) {
const startingMessage = totalMessages - newMessages + 1 // starting message is inclusive
const emails = await this.fetchMails(`${startingMessage}`, '*')
const emails = await this.fetchMailsFrom(
totalMessages - (numMessages - 1),
)
this.loggerService.debug(`Fetched ${emails.length} emails`)
callback(emails)
}
}
@ -102,8 +106,7 @@ export class EmailClient {
throw new Error('Not ready to listen')
}
const mailbox = this.configService.get<string>('EMAIL_MAILBOX', 'INBOX')
this.imapClient.openBox(mailbox, (error, mailbox) => {
this.imapClient.openBox(this.mailboxName, (error, mailbox) => {
if (error) {
this.loggerService.error('Error opening mailbox', {
...error,
@ -171,17 +174,13 @@ export class EmailClient {
})
}
public async fetchMails(startingMessageId: string, endingMessageId: string) {
public async fetchMailsFrom(startingMessageSeqNo: number) {
this.loggerService.debug(
`Fetching mails ${startingMessageId}:${endingMessageId}`,
)
const fetcher = this.imapClient.fetch(
`${startingMessageId}:${endingMessageId}`,
{
bodies: '',
markSeen: true,
},
`Fetching mails starting from ${startingMessageSeqNo}`,
)
const fetcher = this.imapClient.seq.fetch(`${startingMessageSeqNo}:*`, {
bodies: '',
})
return new Promise<Email[]>((res, rej) => {
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() {
this.imapClient.on('ready', () => {
this.loggerService.debug('email client ready')

View file

@ -19,7 +19,7 @@ export class EmailProvider {
}
private async handleReceivedEmails(emails: Email[]) {
this.emailsQueue.addBulk(
await this.emailsQueue.addBulk(
emails.map((email) => ({ name: email.id, data: email })),
)
}
@ -27,4 +27,8 @@ export class EmailProvider {
public registerEmailListener() {
this.emailClient.listen((emails) => this.handleReceivedEmails(emails))
}
public async readEmails(emails: Email[]) {
await this.emailClient.markMailsSeen(emails.map((e) => e.id))
}
}

View file

@ -1,5 +1,6 @@
import { BullModule } from '@nestjs/bull'
import { Module } from '@nestjs/common'
import { EmailModule } from 'src/email/module'
import { ReservationsModule } from 'src/reservations/module'
import { EMAILS_QUEUE_NAME } from '../email/config'
@ -13,6 +14,7 @@ import { WaitingListService } from './service'
ReservationsModule,
BullModule.registerQueue({ name: EMAILS_QUEUE_NAME }),
BullModule.registerQueue({ name: RESERVATIONS_QUEUE_NAME }),
EmailModule,
],
providers: [WaitingListService],
exports: [WaitingListService],

View file

@ -1,6 +1,7 @@
import { InjectQueue, Process, Processor } from '@nestjs/bull'
import { Inject } from '@nestjs/common'
import { Job, Queue } from 'bull'
import { EmailProvider } from 'src/email/provider'
import { ReservationsService } from 'src/reservations/service'
import dayjs from '../common/dayjs'
@ -31,6 +32,9 @@ export class WaitingListService {
@Inject(ReservationsService)
private readonly reservationsService: ReservationsService,
@Inject(EmailProvider)
private readonly emailProvider: EmailProvider,
@Inject(LoggerService)
private readonly loggerService: LoggerService,
) {}
@ -46,6 +50,7 @@ export class WaitingListService {
if (!this.isRelevantEmail) return
await this.emailProvider.readEmails([email])
await this.handleWaitingListEmail(email)
}