diff --git a/mail-vue/src/components/tiny-editor/index.vue b/mail-vue/src/components/tiny-editor/index.vue
index 22f2c57..68e8f2a 100644
--- a/mail-vue/src/components/tiny-editor/index.vue
+++ b/mail-vue/src/components/tiny-editor/index.vue
@@ -92,8 +92,8 @@ function initEditor() {
statusbar: false,
height: "100%",
auto_focus: true,
- relative_urls: false, //阻止 img标签域名和网站域名相同 自动把链接转换相对路径
- remove_script_host: false, // 阻止删除 URL 中的域名
+ //relative_urls: false, //阻止 img标签域名和网站域名相同 自动把链接转换相对路径
+ //remove_script_host: false, // 阻止删除 URL 中的域名
forced_root_block: 'div',
skin: `${uiStore.dark ? 'oxide-dark' : 'oxide'}`,
content_css: `/tinymce/css/index.css,${uiStore.dark ? 'dark' : 'default'}`,
diff --git a/mail-vue/src/i18n/en.js b/mail-vue/src/i18n/en.js
index afc6b18..6af00b1 100644
--- a/mail-vue/src/i18n/en.js
+++ b/mail-vue/src/i18n/en.js
@@ -150,6 +150,7 @@ const en = {
resendToken: 'Resend Token',
oss: 'Object Storage',
osDomain: 'Domain',
+ ossDomainDesc: 'Leave empty if using KV storage.',
emailPush: 'Email Push',
tgBot: 'Telegram Bot',
disable: 'Disable',
@@ -293,13 +294,11 @@ const en = {
include: 'Include',
delAllEmailConfirm: 'Do you really want to delete it?',
s3Configuration: 'S3 Configuration',
- s3Desc: 'If another S3-compatible storage is configured, R2 will take priority if it’s already connected',
confirmDeletionOfContacts: 'Confirm clearing contacts?',
recentContacts: 'Recent contacts',
selectContacts: 'Select',
forcePathStyleDesc: 'Some self-hosted object storages require path-style access to be enabled',
- kvStorageDesc: 'Replace object storage with KV, and update the access domain to a Worker custom domain',
- kvStorage: 'KV Storage',
+ storageType: 'Storage Location',
customDomainDesc: 'Worker custom domain',
show: 'Show',
hide: 'Hide',
diff --git a/mail-vue/src/i18n/zh.js b/mail-vue/src/i18n/zh.js
index 4354bca..c9ca0ae 100644
--- a/mail-vue/src/i18n/zh.js
+++ b/mail-vue/src/i18n/zh.js
@@ -150,6 +150,7 @@ const zh = {
resendToken: 'Resend Token',
oss: '对象存储',
osDomain: '访问域名',
+ ossDomainDesc: '如果是KV存储不要填',
emailPush: '邮件推送',
tgBot: 'Telegram 机器人',
disable: '关闭',
@@ -293,13 +294,11 @@ const zh = {
include: '包含',
delAllEmailConfirm: '确定要删除吗?',
s3Configuration: 'S3 配置',
- s3Desc: '设置其他S3协议存储,如果绑定了R2会优先用R2',
confirmDeletionOfContacts: '确认清除这些联系人吗?',
recentContacts: '最近联系人',
selectContacts: '选中',
forcePathStyleDesc: '路径样式访问,一些自建的对象存储需要打开',
- kvStorageDesc: '使用KV替代对象存储,访问域名改成worker自定义域',
- kvStorage: 'KV 存储',
+ storageType: '存储类型',
customDomainDesc: 'Worker 自定义域',
show: '显示',
hide: '隐藏',
diff --git a/mail-vue/src/utils/convert.js b/mail-vue/src/utils/convert.js
index ae02ab4..1083edf 100644
--- a/mail-vue/src/utils/convert.js
+++ b/mail-vue/src/utils/convert.js
@@ -13,6 +13,10 @@ export function cvtR2Url(key) {
let domain = settings.r2Domain
+ if (!domain) {
+ return key;
+ }
+
if (!domain.startsWith('http')) {
return 'https://' + domain + '/' + key
}
@@ -26,7 +30,7 @@ export function cvtR2Url(key) {
export function toOssDomain(domain) {
if (!domain) {
- return null
+ return ''
}
if (!domain.startsWith('http')) {
diff --git a/mail-vue/src/views/sys-setting/index.vue b/mail-vue/src/views/sys-setting/index.vue
index 80a736e..92c16e3 100644
--- a/mail-vue/src/views/sys-setting/index.vue
+++ b/mail-vue/src/views/sys-setting/index.vue
@@ -197,7 +197,12 @@
{{ $t('oss') }}
-
{{ $t('osDomain') }}
+
+ {{ $t('osDomain') }}
+
+
+
+
{{ setting.r2Domain || '' }}
@@ -208,9 +213,6 @@
{{ $t('s3Configuration') }}
-
-
-
@@ -220,14 +222,12 @@
- {{ $t('kvStorage') }}
-
-
-
+ {{ $t('storageType') }}
-
+
+ {{ setting.storageType }}
+
@@ -1703,6 +1703,10 @@ function editSetting(settingForm, refreshStatus = true) {
grid-template-columns: 1fr auto;
align-items: center;
+ .storage-type {
+ margin-right: 3px;
+ }
+
span {
overflow: hidden;
white-space: nowrap;
diff --git a/mail-worker/src/email/email.js b/mail-worker/src/email/email.js
index 9306c1b..5abdb77 100644
--- a/mail-worker/src/email/email.js
+++ b/mail-worker/src/email/email.js
@@ -152,13 +152,7 @@ export async function email(message, env, ctx) {
attachment.accountId = emailRow.accountId;
});
- try {
- if (attachments.length > 0 && await r2Service.hasOSS({ env })) {
- await attService.addAtt({ env }, attachments);
- }
- } catch (e) {
- console.error(e);
- }
+ await attService.addAtt({ env }, attachments);
emailRow = await emailService.completeReceive({ env }, account ? emailConst.status.RECEIVE : emailConst.status.NOONE, emailRow.emailId);
diff --git a/mail-worker/src/i18n/en.js b/mail-worker/src/i18n/en.js
index 7b1192b..c4a2f65 100644
--- a/mail-worker/src/i18n/en.js
+++ b/mail-worker/src/i18n/en.js
@@ -11,7 +11,6 @@ const en = {
delMyAccount: 'Cannot delete your own account',
noUserAccount: 'This email does not belong to the current user',
usernameLengthLimit: 'Username length exceeds the limit',
- noOsDomainSendPic: 'Cannot send body images: object storage domain not configured',
noOsSendPic: 'Cannot send body images: object storage not configured',
noOsDomainSendAtt: 'Cannot send attachments: object storage domain not configured',
noOsSendAtt: 'Cannot send attachments: object storage not configured',
diff --git a/mail-worker/src/i18n/zh.js b/mail-worker/src/i18n/zh.js
index ba928cd..b793c5b 100644
--- a/mail-worker/src/i18n/zh.js
+++ b/mail-worker/src/i18n/zh.js
@@ -11,7 +11,6 @@ const zh = {
delMyAccount: '不可以删除自己的邮箱',
noUserAccount: '该邮箱不属于当前用户',
usernameLengthLimit: '用户名长度超出限制',
- noOsDomainSendPic: '对象存储域名未配置不能发送正文图片',
noOsSendPic: '对象存储未配置不能发送正文图片',
noOsDomainSendAtt: '对象存储域名未配置不能发送附件',
noOsSendAtt: '对象存储未配置不能发送附件',
diff --git a/mail-worker/src/init/init.js b/mail-worker/src/init/init.js
index c1ce9be..894dc53 100644
--- a/mail-worker/src/init/init.js
+++ b/mail-worker/src/init/init.js
@@ -30,6 +30,14 @@ const init = {
return c.text(t('initSuccess'));
},
+ async v2_7DB(c) {
+ try {
+ await c.env.db.prepare(`ALTER TABLE account ADD COLUMN all_receive INTEGER NOT NULL DEFAULT 0;`).run();
+ } catch (e) {
+ console.error(e)
+ }
+ },
+
async v2_6DB(c) {
try {
await c.env.db.prepare(`ALTER TABLE account ADD COLUMN all_receive INTEGER NOT NULL DEFAULT 0;`).run();
@@ -90,7 +98,6 @@ const init = {
try {
await c.env.db.batch([
c.env.db.prepare(`ALTER TABLE setting ADD COLUMN force_path_style INTEGER NOT NULL DEFAULT 1;`),
- c.env.db.prepare(`ALTER TABLE setting ADD COLUMN kv_storage INTEGER NOT NULL DEFAULT 1;`),
c.env.db.prepare(`ALTER TABLE setting ADD COLUMN custom_domain TEXT NOT NULL DEFAULT '';`),
c.env.db.prepare(`ALTER TABLE setting ADD COLUMN tg_msg_to TEXT NOT NULL DEFAULT 'show';`),
c.env.db.prepare(`ALTER TABLE setting ADD COLUMN tg_msg_from TEXT NOT NULL DEFAULT 'only-name';`)
diff --git a/mail-worker/src/service/att-service.js b/mail-worker/src/service/att-service.js
index b06fbb0..ed69ad2 100644
--- a/mail-worker/src/service/att-service.js
+++ b/mail-worker/src/service/att-service.js
@@ -82,17 +82,28 @@ const attService = {
}
//邮件正文站内图片转cid附件
- if (src && src.startsWith(domainUtils.toOssDomain(r2Domain))) {
+ if (src && (src.startsWith(domainUtils.toOssDomain(r2Domain)) || src.startsWith('attachments/'))) {
const cid = uuidv4().replace(/-/g, '')
img.setAttribute('src', 'cid:' + cid);
const attData = {};
- attData.key = src.replace(domainUtils.toOssDomain(r2Domain) + '/','');
- attData.path = src;
+
+ if (src.startsWith(domainUtils.toOssDomain(r2Domain))) {
+ attData.key = src.replace(domainUtils.toOssDomain(r2Domain) + '/','');
+ attData.path = src;
+ }
+
+ if (src.startsWith('attachments/')) {
+ const origin = new URL(c.req.url).origin;
+ attData.key = src;
+ attData.path = origin + '/' + src;
+ }
+
attData.contentId = cid;
attData.type = attConst.type.EMBED;
imageDataList.push(attData);
+
}
const hasInlineWidth = img.hasAttribute('width');
diff --git a/mail-worker/src/service/email-service.js b/mail-worker/src/service/email-service.js
index 11387df..b2238a5 100644
--- a/mail-worker/src/service/email-service.js
+++ b/mail-worker/src/service/email-service.js
@@ -197,23 +197,6 @@ const emailService = {
}
-
- if (imageDataList.length > 0 && !r2Domain) {
- throw new BizError(t('noOsDomainSendPic'));
- }
-
- if (imageDataList.length > 0 && !await r2Service.hasOSS(c)) {
- throw new BizError(t('noOsSendPic'));
- }
-
- if (attachments.length > 0 && !r2Domain) {
- throw new BizError(t('noOsDomainSendAtt'));
- }
-
- if (attachments.length > 0 && !await r2Service.hasOSS(c)) {
- throw new BizError(t('noOsSendAtt'));
- }
-
if (attachments.length > 0 && manyType === 'divide') {
throw new BizError(t('noSeparateSend'));
}
@@ -385,7 +368,7 @@ const emailService = {
await attService.saveArticleAtt(c, imageDataList, userId, accountId, emailRow.emailId);
}
- if (attachments?.length > 0 && await r2Service.hasOSS(c)) {
+ if (attachments?.length > 0) {
await attService.saveSendAtt(c, attachments, userId, accountId, emailRow.emailId);
}
diff --git a/mail-worker/src/service/login-service.js b/mail-worker/src/service/login-service.js
index be7f8be..873b8fa 100644
--- a/mail-worker/src/service/login-service.js
+++ b/mail-worker/src/service/login-service.js
@@ -230,7 +230,7 @@ const loginService = {
let authInfo = await c.env.kv.get(KvConst.AUTH_INFO + userRow.userId, { type: 'json' });
- if (authInfo) {
+ if (authInfo && (authInfo.user.email === userRow.email)) {
if (authInfo.tokens.length > 10) {
authInfo.tokens.shift();
diff --git a/mail-worker/src/service/r2-service.js b/mail-worker/src/service/r2-service.js
index f9e9aaa..caf54d8 100644
--- a/mail-worker/src/service/r2-service.js
+++ b/mail-worker/src/service/r2-service.js
@@ -5,20 +5,20 @@ import { settingConst } from '../const/entity-const';
const r2Service = {
- async hasOSS(c) {
+ async storageType(c) {
const setting = await settingService.query(c);
- const { kvStorage, bucket, endpoint, s3AccessKey, s3SecretKey } = setting;
+ const { bucket, endpoint, s3AccessKey, s3SecretKey } = setting;
- if (kvStorage === settingConst.kvStorage.OPEN) {
- return true;
+ if (!!(bucket && endpoint && s3AccessKey && s3SecretKey)) {
+ return 'S3';
}
if (c.env.r2) {
- return true;
+ return 'R2';
}
- return !!(bucket && endpoint && s3AccessKey && s3SecretKey);
+ return 'KV';
},
async putObj(c, key, content, metadata) {
diff --git a/mail-worker/src/service/setting-service.js b/mail-worker/src/service/setting-service.js
index 76dbca6..cccc6d5 100644
--- a/mail-worker/src/service/setting-service.js
+++ b/mail-worker/src/service/setting-service.js
@@ -1,12 +1,12 @@
import KvConst from '../const/kv-const';
import setting from '../entity/setting';
import orm from '../entity/orm';
-import { verifyRecordType } from '../const/entity-const';
+import {verifyRecordType} from '../const/entity-const';
import fileUtils from '../utils/file-utils';
import r2Service from './r2-service';
import constant from '../const/constant';
import BizError from '../error/biz-error';
-import { t } from '../i18n/i18n'
+import {t} from '../i18n/i18n'
import verifyRecordService from './verify-record-service';
const settingService = {
@@ -101,6 +101,8 @@ const settingService = {
settingRow.regVerifyOpen = regVerifyOpen
settingRow.addVerifyOpen = addVerifyOpen
+ settingRow.storageType = await r2Service.storageType(c);
+
return settingRow;
},
@@ -131,37 +133,21 @@ const settingService = {
return;
}
- const hasOss = await r2Service.hasOSS(c);
-
- if (hasOss) {
-
- if (background) {
- await r2Service.delete(c,background)
- await orm(c).update(setting).set({ background: '' }).run();
- await this.refresh(c)
- }
-
+ if (background) {
+ await r2Service.delete(c,background)
+ await orm(c).update(setting).set({ background: '' }).run();
+ await this.refresh(c)
}
},
async setBackground(c, params) {
- const settingRow = await this.query(c);
-
let { background } = params
await this.deleteBackground(c);
if (background && !background.startsWith('http')) {
- if (!await r2Service.hasOSS(c)) {
- throw new BizError(t('noOsUpBack'));
- }
-
- if (!settingRow.r2Domain) {
- throw new BizError(t('noOsDomainUpBack'));
- }
-
const file = fileUtils.base64ToFile(background)
const arrayBuffer = await file.arrayBuffer();
@@ -183,7 +169,7 @@ const settingService = {
async websiteConfig(c) {
- const settingRow = await this.get(c, true)
+ const settingRow = await this.get(c, true);
return {
register: settingRow.register,
diff --git a/mail-worker/src/service/user-service.js b/mail-worker/src/service/user-service.js
index bb14a98..333145b 100644
--- a/mail-worker/src/service/user-service.js
+++ b/mail-worker/src/service/user-service.js
@@ -25,6 +25,10 @@ const userService = {
const userRow = await userService.selectById(c, userId);
+ if (!userRow) {
+ throw new BizError(t('authExpired'), 401);
+ }
+
const [account, roleRow, permKeys] = await Promise.all([
accountService.selectByEmailIncludeDel(c, userRow.email),
roleService.selectById(c, userRow.type),
diff --git a/mail-worker/wrangler-dev.toml b/mail-worker/wrangler-dev.toml
index 2943643..fb49a8a 100644
--- a/mail-worker/wrangler-dev.toml
+++ b/mail-worker/wrangler-dev.toml
@@ -22,6 +22,12 @@ id = "2io01d4b299e481b9de060ece9e7785c"
#binding = "r2"
#bucket_name = "email"
+[assets]
+binding = "assets"
+directory = "./dist"
+not_found_handling = "single-page-application"
+run_worker_first = true
+
[vars]
orm_log = false