diff --git a/frontend/src/views/index/TelegramAddress.vue b/frontend/src/views/index/TelegramAddress.vue
index ee736969..fdcc15c1 100644
--- a/frontend/src/views/index/TelegramAddress.vue
+++ b/frontend/src/views/index/TelegramAddress.vue
@@ -148,7 +148,7 @@ onMounted(async () => {
-
+
diff --git a/frontend/src/views/index/Webhook.vue b/frontend/src/views/index/Webhook.vue
index 7e61f251..77117ed9 100644
--- a/frontend/src/views/index/Webhook.vue
+++ b/frontend/src/views/index/Webhook.vue
@@ -89,7 +89,7 @@ onMounted(async () => {
-
+
diff --git a/frontend/src/views/telegram/Mail.vue b/frontend/src/views/telegram/Mail.vue
index 196b44a4..14d0a8bd 100644
--- a/frontend/src/views/telegram/Mail.vue
+++ b/frontend/src/views/telegram/Mail.vue
@@ -41,7 +41,7 @@ onMounted(async () => {
-
+
ID: {{ curMail.id }}
diff --git a/frontend/src/views/user/AddressManagement.vue b/frontend/src/views/user/AddressManagement.vue
index c5e70a20..d0b361df 100644
--- a/frontend/src/views/user/AddressManagement.vue
+++ b/frontend/src/views/user/AddressManagement.vue
@@ -165,6 +165,6 @@ onMounted(async () => {
-
+
diff --git a/frontend/src/views/user/BindAddress.vue b/frontend/src/views/user/BindAddress.vue
index b4cd94c0..42a1d57a 100644
--- a/frontend/src/views/user/BindAddress.vue
+++ b/frontend/src/views/user/BindAddress.vue
@@ -29,7 +29,7 @@ onMounted(async () => {
-
+
diff --git a/frontend/src/views/user/UserBar.vue b/frontend/src/views/user/UserBar.vue
index c3a29e54..e4663c00 100644
--- a/frontend/src/views/user/UserBar.vue
+++ b/frontend/src/views/user/UserBar.vue
@@ -37,19 +37,19 @@ onMounted(async () => {
-
+
-
+
{{ t('currentUser') }} {{ userSettings.user_email }}
-
-
+
+
{{ t('fetchUserSettingsError') }}
diff --git a/frontend/src/views/user/UserLogin.vue b/frontend/src/views/user/UserLogin.vue
index e12a7e4c..60c0665d 100644
--- a/frontend/src/views/user/UserLogin.vue
+++ b/frontend/src/views/user/UserLogin.vue
@@ -228,7 +228,7 @@ onMounted(async () => {
{{ t('resetPassword') }}
-
+
{{ t('cannotForgotPassword') }}
diff --git a/frontend/src/views/user/UserSettings.vue b/frontend/src/views/user/UserSettings.vue
index 353c2188..beecc81e 100644
--- a/frontend/src/views/user/UserSettings.vue
+++ b/frontend/src/views/user/UserSettings.vue
@@ -43,8 +43,8 @@ onMounted(async () => {
-
-
+
+
{{ t('passordTip') }}
diff --git a/vitepress-docs/docs/.vitepress/zh.ts b/vitepress-docs/docs/.vitepress/zh.ts
index bee25f39..156bf505 100644
--- a/vitepress-docs/docs/.vitepress/zh.ts
+++ b/vitepress-docs/docs/.vitepress/zh.ts
@@ -100,7 +100,6 @@ function sidebarGuide(): DefaultTheme.SidebarItem[] {
items: [
{ text: '命令行部署准备', link: 'cli/pre-requisite' },
{ text: 'D1 数据库', link: 'cli/d1' },
- { text: '配置 DKIM', link: 'dkim' },
{ text: 'Cloudflare workers 后端', link: 'cli/worker' },
{ text: '配置邮件转发', link: 'email-routing.md' },
{ text: 'Cloudflare Pages 前端', link: 'cli/pages' },
@@ -112,7 +111,6 @@ function sidebarGuide(): DefaultTheme.SidebarItem[] {
collapsed: true,
items: [
{ text: 'D1 数据库', link: 'ui/d1' },
- { text: '配置 DKIM', link: 'dkim' },
{ text: 'Cloudflare workers 后端', link: 'ui/worker' },
{ text: '配置邮件转发', link: 'email-routing.md' },
{ text: 'Cloudflare Pages 前端', link: 'ui/pages' },
diff --git a/vitepress-docs/docs/en/cli.md b/vitepress-docs/docs/en/cli.md
index ffa5c4e0..fc7824c6 100644
--- a/vitepress-docs/docs/en/cli.md
+++ b/vitepress-docs/docs/en/cli.md
@@ -105,9 +105,6 @@ ENABLE_AUTO_REPLY = false
# Turnstile verification configuration
# CF_TURNSTILE_SITE_KEY = ""
# CF_TURNSTILE_SECRET_KEY = ""
-# dkim config
-# DKIM_SELECTOR = "mailchannels" # Refer to the DKIM section mailchannels._domainkey for mailchannels
-# DKIM_PRIVATE_KEY = "" # Refer to the contents of priv_key.txt in the DKIM section
# telegram bot
# TG_MAX_ACCOUNTS = 5
# global forward address list, if set, all emails will be forwarded to these addresses
@@ -159,39 +156,3 @@ pnpm run deploy
```

-
-## Configure sending emails
-
-Find the `SPF` record of `TXT` in the domain name `DNS` record, and add `include:relay.mailchannels.net`
-
-```bash
-v=spf1 include:_spf.mx.cloudflare.net include:relay.mailchannels.net ~all
-```
-
-Create a new `_mailchannels` record, the type is `TXT`, the content is `v=mc1 cfid=your worker domain name`
-
-- The worker domain name here is the domain name of the back-end api. For example, if I deploy it at `https://temp-email-api.awsl.uk/`, fill in `v=mc1 cfid=awsl.uk`
-- If your domain name is `https://temp-email-api.xxx.workers.dev`, fill in `v=mc1 cfid=xxx.workers.dev`
-
-## Configure DKIM
-
-Ref: [Adding-a-DKIM-Signature](https://support.mailchannels.com/hc/en-us/articles/7122849237389-Adding-a-DKIM-Signature)
-
-Creating a DKIM private and public key:
-Private key as PEM file and base64 encoded txt file:
-
-```bash
-openssl genrsa 2048 | tee priv_key.pem | openssl rsa -outform der | openssl base64 -A > priv_key.txt
-```
-
-Public key as DNS record:
-
-```bash
-echo -n "v=DKIM1;p=" > pub_key_record.txt && \
-openssl rsa -in priv_key.pem -pubout -outform der | openssl base64 -A >> pub_key_record.txt
-```
-
-Add `TXT` record in `Cloudflare` all your mail domain `DNS`
-
-- `_dmarc`: `v=DMARC1; p=none; adkim=r; aspf=r;`
-- `mailchannels._domainkey`: `v=DKIM1; p=`
diff --git a/vitepress-docs/docs/zh/guide/cli/worker.md b/vitepress-docs/docs/zh/guide/cli/worker.md
index ad988e43..75e3cd47 100644
--- a/vitepress-docs/docs/zh/guide/cli/worker.md
+++ b/vitepress-docs/docs/zh/guide/cli/worker.md
@@ -73,9 +73,6 @@ ENABLE_AUTO_REPLY = false
# Turnstile 人机验证配置
# CF_TURNSTILE_SITE_KEY = ""
# CF_TURNSTILE_SECRET_KEY = ""
-# dkim config
-# DKIM_SELECTOR = "mailchannels" # 参考 DKIM 部分 mailchannels._domainkey 的 mailchannels
-# DKIM_PRIVATE_KEY = "" # 参考 DKIM 部分 priv_key.txt 的内容
# telegram bot 最多绑定邮箱数量
# TG_MAX_ACCOUNTS = 5
# 全局转发地址列表,如果不配置则不启用,启用后所有邮件都会转发到列表中的地址
diff --git a/vitepress-docs/docs/zh/guide/config-send-mail.md b/vitepress-docs/docs/zh/guide/config-send-mail.md
index b448179d..b82c5115 100644
--- a/vitepress-docs/docs/zh/guide/config-send-mail.md
+++ b/vitepress-docs/docs/zh/guide/config-send-mail.md
@@ -23,19 +23,3 @@ wrangler secret put RESEND_TOKEN
wrangler secret put RESEND_TOKEN_XXX_COM
wrangler secret put RESEND_TOKEN_DREAMHUNTER2333_XYZ
```
-
-## 使用 mailchannels 发送邮件
-
-::: warning
-[Mail Channels 免费电子邮件发送 API 将于2024年6月30日结束](https://support.mailchannels.com/hc/en-us/articles/26814255454093-End-of-Life-Notice-Cloudflare-Workers)
-:::
-
-1. 找到域名 `DNS` 记录的 `TXT` 的 `SPF` 记录, 增加 `include:relay.mailchannels.net`
-
- `v=spf1 include:_spf.mx.cloudflare.net include:relay.mailchannels.net ~all`
-
-2. 新建 `_mailchannels` 记录, 类型为 `TXT`, 内容为 `v=mc1 cfid=你的worker域名`
-
-- 此处 worker 域名为后端 api 的域名,比如我部署在 `https://temp-email-api.awsl.uk/`,则填写 `v=mc1 cfid=awsl.uk`
-
-- 如果你的域名是 `https://temp-email-api.xxx.workers.dev`,则填写 `v=mc1 cfid=xxx.workers.dev`
diff --git a/vitepress-docs/docs/zh/guide/dkim.md b/vitepress-docs/docs/zh/guide/dkim.md
deleted file mode 100644
index e4edbc06..00000000
--- a/vitepress-docs/docs/zh/guide/dkim.md
+++ /dev/null
@@ -1,33 +0,0 @@
-# 配置 DKIM
-
-如果你不想配置 DKIM,可以跳过这一节。
-
-参考: [Adding-a-DKIM-Signature](https://support.mailchannels.com/hc/en-us/articles/7122849237389-Adding-a-DKIM-Signature)
-
-Creating a DKIM private and public key:
-Private key as PEM file and base64 encoded txt file:
-
-```bash
-openssl genrsa 2048 | tee priv_key.pem | openssl rsa -outform der | openssl base64 -A > priv_key.txt
-```
-
-Public key as DNS record:
-
-```bash
-echo -n "v=DKIM1;p=" > pub_key_record.txt && \
-openssl rsa -in priv_key.pem -pubout -outform der | openssl base64 -A >> pub_key_record.txt
-```
-
-在 `Cloudflare` 的 `DNS` 记录中添加 `TXT` 记录
-
-例如:
-
-- `_dmarc`: `v=DMARC1; p=none; adkim=r; aspf=r;`
-- `mailchannels._domainkey`: `v=DKIM1; p=`
-
-那我在 `wrangler.toml` 中的配置应该是这样的:
-
-```toml
-DKIM_SELECTOR = "mailchannels"
-DKIM_PRIVATE_KEY = ""
-```
diff --git a/vitepress-docs/docs/zh/guide/feature/subdomain.md b/vitepress-docs/docs/zh/guide/feature/subdomain.md
index f8fb7acf..b07de2d9 100644
--- a/vitepress-docs/docs/zh/guide/feature/subdomain.md
+++ b/vitepress-docs/docs/zh/guide/feature/subdomain.md
@@ -1,5 +1,9 @@
# 配置子域名邮箱
+::: warning
+子域名邮箱发送邮件可能无法发送邮件,建议使用主域名邮箱发送邮件,子域名邮箱仅用于接收邮件。
+:::
+
参考
- [配置子域名邮箱](https://github.com/dreamhunter2333/cloudflare_temp_email/issues/164#issuecomment-2082612710)
diff --git a/worker/src/admin_api/index.ts b/worker/src/admin_api/index.ts
index 80687f65..d5199e32 100644
--- a/worker/src/admin_api/index.ts
+++ b/worker/src/admin_api/index.ts
@@ -127,6 +127,16 @@ api.get('/admin/mails_unknow', async (c) => {
);
});
+api.delete('/admin/mails/:id', async (c) => {
+ const { id } = c.req.param();
+ const { success } = await c.env.DB.prepare(
+ `DELETE FROM raw_mails WHERE id = ? `
+ ).bind(id).run();
+ return c.json({
+ success: success
+ })
+})
+
api.get('/admin/address_sender', async (c) => {
const { address, limit, offset } = c.req.query();
if (address) {
@@ -166,6 +176,16 @@ api.post('/admin/address_sender', async (c) => {
})
})
+api.delete('/admin/address_sender/:id', async (c) => {
+ const { id } = c.req.param();
+ const { success } = await c.env.DB.prepare(
+ `DELETE FROM address_sender WHERE id = ? `
+ ).bind(id).run();
+ return c.json({
+ success: success
+ })
+})
+
api.get('/admin/sendbox', async (c) => {
const { address, limit, offset } = c.req.query();
if (address) {
@@ -182,6 +202,16 @@ api.get('/admin/sendbox', async (c) => {
);
})
+api.delete('/admin/sendbox/:id', async (c) => {
+ const { id } = c.req.param();
+ const { success } = await c.env.DB.prepare(
+ `DELETE FROM sendbox WHERE id = ? `
+ ).bind(id).run();
+ return c.json({
+ success: success
+ })
+})
+
api.get('/admin/statistics', async (c) => {
const { count: mailCount } = await c.env.DB.prepare(
`SELECT count(*) as count FROM raw_mails`
diff --git a/worker/src/mails_api/send_mail_api.ts b/worker/src/mails_api/send_mail_api.ts
index b0712968..0ee56bf7 100644
--- a/worker/src/mails_api/send_mail_api.ts
+++ b/worker/src/mails_api/send_mail_api.ts
@@ -4,7 +4,7 @@ import { createMimeMessage } from 'mimetext';
import { Resend } from 'resend';
import { CONSTANTS } from '../constants'
-import { getJsonSetting, getDomains, getIntValue } from '../utils';
+import { getJsonSetting, getDomains, getIntValue, getBooleanValue } from '../utils';
import { GeoData } from '../models'
import { handleListQuery } from '../common'
import { HonoCustomType } from '../types';
@@ -89,64 +89,6 @@ const sendMailByResend = async (
console.log(`Resend success: ${JSON.stringify(data)}`);
}
-const sendMailByMailChannels = async (
- c: Context, address: string,
- reqJson: {
- from_name: string, to_mail: string, to_name: string,
- subject: string, content: string, is_html: boolean
- }
-): Promise => {
- /* eslint-disable prefer-const */
- let {
- from_name, to_mail, to_name,
- subject, content, is_html
- } = reqJson;
- /* eslint-enable prefer-const */
- from_name = from_name || address;
- to_name = to_name || to_mail;
- let dmikBody = {}
- if (c.env.DKIM_SELECTOR && c.env.DKIM_PRIVATE_KEY && address.includes("@")) {
- dmikBody = {
- "dkim_domain": address.split("@")[1],
- "dkim_selector": c.env.DKIM_SELECTOR,
- "dkim_private_key": c.env.DKIM_PRIVATE_KEY,
- }
- }
- const body = {
- "personalizations": [
- {
- "to": [{
- "email": to_mail,
- "name": to_name,
- }],
- ...dmikBody,
- }
- ],
- "from": {
- "email": address,
- "name": from_name,
- },
- "subject": subject,
- "content": [{
- "type": is_html ? "text/html" : "text/plain",
- "value": content,
- }],
- };
- const send_request = new Request("https://api.mailchannels.net/tx/v1/send", {
- "method": "POST",
- "headers": {
- "content-type": "application/json",
- },
- "body": JSON.stringify(body),
- });
- const resp = await fetch(send_request);
- const respText = await resp.text();
- console.log(resp.status + " " + resp.statusText + ": " + respText);
- if (resp.status >= 300) {
- throw new Error(`Mailchannels error: ${resp.status} ${respText}`);
- }
-}
-
export const sendMail = async (
c: Context, address: string,
reqJson: {
@@ -208,9 +150,8 @@ export const sendMail = async (
else if (resendEnabled) {
await sendMailByResend(c, address, reqJson);
}
- // send by mailchannels
else {
- await sendMailByMailChannels(c, address, reqJson);
+ throw new Error("Please enable resend or verified address list")
}
// update balance
if (!sendByVerifiedAddressList) {
@@ -292,3 +233,17 @@ api.get('/api/sendbox', async (c) => {
const { limit, offset } = c.req.query();
return getSendbox(c, address, limit, offset);
})
+
+api.delete('/api/sendbox/:id', async (c) => {
+ if (!getBooleanValue(c.env.ENABLE_USER_DELETE_EMAIL)) {
+ return c.text("User delete email is disabled", 403)
+ }
+ const { address } = c.get("jwtPayload")
+ const { id } = c.req.param();
+ const { success } = await c.env.DB.prepare(
+ `DELETE FROM sendbox WHERE address = ? and id = ? `
+ ).bind(address, id).run();
+ return c.json({
+ success: success
+ })
+})
diff --git a/worker/src/types.d.ts b/worker/src/types.d.ts
index ed54c874..b523df9f 100644
--- a/worker/src/types.d.ts
+++ b/worker/src/types.d.ts
@@ -33,10 +33,6 @@ export type Bindings = {
S3_BUCKET: string | undefined
S3_URL_EXPIRES: number | undefined
- // dkim
- DKIM_SELECTOR: string | undefined
- DKIM_PRIVATE_KEY: string | undefined
-
// cf turnstile
CF_TURNSTILE_SITE_KEY: string | undefined
CF_TURNSTILE_SECRET_KEY: string | undefined
diff --git a/worker/wrangler.toml.template b/worker/wrangler.toml.template
index f82420a9..b71a48a9 100644
--- a/worker/wrangler.toml.template
+++ b/worker/wrangler.toml.template
@@ -47,9 +47,6 @@ ENABLE_AUTO_REPLY = false
# Turnstile verification
# CF_TURNSTILE_SITE_KEY = ""
# CF_TURNSTILE_SECRET_KEY = ""
-# dkim config
-# DKIM_SELECTOR = ""
-# DKIM_PRIVATE_KEY = ""
# telegram bot
# TG_MAX_ACCOUNTS = 5
# global forward address list, if set, all emails will be forwarded to these addresses