diff options
Diffstat (limited to 'services/docker/mail-server/relay/aws/retriever.ts')
-rw-r--r-- | services/docker/mail-server/relay/aws/retriever.ts | 63 |
1 files changed, 35 insertions, 28 deletions
diff --git a/services/docker/mail-server/relay/aws/retriever.ts b/services/docker/mail-server/relay/aws/retriever.ts index 2ee5643..b81a8f6 100644 --- a/services/docker/mail-server/relay/aws/retriever.ts +++ b/services/docker/mail-server/relay/aws/retriever.ts @@ -6,16 +6,18 @@ import { S3Client, } from "@aws-sdk/client-s3"; -import { AwsContext, s3MoveObject } from "./context.ts"; -import { getLogger } from "../logger.ts"; -import { getConfig } from "../config.ts"; +import { log, warn } from "../logger.ts"; +import { getConfigValue } from "../config.ts"; +import "../util.ts"; import { Mail, MailDeliverer } from "../mail.ts"; -import { generateTimeStringForFileName } from "../util.ts"; +import { AwsContext, s3MoveObject } from "./context.ts"; + +const AWS_SES_S3_SETUP_TAG = "AMAZON_SES_SETUP_NOTIFICATION"; export class AwsMailRetriever { readonly liveMailPrefix = "mail/live/"; readonly archiveMailPrefix = "mail/archive/"; - readonly mailBucket = getConfig().getValue("awsMailBucket"); + readonly mailBucket = getConfigValue("awsMailBucket"); readonly #s3; @@ -23,11 +25,12 @@ export class AwsMailRetriever { aws: AwsContext, public readonly inboundDeliverer: MailDeliverer, ) { - const { region, credentials } = aws; - this.#s3 = new S3Client({ region, credentials }); + this.#s3 = new S3Client(aws); } async listLiveMails(): Promise<string[]> { + log("Begin to retrieve live mails."); + const listCommand = new ListObjectsV2Command({ Bucket: this.mailBucket, Prefix: this.liveMailPrefix, @@ -35,25 +38,28 @@ export class AwsMailRetriever { const res = await this.#s3.send(listCommand); if (res.Contents == null) { - getLogger().warn("Listing live mails in S3 returns null Content."); + warn("Listing live mails in S3 returns null Content."); return []; } const result: string[] = []; for (const object of res.Contents) { - if (object.Key != null) { - // TODO: check prefix consistence here. - result.push(object.Key.slice(this.liveMailPrefix.length)); - } else { - getLogger().warn( - "Listing live mails in S3 returns an object with no Key.", - ); + if (object.Key == null) { + warn("Listing live mails in S3 returns an object with no Key."); + continue; } + + if (object.Key.endsWith(AWS_SES_S3_SETUP_TAG)) continue; + + result.push(object.Key.slice(this.liveMailPrefix.length)); } return result; } async deliverS3Mail(s3Key: string) { + log(`Begin to deliver s3 mail ${s3Key}...`); + + log(`Fetching s3 mail ${s3Key}...`); const mailPath = `${this.liveMailPrefix}${s3Key}`; const command = new GetObjectCommand({ Bucket: this.mailBucket, @@ -62,29 +68,30 @@ export class AwsMailRetriever { const res = await this.#s3.send(command); if (res.Body == null) { - // TODO: Better error. - throw new Error(); + throw new Error("S3 mail returns a null body."); } const rawMail = await res.Body.transformToString(); + log(`Done fetching s3 mail ${s3Key}.`); + + log(`Delivering s3 mail ${s3Key}...`); const mail = new Mail(rawMail); await this.inboundDeliverer.deliver(mail); + log(`Done delivering s3 mail ${s3Key}.`); + const date = mail.date ?? mail.simpleParseDate(); - const dateString = date != null - ? generateTimeStringForFileName(date, true) - : "invalid-date"; - - // TODO: Continue here. - await s3MoveObject( - this.#s3, - this.mailBucket, - mailPath, - `${this.archiveMailPrefix}${dateString}/${s3Key}`, - ); + const dateString = date?.toFileNameString(true) ?? "invalid-date"; + const newPath = `${this.archiveMailPrefix}${dateString}/${s3Key}`; + + log(`Archiving s3 mail ${s3Key} to ${newPath}...`); + await s3MoveObject(this.#s3, this.mailBucket, mailPath, newPath); + log(`Done delivering s3 mail ${s3Key}...`); } async recycleLiveMails() { + log("Begin to recycle live mails..."); const mails = await this.listLiveMails(); + log(`Found ${mails.length} live mails`); for (const s3Key of mails) { await this.deliverS3Mail(s3Key); } |