aboutsummaryrefslogtreecommitdiff
path: root/deno/mail/mail.ts
diff options
context:
space:
mode:
Diffstat (limited to 'deno/mail/mail.ts')
-rw-r--r--deno/mail/mail.ts76
1 files changed, 73 insertions, 3 deletions
diff --git a/deno/mail/mail.ts b/deno/mail/mail.ts
index 9cc591c..b88ce2b 100644
--- a/deno/mail/mail.ts
+++ b/deno/mail/mail.ts
@@ -1,5 +1,8 @@
import { encodeBase64 } from "@std/encoding/base64";
import { parse } from "@std/csv/parse";
+
+import { StringUtils } from "@crupest/base";
+
import { simpleParseMail } from "./mail-parsing.ts";
export class Mail {
@@ -47,7 +50,9 @@ export interface MailDeliverRecipientResult {
export class MailDeliverResult {
message?: string;
- smtpMessage?: string;
+ messageForSmtp?: string;
+ newMessageId?: string;
+
recipients = new Map<string, MailDeliverRecipientResult>();
constructor(public mail: Mail) {}
@@ -58,8 +63,8 @@ export class MailDeliverResult {
generateLogMessage(prefix: string) {
const lines = [];
if (this.message != null) lines.push(`${prefix} message: ${this.message}`);
- if (this.smtpMessage != null) {
- lines.push(`${prefix} smtpMessage: ${this.smtpMessage}`);
+ if (this.messageForSmtp != null) {
+ lines.push(`${prefix} smtpMessage: ${this.messageForSmtp}`);
}
for (const [name, result] of this.recipients.entries()) {
const { kind, message } = result;
@@ -67,6 +72,13 @@ export class MailDeliverResult {
}
return lines.join("\n");
}
+
+ generateMessageForSmtp(): string {
+ if (this.messageForSmtp != null) return this.messageForSmtp;
+ return `2.0.0 OK${
+ StringUtils.prependNonEmpty(this.newMessageId)
+ } Message accepted for delivery`;
+ }
}
export class MailDeliverContext {
@@ -232,3 +244,61 @@ export class AliasRecipientMailHook implements MailDeliverHook {
}
}
}
+
+export class MessageIdRewriteHook implements MailDeliverHook {
+ readonly #lookup;
+
+ constructor(lookup: (origin: string) => Promise<string | null>) {
+ this.#lookup = lookup;
+ }
+
+ async callback(context: MailDeliverContext): Promise<void> {
+ const addresses = context.mail.simpleFindAllAddresses();
+ for (const address of addresses) {
+ const newMessageId = await this.#lookup(address);
+ if (newMessageId != null && newMessageId.length !== 0) {
+ console.info(
+ context.logTag,
+ `Rewrite address-line string in mail: ${address} => ${newMessageId}.`,
+ );
+ context.mail.raw = context.mail.raw.replaceAll(address, newMessageId);
+ }
+ }
+ }
+}
+
+export class MessageIdSaveHook implements MailDeliverHook {
+ readonly #record;
+
+ constructor(
+ record: (
+ original: string,
+ newMessageId: string,
+ context: MailDeliverContext,
+ ) => Promise<void>,
+ ) {
+ this.#record = record;
+ }
+
+ async callback(context: MailDeliverContext): Promise<void> {
+ const { messageId } = context.mail.parsed;
+ if (messageId == null) {
+ console.warn(
+ context.logTag,
+ "Original mail doesn't have message id, skip saving message id map.",
+ );
+ return;
+ }
+ if (context.result.newMessageId != null) {
+ console.info(
+ context.logTag,
+ `Save message id map: ${messageId} => ${context.result.newMessageId}.`,
+ );
+ context.mail.raw = context.mail.raw.replaceAll(
+ messageId,
+ context.result.newMessageId,
+ );
+ await this.#record(messageId, context.result.newMessageId, context);
+ }
+ }
+}