Compare commits

...

6 Commits

Author SHA1 Message Date
Dream Hunter
d0ccc3ded1 v0.6.1 2024-07-22 13:09:42 +08:00
Dream Hunter
163d9451f7 feat: worker: newAddress if domain is not set, use the first domain (#358) 2024-07-22 13:05:50 +08:00
Dream Hunter
60dda7e3fe feat: add ANNOUNCEMENT (#357) 2024-07-22 13:01:38 +08:00
Dream Hunter
384eb9b041 fix: imap proxy do not support password && cleanup days translate (#356) 2024-07-19 22:40:53 +08:00
tqjason
38816cbf0f Add new workflow action and Fix cleanup bug (#355)
* Create frontend_pagefunction_deploy.yaml

* Update frontend_pagefunction_deploy.yaml

* Update cleanup_api.ts

* Update common.ts

* Update cleanup_api.ts

* Update common.ts
2024-07-19 22:34:01 +08:00
Dream Hunter
d7d1ba6b64 feat: wrangler d1 execute dev add --remote (#352) 2024-07-15 12:04:14 +08:00
17 changed files with 93 additions and 22 deletions

View File

@@ -0,0 +1,39 @@
name: Deploy Frontend with page function
on:
workflow_dispatch:
jobs:
deploy:
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Install Node.js
uses: actions/setup-node@v4
with:
node-version: 18
- uses: pnpm/action-setup@v3
name: Install pnpm
id: pnpm-install
with:
version: 8
run_install: false
- name: Deploy Frontend for ${{ github.ref_name }}
run: |
cd frontend/
pnpm install --no-frozen-lockfile
pnpm build:pages
cd ../pages/
echo '${{ secrets.PAGE_TOML }}' > wrangler.toml
pnpm install --no-frozen-lockfile
pnpm run deploy
echo "Deploying prodcution for ${{ github.ref_name }}"
env:
CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}

View File

@@ -1,6 +1,13 @@
<!-- markdownlint-disable-file MD004 MD024 MD034 MD036 --> <!-- markdownlint-disable-file MD004 MD024 MD034 MD036 -->
# CHANGE LOG # CHANGE LOG
## v0.6.1
- pages github actions && 修复清理邮件天数为 0 不生效 by @tqjason (#355)
- fix: imap proxy server 不支持 密码 by @dreamhunter2333 (#356)
- worker 新增 `ANNOUNCEMENT` 配置, 用于配置公告信息 by @dreamhunter2333 (#357)
- fix: telegram bot 新建地址默认选择第一个域名 by @dreamhunter2333 (#358)
## v0.6.0 ## v0.6.0
### Breaking Changes ### Breaking Changes
@@ -313,7 +320,7 @@ The `mails` table will be discarded, and the `raw` text of the new `mail` will b
```bash ```bash
git checkout v0.2.0 git checkout v0.2.0
cd worker cd worker
wrangler d1 execute dev --file=../db/2024-04-09-patch.sql wrangler d1 execute dev --file=../db/2024-04-09-patch.sql --remote
pnpm run deploy pnpm run deploy
cd ../frontend cd ../frontend
pnpm run deploy pnpm run deploy

View File

@@ -1,6 +1,6 @@
{ {
"name": "cloudflare_temp_email", "name": "cloudflare_temp_email",
"version": "0.6.0", "version": "0.6.1",
"private": true, "private": true,
"type": "module", "type": "module",
"scripts": { "scripts": {

View File

@@ -54,7 +54,7 @@ onMounted(async () => {
<n-config-provider :locale="localeConfig" :theme="theme"> <n-config-provider :locale="localeConfig" :theme="theme">
<n-global-style /> <n-global-style />
<n-spin description="loading..." :show="loading"> <n-spin description="loading..." :show="loading">
<n-message-provider> <n-message-provider container-style="margin-top: 20px;">
<n-grid x-gap="12" :cols="12"> <n-grid x-gap="12" :cols="12">
<n-gi v-if="showSideMargin" span="1"></n-gi> <n-gi v-if="showSideMargin" span="1"></n-gi>
<n-gi :span="!showSideMargin ? 12 : 10"> <n-gi :span="!showSideMargin ? 12 : 10">

View File

@@ -4,7 +4,7 @@ import axios from 'axios'
const API_BASE = import.meta.env.VITE_API_BASE || ""; const API_BASE = import.meta.env.VITE_API_BASE || "";
const { const {
loading, auth, jwt, settings, openSettings, loading, auth, jwt, settings, openSettings,
userOpenSettings, userSettings, userOpenSettings, userSettings, announcement,
showAuth, adminAuth, showAdminAuth, userJwt showAuth, adminAuth, showAdminAuth, userJwt
} = useGlobalState(); } = useGlobalState();
@@ -56,6 +56,7 @@ const getOpenSettings = async (message) => {
const res = await api.fetch("/open_api/settings"); const res = await api.fetch("/open_api/settings");
const domainLabels = res["domainLabels"] || []; const domainLabels = res["domainLabels"] || [];
Object.assign(openSettings.value, { Object.assign(openSettings.value, {
...res,
title: res["title"] || "", title: res["title"] || "",
prefix: res["prefix"] || "", prefix: res["prefix"] || "",
minAddressLen: res["minAddressLen"] || 1, minAddressLen: res["minAddressLen"] || 1,
@@ -81,6 +82,14 @@ const getOpenSettings = async (message) => {
if (openSettings.value.needAuth) { if (openSettings.value.needAuth) {
showAuth.value = true; showAuth.value = true;
} }
if (openSettings.value.announcement && openSettings.value.announcement != announcement.value) {
announcement.value = openSettings.value.announcement;
message.info(announcement.value, {
showIcon: false,
duration: 0,
closable: true
});
}
} catch (error) { } catch (error) {
message.error(error.message || "error"); message.error(error.message || "error");
} }

View File

@@ -1,13 +1,15 @@
import { ref } from "vue"; import { ref } from "vue";
import { createGlobalState, useStorage, useDark, useToggle } from '@vueuse/core' import { createGlobalState, useStorage, useDark, useToggle, useLocalStorage } from '@vueuse/core'
export const useGlobalState = createGlobalState( export const useGlobalState = createGlobalState(
() => { () => {
const isDark = useDark() const isDark = useDark()
const toggleDark = useToggle(isDark) const toggleDark = useToggle(isDark)
const loading = ref(false); const loading = ref(false);
const announcement = useLocalStorage('announcement', '');
const openSettings = ref({ const openSettings = ref({
title: '', title: '',
announcement: '',
prefix: '', prefix: '',
needAuth: false, needAuth: false,
adminContact: '', adminContact: '',
@@ -83,6 +85,7 @@ export const useGlobalState = createGlobalState(
loading, loading,
settings, settings,
sendMailModel, sendMailModel,
announcement,
openSettings, openSettings,
showAuth, showAuth,
showAddressCredential, showAddressCredential,

View File

@@ -22,10 +22,10 @@ const cleanupModel = ref({
const { t } = useI18n({ const { t } = useI18n({
messages: { messages: {
en: { en: {
tip: 'Please input the cleanup days', tip: 'Please input the days',
mailBoxLabel: 'Clean up days for mailbox', mailBoxLabel: 'Cleanup the inbox before n days',
mailUnknowLabel: "Clean up days for unknow receiver", mailUnknowLabel: "Cleanup the unknow mail before n days",
sendBoxLabel: "Clean up days for sendbox", sendBoxLabel: "Cleanup the sendbox before n days",
cleanupNow: "Cleanup now", cleanupNow: "Cleanup now",
autoCleanup: "Auto cleanup", autoCleanup: "Auto cleanup",
cleanupSuccess: "Cleanup success", cleanupSuccess: "Cleanup success",
@@ -33,10 +33,10 @@ const { t } = useI18n({
cronTip: "Enable cron cleanup, need to configure [crons] in worker, please refer to the document", cronTip: "Enable cron cleanup, need to configure [crons] in worker, please refer to the document",
}, },
zh: { zh: {
tip: '请输入清理天数', tip: '请输入天数',
mailBoxLabel: '收件箱清理天数', mailBoxLabel: '清理 n 天前的收件箱',
mailUnknowLabel: "无收件人邮件清理天数", mailUnknowLabel: "清理 n 天前的无收件人邮件",
sendBoxLabel: "发件箱清理天数", sendBoxLabel: "清理 n 天前的发件箱",
autoCleanup: "自动清理", autoCleanup: "自动清理",
cleanupSuccess: "清理成功", cleanupSuccess: "清理成功",
cleanupNow: "立即清理", cleanupNow: "立即清理",

View File

@@ -13,6 +13,7 @@ class Settings(BaseSettings):
proxy_url: str = "http://localhost:8787" proxy_url: str = "http://localhost:8787"
port: int = 8025 port: int = 8025
imap_port: int = 11143 imap_port: int = 11143
basic_password: str = ""
class Config: class Config:
env_file = ".env" env_file = ".env"

View File

@@ -121,6 +121,7 @@ class SimpleMailbox:
f"{settings.proxy_url}/api/mails?limit={limit}&offset={start - 1}", f"{settings.proxy_url}/api/mails?limit={limit}&offset={start - 1}",
headers={ headers={
"Authorization": f"Bearer {self.password}", "Authorization": f"Bearer {self.password}",
"x-custom-auth": f"{settings.basic_password}",
"Content-Type": "application/json" "Content-Type": "application/json"
} }
) )
@@ -147,6 +148,7 @@ class SimpleMailbox:
f"{settings.proxy_url}/api/sendbox?limit={limit}&offset={start - 1}", f"{settings.proxy_url}/api/sendbox?limit={limit}&offset={start - 1}",
headers={ headers={
"Authorization": f"Bearer {self.password}", "Authorization": f"Bearer {self.password}",
"x-custom-auth": f"{settings.basic_password}",
"Content-Type": "application/json" "Content-Type": "application/json"
} }
) )

View File

@@ -34,10 +34,10 @@ git clone https://github.com/dreamhunter2333/cloudflare_temp_email.git
```bash ```bash
# create a database, and copy the output to wrangler.toml in the next step # create a database, and copy the output to wrangler.toml in the next step
wrangler d1 create dev wrangler d1 create dev
wrangler d1 execute dev --file=db/schema.sql wrangler d1 execute dev --file=db/schema.sql --remote
# schema update, if you have initialized the database before this date, you can execute this command to update # schema update, if you have initialized the database before this date, you can execute this command to update
# wrangler d1 execute dev --file=db/2024-01-13-patch.sql # wrangler d1 execute dev --file=db/2024-01-13-patch.sql --remote
# wrangler d1 execute dev --file=db/2024-04-03-patch.sql # wrangler d1 execute dev --file=db/2024-04-03-patch.sql --remote
# create a namespace, and copy the output to wrangler.toml in the next step # create a namespace, and copy the output to wrangler.toml in the next step
wrangler kv:namespace create DEV wrangler kv:namespace create DEV
``` ```
@@ -77,6 +77,7 @@ node_compat = true
# TITLE = "Custom Title" # The title of the site # TITLE = "Custom Title" # The title of the site
PREFIX = "tmp" # The mailbox name prefix to be processed PREFIX = "tmp" # The mailbox name prefix to be processed
# (min, max) length of the adderss, if not set, the default is (1, 30) # (min, max) length of the adderss, if not set, the default is (1, 30)
# ANNOUNCEMENT = "Custom Announcement"
# MIN_ADDRESS_LEN = 1 # MIN_ADDRESS_LEN = 1
# MAX_ADDRESS_LEN = 30 # MAX_ADDRESS_LEN = 30
# If you want your site to be private, uncomment below and change your password # If you want your site to be private, uncomment below and change your password

View File

@@ -9,7 +9,7 @@ cd worker
cp wrangler.toml.template wrangler.toml cp wrangler.toml.template wrangler.toml
# 创建 D1 并执行 schema.sql # 创建 D1 并执行 schema.sql
wrangler d1 create dev wrangler d1 create dev
wrangler d1 execute dev --file=../db/schema.sql wrangler d1 execute dev --file=../db/schema.sql --remote
``` ```
创建完成后,我们在 cloudflare 的控制台可以看到 D1 数据库 创建完成后,我们在 cloudflare 的控制台可以看到 D1 数据库
@@ -25,6 +25,6 @@ wrangler d1 execute dev --file=../db/schema.sql
```bash ```bash
cd worker cd worker
wrangler d1 execute dev --file=../db/2024-01-13-patch.sql wrangler d1 execute dev --file=../db/2024-01-13-patch.sql --remote
wrangler d1 execute dev --file=../db/2024-04-03-patch.sql wrangler d1 execute dev --file=../db/2024-04-03-patch.sql --remote
``` ```

View File

@@ -45,6 +45,7 @@ node_compat = true
# TITLE = "Custom Title" # 自定义网站标题 # TITLE = "Custom Title" # 自定义网站标题
PREFIX = "tmp" # 要处理的邮箱名称前缀,不需要后缀可配置为空字符串 PREFIX = "tmp" # 要处理的邮箱名称前缀,不需要后缀可配置为空字符串
# (min, max) adderss的长度如果不设置默认为(1, 30) # (min, max) adderss的长度如果不设置默认为(1, 30)
# ANNOUNCEMENT = "Custom Announcement" # 自定义公告
# MIN_ADDRESS_LEN = 1 # MIN_ADDRESS_LEN = 1
# MAX_ADDRESS_LEN = 30 # MAX_ADDRESS_LEN = 30
# 如果你想要你的网站私有,取消下面的注释,并修改密码 # 如果你想要你的网站私有,取消下面的注释,并修改密码

View File

@@ -1,6 +1,6 @@
import { Hono } from 'hono' import { Hono } from 'hono'
import { getDomains, getPasswords, getBooleanValue, getIntValue, getStringArray, getDefaultDomains } from './utils'; import { getDomains, getPasswords, getBooleanValue, getIntValue, getStringArray, getDefaultDomains, getStringValue } from './utils';
import { CONSTANTS } from './constants'; import { CONSTANTS } from './constants';
import { HonoCustomType } from './types'; import { HonoCustomType } from './types';
import { isS3Enabled } from './mails_api/s3_attachment'; import { isS3Enabled } from './mails_api/s3_attachment';
@@ -17,6 +17,7 @@ api.get('/open_api/settings', async (c) => {
} }
return c.json({ return c.json({
"title": c.env.TITLE, "title": c.env.TITLE,
"announcement": getStringValue(c.env.ANNOUNCEMENT),
"prefix": c.env.PREFIX, "prefix": c.env.PREFIX,
"minAddressLen": getIntValue(c.env.MIN_ADDRESS_LEN, 1), "minAddressLen": getIntValue(c.env.MIN_ADDRESS_LEN, 1),
"maxAddressLen": getIntValue(c.env.MAX_ADDRESS_LEN, 30), "maxAddressLen": getIntValue(c.env.MAX_ADDRESS_LEN, 30),

View File

@@ -40,6 +40,11 @@ export const newAddress = async (
} }
// check domain // check domain
const allowDomains = checkAllowDomains ? await getAllowDomains(c) : getDomains(c); const allowDomains = checkAllowDomains ? await getAllowDomains(c) : getDomains(c);
// if domain is not set, use the first domain
if (!domain && allowDomains.length > 0) {
domain = allowDomains[0];
}
// check domain is valid
if (!domain || !allowDomains.includes(domain)) { if (!domain || !allowDomains.includes(domain)) {
throw new Error("Invalid domain") throw new Error("Invalid domain")
} }
@@ -78,7 +83,7 @@ export const cleanup = async (
cleanType: string | undefined | null, cleanType: string | undefined | null,
cleanDays: number | undefined | null cleanDays: number | undefined | null
): Promise<boolean> => { ): Promise<boolean> => {
if (!cleanType || !cleanDays || cleanDays < 0 || cleanDays > 30) { if (!cleanType || typeof cleanDays !== 'number' || cleanDays < 0 || cleanDays > 30) {
throw new Error("Invalid cleanType or cleanDays") throw new Error("Invalid cleanType or cleanDays")
} }
console.log(`Cleanup ${cleanType} before ${cleanDays} days`); console.log(`Cleanup ${cleanType} before ${cleanDays} days`);

View File

@@ -1,5 +1,5 @@
export const CONSTANTS = { export const CONSTANTS = {
VERSION: 'v0.6.0', VERSION: 'v0.6.1',
// DB settings // DB settings
ADDRESS_BLOCK_LIST_KEY: 'address_block_list', ADDRESS_BLOCK_LIST_KEY: 'address_block_list',

View File

@@ -13,6 +13,7 @@ export type Bindings = {
// config // config
TITLE: string | undefined TITLE: string | undefined
ANNOUNCEMENT: string | undefined | null
PREFIX: string | undefined PREFIX: string | undefined
MIN_ADDRESS_LEN: string | number | undefined MIN_ADDRESS_LEN: string | number | undefined
MAX_ADDRESS_LEN: string | number | undefined MAX_ADDRESS_LEN: string | number | undefined

View File

@@ -17,6 +17,7 @@ node_compat = true
[vars] [vars]
# TITLE = "Custom Title" # custom title # TITLE = "Custom Title" # custom title
# ANNOUNCEMENT = "Custom Announcement"
PREFIX = "tmp" PREFIX = "tmp"
# (min, max) length of the adderss, if not set, the default is (1, 30) # (min, max) length of the adderss, if not set, the default is (1, 30)
# MIN_ADDRESS_LEN = 1 # MIN_ADDRESS_LEN = 1