diff --git a/frontend/src/views/MailBox.vue b/frontend/src/views/MailBox.vue
index 47b297e4..b2ba5b5e 100644
--- a/frontend/src/views/MailBox.vue
+++ b/frontend/src/views/MailBox.vue
@@ -32,14 +32,18 @@ const { t } = useI18n({
refresh: 'Refresh',
attachments: 'Show Attachments',
downloadMail: 'Download Mail',
- pleaseSelectMail: "Please select a mail to view."
+ pleaseSelectMail: "Please select a mail to view.",
+ delete: 'Delete',
+ deleteMailTip: 'Are you sure you want to delete this mail?'
},
zh: {
autoRefresh: '自动刷新',
refresh: '刷新',
downloadMail: '下载邮件',
attachments: '查看附件',
- pleaseSelectMail: "请选择一封邮件查看。"
+ pleaseSelectMail: "请选择一封邮件查看。",
+ delete: '删除',
+ deleteMailTip: '确定要删除这封邮件吗?'
}
}
});
@@ -100,6 +104,19 @@ const mailItemClass = (row) => {
return curMail.value && row.id == curMail.value.id ? (themeSwitch.value ? 'overlay overlay-dark-backgroud' : 'overlay overlay-light-backgroud') : '';
};
+const deleteMail = async () => {
+ try {
+ await api.fetch(`/api/mails/${curMail.value.id}`, {
+ method: 'DELETE'
+ });
+ message.success(t("success"));
+ curMail.value = null;
+ await refresh();
+ } catch (error) {
+ message.error(error.message || "error");
+ }
+};
+
onMounted(async () => {
await refresh();
});
@@ -158,6 +175,12 @@ onMounted(async () => {
FROM: {{ curMail.source }}
+
+
+ {{ t('delete') }}
+
+ {{ t('deleteMailTip') }}
+
{{ t('attachments') }}
diff --git a/frontend/src/views/admin/MailsUnknow.vue b/frontend/src/views/admin/MailsUnknow.vue
index 11f6c8fc..ff628ed7 100644
--- a/frontend/src/views/admin/MailsUnknow.vue
+++ b/frontend/src/views/admin/MailsUnknow.vue
@@ -86,6 +86,9 @@ onMounted(async () => {
ID: {{ row.id }}
+
+ TO: {{ row.address }}
+
diff --git a/frontend/src/views/admin/SenderAccess.vue b/frontend/src/views/admin/SenderAccess.vue
index 71e359c7..a88d876d 100644
--- a/frontend/src/views/admin/SenderAccess.vue
+++ b/frontend/src/views/admin/SenderAccess.vue
@@ -57,6 +57,7 @@ const updateData = async () => {
await api.fetch(`/admin/address_sender`, {
method: 'POST',
body: JSON.stringify({
+ address: curRow.value.address,
address_id: curRow.value.id,
balance: senderBalance.value,
enabled: senderEnabled.value ? 1 : 0
diff --git a/vitepress-docs/docs/en/index.md b/vitepress-docs/docs/en/index.md
index 76dcde17..b9763491 100644
--- a/vitepress-docs/docs/en/index.md
+++ b/vitepress-docs/docs/en/index.md
@@ -20,5 +20,5 @@ features:
- title: Use rust wasm to parse emails
details: Use rust wasm to parse emails, support various RFC standards for emails, support attachments, extremely fast
- title: Support sending emails
- details: Support sending txt or html emails through domain name mailboxes
+ details: Support sending txt or html emails through domain name mailboxes,Support DKIM signature
---
diff --git a/vitepress-docs/docs/index.md b/vitepress-docs/docs/index.md
index a577cfdc..4613bfe5 100644
--- a/vitepress-docs/docs/index.md
+++ b/vitepress-docs/docs/index.md
@@ -24,5 +24,5 @@ features:
- title: 使用 rust wasm 解析邮件
details: 使用 rust wasm 解析邮件,支持邮件各种RFC标准,支持附件, 速度极快
- title: 支持发送邮件
- details: 支持通过域名邮箱发送 txt 或者 html 邮件
+ details: 支持通过域名邮箱发送 txt 或者 html 邮件,支持 DKIM 签名
---
diff --git a/worker/src/admin_api.js b/worker/src/admin_api.js
index 42ddd543..5c3ff190 100644
--- a/worker/src/admin_api.js
+++ b/worker/src/admin_api.js
@@ -1,6 +1,7 @@
import { Hono } from 'hono'
import { Jwt } from 'hono/utils/jwt'
import { getSendbox } from './send_mail_api'
+import { sendAdminInternalMail } from './utils'
const api = new Hono()
@@ -164,7 +165,7 @@ api.get('/admin/address_sender', async (c) => {
})
api.post('/admin/address_sender', async (c) => {
- let { address_id, balance, enabled } = await c.req.json();
+ let { address, address_id, balance, enabled } = await c.req.json();
if (!address_id) {
return c.text("Invalid address_id", 400)
}
@@ -175,6 +176,10 @@ api.post('/admin/address_sender', async (c) => {
if (!success) {
return c.text("Failed to update address sender", 500)
}
+ await sendAdminInternalMail(
+ c, address, "Account Send Access Updated",
+ `You send access has been ${enabled ? "enabled" : "disabled"}, balance: ${balance}`
+ );
return c.json({
success: success
})
diff --git a/worker/src/router.js b/worker/src/router.js
index c310ce82..77a435f1 100644
--- a/worker/src/router.js
+++ b/worker/src/router.js
@@ -33,6 +33,17 @@ api.get('/api/mails', async (c) => {
})
})
+api.delete('/api/mails/:id', async (c) => {
+ const { address } = c.get("jwtPayload")
+ const { id } = c.req.param();
+ const { success } = await c.env.DB.prepare(
+ `DELETE FROM raw_mails WHERE address = ? and id = ?`
+ ).bind(address, id).run();
+ return c.json({
+ success: success
+ })
+})
+
api.get('/api/settings', async (c) => {
const { address, address_id } = c.get("jwtPayload")
if (address_id && address_id > 0) {
diff --git a/worker/src/utils.js b/worker/src/utils.js
index 624e9502..87e28153 100644
--- a/worker/src/utils.js
+++ b/worker/src/utils.js
@@ -1,3 +1,5 @@
+import { createMimeMessage } from "mimetext";
+
export const getDomains = (c) => {
if (!c.env.DOMAINS) {
return [];
@@ -45,3 +47,33 @@ export const getAdminPasswords = (c) => {
}
return c.env.ADMIN_PASSWORDS;
}
+
+export const sendAdminInternalMail = async (c, toMail, subject, text) => {
+ try {
+
+ const msg = createMimeMessage();
+ msg.setSender({
+ name: "Admin",
+ addr: "admin@internal"
+ });
+ msg.setRecipient(toMail);
+ msg.setSubject(subject);
+ msg.addMessage({
+ contentType: 'text/plain',
+ data: text
+ });
+ const message_id = Math.random().toString(36).substring(2, 15);
+ const { success } = await c.env.DB.prepare(
+ `INSERT INTO raw_mails (source, address, raw, message_id) VALUES (?, ?, ?, ?)`
+ ).bind(
+ "admin@internal", toMail, msg.asRaw(), message_id
+ ).run();
+ if (!success) {
+ console.log(`Failed save message from admin@internal to ${toMail}`);
+ }
+ return success;
+ } catch (error) {
+ console.log("sendAdminInternalMail error", error);
+ return false;
+ }
+};