@zaclinley/dsh-mailharbor 0.16.0 → 0.17.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +26 -0
- package/README.md +18 -18
- package/README.zh.md +1 -1
- package/lib/client.js +248 -39
- package/lib/client.js.map +3 -3
- package/lib/index.js +48 -5
- package/lib/index.js.map +2 -2
- package/package.json +1 -1
package/lib/index.js
CHANGED
|
@@ -1209,6 +1209,18 @@ var MailDatabase = class {
|
|
|
1209
1209
|
where.push("e.date >= ?");
|
|
1210
1210
|
params.push(query.since);
|
|
1211
1211
|
}
|
|
1212
|
+
if (typeof query.before === "string" && query.before !== "") {
|
|
1213
|
+
where.push("e.date < ?");
|
|
1214
|
+
params.push(query.before.length === 10 ? `${query.before} 23:59:59` : query.before);
|
|
1215
|
+
}
|
|
1216
|
+
if (typeof query.from === "string" && query.from.trim() !== "") {
|
|
1217
|
+
const needle = `%${query.from.trim().toLowerCase()}%`;
|
|
1218
|
+
where.push("(lower(e.from_addr) LIKE ? OR lower(e.from_name) LIKE ?)");
|
|
1219
|
+
params.push(needle, needle);
|
|
1220
|
+
}
|
|
1221
|
+
if (query.attachmentsOnly === true) {
|
|
1222
|
+
where.push("EXISTS (SELECT 1 FROM attachments a WHERE a.email_id = e.id)");
|
|
1223
|
+
}
|
|
1212
1224
|
if (query.unread !== void 0) {
|
|
1213
1225
|
const mids = query.unread.mids.slice(0, 500);
|
|
1214
1226
|
const ids = query.unread.ids.slice(0, 500);
|
|
@@ -2768,7 +2780,7 @@ ${conversation.trim()}
|
|
|
2768
2780
|
}
|
|
2769
2781
|
|
|
2770
2782
|
// src/host/version.ts
|
|
2771
|
-
var VERSION = "0.
|
|
2783
|
+
var VERSION = "0.17.0";
|
|
2772
2784
|
|
|
2773
2785
|
// src/host/api.ts
|
|
2774
2786
|
init_smtp();
|
|
@@ -2872,11 +2884,19 @@ function buildRouter(runtime) {
|
|
|
2872
2884
|
return { ...items, offset, limit };
|
|
2873
2885
|
}
|
|
2874
2886
|
const unreadOnly = url.searchParams.get("unread") === "1";
|
|
2887
|
+
const from = url.searchParams.get("from") ?? "";
|
|
2888
|
+
const since = url.searchParams.get("since") ?? "";
|
|
2889
|
+
const before = url.searchParams.get("before") ?? "";
|
|
2890
|
+
const attachmentsOnly = url.searchParams.get("attachment") === "1";
|
|
2875
2891
|
const page = runtime.database(account).list({
|
|
2876
2892
|
mailbox: mailbox === "" ? "all" : mailbox,
|
|
2877
2893
|
query,
|
|
2878
2894
|
offset,
|
|
2879
2895
|
limit,
|
|
2896
|
+
...from.trim() === "" ? {} : { from },
|
|
2897
|
+
...since === "" ? {} : { since },
|
|
2898
|
+
...before === "" ? {} : { before },
|
|
2899
|
+
...attachmentsOnly ? { attachmentsOnly: true } : {},
|
|
2880
2900
|
...unreadOnly ? { unread: unreadKeys(runtime, account) } : {}
|
|
2881
2901
|
});
|
|
2882
2902
|
return { ...page, items: page.items.map((item) => localSummary(runtime, account, item)) };
|
|
@@ -3107,14 +3127,26 @@ function buildRouter(runtime) {
|
|
|
3107
3127
|
const part = Number(url.searchParams.get("part") ?? 0);
|
|
3108
3128
|
const provider = runtime.provider(account);
|
|
3109
3129
|
const file2 = await provider.attachment(mailbox, uid, part);
|
|
3110
|
-
writeAttachment(
|
|
3130
|
+
writeAttachment(
|
|
3131
|
+
res,
|
|
3132
|
+
file2.filename,
|
|
3133
|
+
file2.contentType,
|
|
3134
|
+
Buffer.from(file2.dataBase64, "base64"),
|
|
3135
|
+
canPreviewInline(file2.contentType) && url.searchParams.get("inline") === "1"
|
|
3136
|
+
);
|
|
3111
3137
|
return void 0;
|
|
3112
3138
|
}
|
|
3113
3139
|
const emailId = Number(url.searchParams.get("emailId") ?? 0);
|
|
3114
3140
|
const attachmentId = Number(url.searchParams.get("attachmentId") ?? 0);
|
|
3115
3141
|
const file = runtime.database(account).attachment(emailId, attachmentId);
|
|
3116
3142
|
if (file === void 0) throw new HttpError(404, "\u9644\u4EF6\u4E0D\u5B58\u5728");
|
|
3117
|
-
writeAttachment(
|
|
3143
|
+
writeAttachment(
|
|
3144
|
+
res,
|
|
3145
|
+
file.filename,
|
|
3146
|
+
file.contentType,
|
|
3147
|
+
Buffer.from(file.data),
|
|
3148
|
+
canPreviewInline(file.contentType) && url.searchParams.get("inline") === "1"
|
|
3149
|
+
);
|
|
3118
3150
|
return void 0;
|
|
3119
3151
|
});
|
|
3120
3152
|
router.get("/drafts", ({ url }) => {
|
|
@@ -3998,13 +4030,24 @@ async function listServer(runtime, account, mailbox, query, limit, offset = 0) {
|
|
|
3998
4030
|
);
|
|
3999
4031
|
return { items, total: result.total };
|
|
4000
4032
|
}
|
|
4001
|
-
function
|
|
4033
|
+
function canPreviewInline(contentType) {
|
|
4034
|
+
const type = contentType.toLowerCase();
|
|
4035
|
+
return type.startsWith("image/") && type !== "image/svg+xml" || type === "application/pdf" || type === "text/plain" || type === "text/csv" || type === "text/markdown" || type === "application/json";
|
|
4036
|
+
}
|
|
4037
|
+
function writeAttachment(res, filename, contentType, data, inline = false) {
|
|
4002
4038
|
res.statusCode = 200;
|
|
4003
4039
|
res.setHeader("content-type", contentType);
|
|
4004
4040
|
res.setHeader("content-length", String(data.length));
|
|
4005
|
-
res.setHeader(
|
|
4041
|
+
res.setHeader(
|
|
4042
|
+
"content-disposition",
|
|
4043
|
+
`${inline ? "inline" : "attachment"}; filename*=UTF-8''${encodeURIComponent(filename)}`
|
|
4044
|
+
);
|
|
4006
4045
|
res.setHeader("cache-control", "no-store");
|
|
4007
4046
|
res.setHeader("x-content-type-options", "nosniff");
|
|
4047
|
+
res.setHeader(
|
|
4048
|
+
"content-security-policy",
|
|
4049
|
+
"sandbox; default-src 'none'; img-src 'self' data:; style-src 'unsafe-inline'"
|
|
4050
|
+
);
|
|
4008
4051
|
res.end(data);
|
|
4009
4052
|
}
|
|
4010
4053
|
function asObject(value) {
|