发送邮件正文图片链接改为内置附件

This commit is contained in:
eoao
2025-11-06 22:55:00 +08:00
parent 4d00f0aeb7
commit 6cd3dcb7ef
10 changed files with 186 additions and 39 deletions

View File

@@ -1,13 +1,14 @@
import orm from '../entity/orm';
import { att } from '../entity/att';
import { and, eq, isNull, inArray } from 'drizzle-orm';
import { and, eq, isNull, inArray, desc } from 'drizzle-orm';
import r2Service from './r2-service';
import constant from '../const/constant';
import fileUtils from '../utils/file-utils';
import { attConst } from '../const/entity-const';
import { parseHTML } from 'linkedom';
import { v4 as uuidv4 } from 'uuid';
import domainUtils from '../utils/domain-uitls';
import BizError from '../error/biz-error';
import settingService from "./setting-service";
const attService = {
@@ -46,22 +47,27 @@ const attService = {
).all();
},
async toImageUrlHtml(c, content, r2Domain) {
async toImageUrlHtml(c, content) {
const { r2Domain } = await settingService.query(c);
const { document } = parseHTML(content);
const images = Array.from(document.querySelectorAll('img'));
const attDataList = [];
let imageDataList = [];
for (const img of images) {
//邮件正文base64图片转cid附件
const src = img.getAttribute('src');
if (src && src.startsWith('data:image')) {
const file = fileUtils.base64ToFile(src);
const buff = await file.arrayBuffer();
const cid = uuidv4().replace(/-/g, '');
const key = constant.ATTACHMENT_PREFIX + await fileUtils.getBuffHash(buff) + fileUtils.getExtFileName(file.name);
img.setAttribute('src', domainUtils.toOssDomain(r2Domain) + '/' + key);
img.setAttribute('src', 'cid:' + cid);
const attData = {};
attData.key = key;
@@ -69,8 +75,24 @@ const attService = {
attData.mimeType = file.type;
attData.size = file.size;
attData.buff = buff;
attData.content = fileUtils.base64ToDataStr(src);
attData.contentId = cid;
attDataList.push(attData);
imageDataList.push(attData);
}
//邮件正文站内图片转cid附件
if (src && src.startsWith(domainUtils.toOssDomain(r2Domain))) {
const cid = uuidv4().replace(/-/g, '')
img.setAttribute('src', 'cid:' + cid);
const attData = {};
attData.key = src.replace(domainUtils.toOssDomain(r2Domain) + '/','');
attData.path = src;
attData.contentId = cid;
attData.type = attConst.type.EMBED;
imageDataList.push(attData);
}
const hasInlineWidth = img.hasAttribute('width');
@@ -82,7 +104,26 @@ const attService = {
img.setAttribute('style', newStyle);
}
}
return { attDataList, html: document.toString() };
//查询已有内嵌url图片信息
const keys = [...new Set(imageDataList.filter(item => item.path).map(item => item.key))];
const dbImageList = await this.selectOneByKeys(c, keys);
//设置给当前附件
imageDataList.forEach(image => {
dbImageList.forEach(dbImage => {
if (image.path && (image.key === dbImage.key)) {
image.size = dbImage.size;
image.filename = dbImage.filename;
image.mimeType = dbImage.mimeType;
image.contentType = dbImage.mimeType;
}
})
})
imageDataList = imageDataList.filter(image => !image.path || image.size);
return { imageDataList, html: document.toString() };
},
async saveSendAtt(c, attList, userId, accountId, emailId) {
@@ -194,8 +235,14 @@ const attService = {
},
async removeByAccountId(c, accountId) {
console.log(accountId)
await this.removeAttByField(c, "account_id", [accountId])
},
selectOneByKeys(c, keys) {
if (!keys || keys.length === 0) {
return []
}
return orm(c).select().from(att).where(inArray(att.key, keys)).orderBy(desc(att.attId)).groupBy(att.key).all();
}
};