You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

129 lines
3.7 KiB

This file contains invisible Unicode characters!

This file contains invisible Unicode characters that may be processed differently from what appears below. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to reveal hidden characters.

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

/**
* �docx/邮件/邮件3 主题注入本地库并�ParsePipeline(主�only,无正文/附件)�
* 用法: pnpm sample:mail3
*
* 完整样例(å<CB86>«å<C2AB>¡è½¬æµ?PDF 入库)请用:pnpm sample:mails
*/
import { createHash } from "crypto";
import { prisma } from "@/services/db";
import { ParsePipeline } from "@/services/parse/pipeline";
const MAIL3_SUBJECT =
"Fw: 转å<C2AC>‘:派é€<C3A9>è¦<C3A8>求更æ–? 拆柜清å<E280A6>•æ›´æ–°ï¼?DO请查æ”?拆柜清å<E280A6>•æ›´æ–°: WHSU5574991+WHL063G550810+船å<C2B9><C3A5>航次:OOCL SINGAPORE / 065W+ETAï¼?/28+FedEx-29ä»?UPS-102ä»?亚马逊å<C5A0>¡æ´?289ä»?ç§<C3A7>人地å<C2B0>€-166ä»?拦截-209ä»?拆柜清å<E280A6>•";
const MAIL3_BODY = [
"æ´¾é€<C3A9>è¦<C3A8>求更新,请查æ”?DO 与拆柜清å<E280A6>•ã€?,
"柜å<EFBFBD>·ï¼šWHSU5574991",
"æ<EFBFBD><EFBFBD>å<EFBFBD>•:WHL063G550810",
"船å<EFBFBD><EFBFBD>航次:OOCL SINGAPORE / 065W",
"ETAï¼?026-06-28",
].join("\n");
const MESSAGE_ID = "<sample-mail3-whsu5574991@local.test>";
const FROM_ADDR = "clx@cnwally.com.cn";
async function main() {
const rawHash = createHash("sha256")
.update(`mail3|${MAIL3_SUBJECT}|${MAIL3_BODY}|v2`)
.digest("hex");
const existing = await prisma.mailMessage.findFirst({
where: {
OR: [{ messageId: MESSAGE_ID }, { rawHash }],
},
});
let mailId: bigint;
if (existing) {
await prisma.containerImport.deleteMany({ where: { mailId: existing.id } });
await prisma.parseResult.deleteMany({ where: { mailId: existing.id } });
await prisma.mailAttachment.deleteMany({ where: { mailId: existing.id } });
await prisma.mailMessage.update({
where: { id: existing.id },
data: {
subject: MAIL3_SUBJECT.slice(0, 512),
fromAddr: FROM_ADDR,
bodyText: MAIL3_BODY,
ocrText: null,
status: "FETCHED",
mailType: "UNKNOWN",
lastError: null,
typeEvidence: {
sample_dir: "docx/é‚®ä»/é‚®ä»3",
note: "subject_only_ingest",
},
receivedAt: new Date("2026-07-14T08:02:00.000Z"),
version: { increment: 1 },
},
});
mailId = existing.id;
console.log(`updated existing mail id=${mailId}`);
} else {
const created = await prisma.mailMessage.create({
data: {
messageId: MESSAGE_ID,
subject: MAIL3_SUBJECT.slice(0, 512),
fromAddr: FROM_ADDR,
bodyText: MAIL3_BODY,
status: "FETCHED",
mailType: "UNKNOWN",
rawHash,
folder: "INBOX",
receivedAt: new Date("2026-07-14T08:02:00.000Z"),
isThreadRoot: true,
typeEvidence: {
sample_dir: "docx/é‚®ä»/é‚®ä»3",
note: "subject_body_ingest",
},
},
});
mailId = created.id;
console.log(`created mail id=${mailId}`);
}
await ParsePipeline.run(mailId);
const mail = await prisma.mailMessage.findUnique({
where: { id: mailId },
include: { parseResult: true },
});
const header = mail?.parseResult?.containerHeader as {
F_ContainerNo?: string;
F_BLCopyCode?: string;
F_ETA?: string;
F_Instruction?: string;
} | null;
const lineage = mail?.parseResult?.lineage as {
mail_record?: { kind?: string; summary?: string };
} | null;
console.log(
JSON.stringify(
{
id: String(mailId),
status: mail?.status,
mail_type: mail?.mailType,
container_no: header?.F_ContainerNo,
bl: header?.F_BLCopyCode,
eta: header?.F_ETA,
instruction: header?.F_Instruction,
mail_record_kind: lineage?.mail_record?.kind,
summary: lineage?.mail_record?.summary,
url: `http://localhost:3100/mails/${mailId}`,
},
null,
2,
),
);
}
main()
.catch((err) => {
console.error(err);
process.exitCode = 1;
})
.finally(async () => {
await prisma.$disconnect();
});