新增自定义显示TG邮件消息内容

This commit is contained in:
eoao
2025-10-23 00:22:45 +08:00
parent b8b1bee015
commit b41c9f4725
10 changed files with 118 additions and 61 deletions
@@ -87,16 +87,11 @@ function autoScale() {
if (!shadowContent) return
const parentWidth = parent.offsetWidth
const parentHeight = parent.offsetHeight
const childWidth = shadowContent.scrollWidth
const childHeight = shadowContent.scrollHeight
if (childWidth === 0 || childHeight === 0) return
if (childWidth === 0) return
const scaleX = parentWidth / childWidth
const scaleY = parentHeight / childHeight
const scale = Math.min(scaleX, scaleY)
const scale = parentWidth / childWidth
const hostElement = shadowRoot.host
hostElement.style.zoom = scale
+20 -15
View File
@@ -137,7 +137,7 @@ const en = {
websiteReg: 'Sign Up',
loginDomain: 'Sign-In Box Domain',
multipleEmail: 'Multiple Accounts',
multipleEmailDesc: 'Enable this feature to allow users to add multiple accounts.',
multipleEmailDesc: 'Enable this feature to allow users to add multiple accounts',
customization: 'Customization',
websiteTitle: 'Title',
loginBoxOpacity: 'Login Box Opacity',
@@ -145,7 +145,7 @@ const en = {
emailSetting: 'Email',
receiveEmail: 'Receive Email',
autoRefresh: 'Auto Refresh',
autoRefreshDesc: 'Automatically fetch the latest emails from the server.',
autoRefreshDesc: 'Automatically fetch the latest emails from the server',
sendEmail: 'Send Email',
resendToken: 'Resend Token',
oss: 'Object Storage',
@@ -165,7 +165,7 @@ const en = {
version: 'Version',
community: 'Community',
changeTitle: 'Change Title',
addResendTokenDesc: 'Input to add; leave empty to delete.',
addResendTokenDesc: 'Input to add; leave empty to delete',
addOsDomain: 'Add Domain',
domainDesc: 'Domain',
addTurnstileSecret: 'Add turnstile secret',
@@ -173,14 +173,14 @@ const en = {
tgBotDesc: 'Forward received emails to a Telegram bot',
tgBotToken: 'Bot token',
toBotTokenDesc: 'Multiple user chat_ids, separated by commas',
otherEmailDesc: 'emails can be forwarded to external email, but must be verified via cloudflare.',
otherEmailInputDesc: 'Separate multiple email addresses with commas.',
forwardingRulesDesc: 'Rule-based forwarding only forwards emails received by the specified address.',
ruleEmailsInputDesc: 'Separate multiple email addresses with commas.',
otherEmailDesc: 'emails can be forwarded to external email, but must be verified via cloudflare',
otherEmailInputDesc: 'Separate multiple email addresses with commas',
forwardingRulesDesc: 'Rule-based forwarding only forwards emails received by the specified address',
ruleEmailsInputDesc: 'Separate multiple email addresses with commas',
resendTokenList: 'Token List',
domain: 'Domain',
optional: 'Optional',
subjectInputDesc: 'Please enter the email subject.',
subjectInputDesc: 'Please enter the email subject',
changeUserName: 'Change Username',
sendSeparately: 'Separately',
send: 'Send',
@@ -251,14 +251,14 @@ const en = {
supportDesc: 'Buy me tea',
featDesc: 'Feature Description',
emailInterception: 'Email Interception',
emailInterceptionDesc: 'Enter a domain or email address to prevent users from receiving emails from certain websites (Enter * to block all).',
emailInterceptionDesc: 'Enter a domain or email address to prevent users from receiving emails from certain websites (Enter * to block all)',
availableDomains: 'Available Domains',
availableDomainsDesc: 'Restrict users to email domains specified. Domains not on the approved list will be blocked from registration, adding email addresses, and sending/receiving emails. If left blank, all domains will be allowed by default.',
availableDomainsDesc: 'Restrict users to email domains specified. Domains not on the approved list will be blocked from registration, adding email addresses, and sending/receiving emails. If left blank, all domains will be allowed by default',
backgroundUrlDesc: 'Image URL',
localUpload: ' Local upload',
imageLink: 'Image URL',
imageLinkErrorMsg: 'Invalid image URL',
backgroundWarning: 'Image file size affects website load speed.',
backgroundWarning: 'Image file size affects website load speed',
rulesVerify: 'Rules',
rulesVerifyTitle: 'Trigger After {count} Daily Uses per IP',
botVerifyMsg: 'Please verify that you are human',
@@ -278,7 +278,7 @@ const en = {
verifyModuleFailed: 'Verification module failed to load. Please refresh the page',
popUp: 'Pop Up',
noRecipientTitle: 'No Recipient',
noRecipientDesc: 'Emails can be received even without a registered email address.',
noRecipientDesc: 'Emails can be received even without a registered email address',
preview: 'Preview',
help: 'Help',
document: 'Document',
@@ -292,12 +292,17 @@ 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 its 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'
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',
customDomainDesc: 'Worker custom domain',
show: 'Show',
hide: 'Hide',
onlyName: 'Only name'
}
export default en
+5 -2
View File
@@ -298,7 +298,10 @@ const zh = {
selectContacts: '选中',
forcePathStyleDesc: '路径样式访问,一些自建的对象存储需要打开',
kvStorageDesc: '使用KV替代对象存储,访问域名改成worker自定义域',
kvStorage: 'KV存储',
customDomainDesc: 'Worker 自定义域'
kvStorage: 'KV 存储',
customDomainDesc: 'Worker 自定义域',
show: '显示',
hide: '隐藏',
onlyName: '仅名字'
}
export default zh
+49 -3
View File
@@ -96,7 +96,7 @@
fit="cover"
>
<template #error>
<div class="error-image" @click="openSetBackground">
<div class="error-image">
<Icon icon="ph:image" width="24" height="24"/>
</div>
</template>
@@ -486,6 +486,28 @@
<el-input-tag tag-type="warning" :placeholder="$t('toBotTokenDesc')" v-model="tgChatId"
@add-tag="addChatTag"></el-input-tag>
<el-input tag-type="warning" :placeholder="$t('customDomainDesc')" v-model="customDomain" ></el-input>
<div class="tg-msg-label">
<span>{{t('from')}}</span>
<el-select v-model="tgMsgFrom" >
<el-option
v-for="item in tgMsgFromOption"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</div>
<div class="tg-msg-label">
<span>{{t('recipient')}}</span>
<el-select v-model="tgMsgTo" >
<el-option
v-for="item in tgMsgToOption"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</div>
</div>
<template #footer>
<div class="dialog-footer">
@@ -787,6 +809,12 @@ const emailColumnWidth = ref(0)
const tokenColumnWidth = ref(0)
const ruleType = ref(0)
const ruleEmail = ref([])
const tgMsgFrom = ref('')
const tgMsgTo = ref('')
const tgMsgFromOption = [{label: t('show'), value: 'show'}, {label: t('hide'), value: 'hide'}, {label: t('onlyName'), value:'only-name'}]
const tgMsgToOption = [{label: t('show'), value: 'show'}, {label: t('hide'), value: 'hide'}]
const tgMsgLabelWidth = computed(() => locale.value === 'en' ? '120px' : '100px');
getSettings()
getUpdate()
@@ -901,6 +929,8 @@ function openTgSetting() {
tgBotStatus.value = setting.value.tgBotStatus
tgBotToken.value = setting.value.tgBotToken
customDomain.value = setting.value.customDomain
tgMsgFrom.value = setting.value.tgMsgFrom
tgMsgTo.value = setting.value.tgMsgTo
tgChatId.value = []
if (setting.value.tgChatId) {
const list = setting.value.tgChatId.split(',')
@@ -1036,7 +1066,9 @@ function tgBotSave() {
tgBotToken: tgBotToken.value,
customDomain: customDomain.value,
tgBotStatus: tgBotStatus.value,
tgChatId: tgChatId.value + ''
tgChatId: tgChatId.value + '',
tgMsgFrom: tgMsgFrom.value,
tgMsgTo: tgMsgTo.value
}
editSetting(form)
}
@@ -1496,6 +1528,7 @@ function editSetting(settingForm, refreshStatus = true) {
.forward-set-title {
top: 1px;
padding-right: 5px;
position: relative;
font-size: 16px;
font-weight: bold;;
@@ -1548,11 +1581,24 @@ function editSetting(settingForm, refreshStatus = true) {
.forward-set-body {
display: flex;
flex-direction: column;
gap: 15px;
.el-switch {
align-self: end;
}
> *:nth-child(-n+2) {
margin-bottom: 15px;
}
.tg-msg-label {
margin-top: 10px;
display: flex;
align-items: center;
justify-content: space-between;
.el-select {
width: v-bind(tgMsgLabelWidth);
}
}
}
.forward {
+1
View File
@@ -6,3 +6,4 @@ app.get('/telegram/getEmail/:token', async (c) => {
c.header('Cache-Control', 'public, max-age=604800, immutable');
return c.html(content)
});
+3 -1
View File
@@ -42,6 +42,8 @@ export const setting = sqliteTable('setting', {
s3SecretKey: text('s3_secret_key').default('').notNull(),
kvStorage: integer('kv_storage').default(1).notNull(),
forcePathStyle: integer('force_path_style').default(1).notNull(),
customDomain: text('custom_domain').default('').notNull()
customDomain: text('custom_domain').default('').notNull(),
tgMsgFrom: text('tg_msg_from').default('only-name').notNull(),
tgMsgTo: text('tg_msg_to').default('show').notNull()
});
export default setting
+3 -1
View File
@@ -32,7 +32,9 @@ const init = {
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 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';`)
]);
} catch (e) {
console.error(e)
+2 -21
View File
@@ -15,26 +15,6 @@ import verifyUtils from '../utils/verify-utils';
const telegramService = {
async getEmailById(c, params) {
const { emailId } = params
const emailRow = await orm(c).select().from(email).where(eq(email.emailId, emailId)).get();
if (emailRow) {
if (emailRow.content) {
return emailHtmlTemplate(emailRow.content || '')
} else {
return emailTextTemplate(emailRow.text || '')
}
} else {
return emailTextTemplate('The email does not exist')
}
},
async getEmailContent(c, params) {
const { token } = params
@@ -50,7 +30,8 @@ const telegramService = {
if (emailRow) {
if (emailRow.content) {
return emailHtmlTemplate(emailRow.content || '')
const { r2Domain } = await settingService.query(c);
return emailHtmlTemplate(emailRow.content || '', r2Domain)
} else {
return emailTextTemplate(emailRow.text || '')
}
+6 -8
View File
@@ -1,10 +1,12 @@
import { parseHTML } from 'linkedom';
import domainUtils from '../utils/domain-uitls';
export default function emailHtmlTemplate(html) {
export default function emailHtmlTemplate(html, domain) {
const { document } = parseHTML(html);
document.querySelectorAll('script').forEach(script => script.remove());
html = document.documentElement.outerHTML;
html = html.replace(/{{domain}}/g, domainUtils.toOssDomain(domain) + '/');
return `<!DOCTYPE html>
<html lang='en' >
@@ -105,6 +107,7 @@ export default function emailHtmlTemplate(html) {
}
function autoScale(shadowRoot, container) {
if (!shadowRoot || !container) return;
const parent = container;
@@ -113,16 +116,11 @@ export default function emailHtmlTemplate(html) {
if (!shadowContent) return;
const parentWidth = parent.offsetWidth;
const parentHeight = parent.offsetHeight;
const childWidth = shadowContent.scrollWidth;
const childHeight = shadowContent.scrollHeight;
if (childWidth === 0 || childHeight === 0) return;
if (childWidth === 0) return;
const scaleX = parentWidth / childWidth;
const scaleY = parentHeight / childHeight;
const scale = Math.min(scaleX, scaleY);
const scale = parentWidth / childWidth;
const hostElement = shadowRoot.host;
hostElement.style.zoom = scale;
+27 -3
View File
@@ -1,7 +1,31 @@
export default function emailMsgTemplate(email) {
return `<b>${email.subject}</b>
export default function emailMsgTemplate(email, tgMsgTo, tgMsgFrom) {
let template = `<b>${email.subject}</b>`
if (tgMsgFrom === 'only-name') {
template += `
发件人${email.name}`
}
if (tgMsgFrom === 'show') {
template += `
发件人${email.name} &lt;${email.sendEmail}&gt;`
}
if(tgMsgTo === 'show' && tgMsgFrom === 'hide') {
template += `
发件人${email.name} &lt;${email.sendEmail}&gt;
收件人\u200B${email.toEmail}`
return template
}
if(tgMsgTo === 'show') {
template += `
收件人\u200B${email.toEmail}`
}
return template;
}