feat: add 126 mail provider routing
This commit is contained in:
@@ -628,6 +628,7 @@ function normalizeMailProvider(value = '') {
|
|||||||
case CLOUDFLARE_TEMP_EMAIL_PROVIDER:
|
case CLOUDFLARE_TEMP_EMAIL_PROVIDER:
|
||||||
case '163':
|
case '163':
|
||||||
case '163-vip':
|
case '163-vip':
|
||||||
|
case '126':
|
||||||
case 'qq':
|
case 'qq':
|
||||||
case 'inbucket':
|
case 'inbucket':
|
||||||
case '2925':
|
case '2925':
|
||||||
@@ -6131,6 +6132,9 @@ function getMailConfig(state) {
|
|||||||
if (provider === '163-vip') {
|
if (provider === '163-vip') {
|
||||||
return { source: 'mail-163', url: 'https://webmail.vip.163.com/js6/main.jsp?df=mail163_letter#module=mbox.ListModule%7C%7B%22fid%22%3A1%2C%22order%22%3A%22date%22%2C%22desc%22%3Atrue%7D', label: '163 VIP 邮箱' };
|
return { source: 'mail-163', url: 'https://webmail.vip.163.com/js6/main.jsp?df=mail163_letter#module=mbox.ListModule%7C%7B%22fid%22%3A1%2C%22order%22%3A%22date%22%2C%22desc%22%3Atrue%7D', label: '163 VIP 邮箱' };
|
||||||
}
|
}
|
||||||
|
if (provider === '126') {
|
||||||
|
return { source: 'mail-163', url: 'https://mail.126.com/js6/main.jsp?df=mail163_letter#module=mbox.ListModule%7C%7B%22fid%22%3A1%2C%22order%22%3A%22date%22%2C%22desc%22%3Atrue%7D', label: '126 邮箱' };
|
||||||
|
}
|
||||||
if (provider === 'inbucket') {
|
if (provider === 'inbucket') {
|
||||||
const host = normalizeInbucketOrigin(state.inbucketHost);
|
const host = normalizeInbucketOrigin(state.inbucketHost);
|
||||||
const mailbox = (state.inbucketMailbox || '').trim();
|
const mailbox = (state.inbucketMailbox || '').trim();
|
||||||
|
|||||||
+20
-5
@@ -2,13 +2,20 @@
|
|||||||
|
|
||||||
const getActivationStrategy = self.MultiPageActivationUtils?.getActivationStrategy;
|
const getActivationStrategy = self.MultiPageActivationUtils?.getActivationStrategy;
|
||||||
|
|
||||||
const SCRIPT_SOURCE = (() => {
|
function detectScriptSource({
|
||||||
if (window.__MULTIPAGE_SOURCE) return window.__MULTIPAGE_SOURCE;
|
injectedSource,
|
||||||
const url = location.href;
|
url = '',
|
||||||
const hostname = location.hostname;
|
hostname = '',
|
||||||
|
} = {}) {
|
||||||
|
if (injectedSource) return injectedSource;
|
||||||
if (url.includes('auth0.openai.com') || url.includes('auth.openai.com') || url.includes('accounts.openai.com')) return 'signup-page';
|
if (url.includes('auth0.openai.com') || url.includes('auth.openai.com') || url.includes('accounts.openai.com')) return 'signup-page';
|
||||||
if (hostname === 'mail.qq.com' || hostname === 'wx.mail.qq.com') return 'qq-mail';
|
if (hostname === 'mail.qq.com' || hostname === 'wx.mail.qq.com') return 'qq-mail';
|
||||||
if (hostname === 'mail.163.com' || hostname.endsWith('.mail.163.com') || hostname === 'webmail.vip.163.com') return 'mail-163';
|
if (
|
||||||
|
hostname === 'mail.163.com'
|
||||||
|
|| hostname.endsWith('.mail.163.com')
|
||||||
|
|| hostname === 'webmail.vip.163.com'
|
||||||
|
|| hostname === 'mail.126.com'
|
||||||
|
) return 'mail-163';
|
||||||
if (hostname === 'mail.google.com') return 'gmail-mail';
|
if (hostname === 'mail.google.com') return 'gmail-mail';
|
||||||
if (hostname === 'www.icloud.com' || hostname === 'www.icloud.com.cn') return 'icloud-mail';
|
if (hostname === 'www.icloud.com' || hostname === 'www.icloud.com.cn') return 'icloud-mail';
|
||||||
if (url.includes('duckduckgo.com/email/settings/autofill')) return 'duck-mail';
|
if (url.includes('duckduckgo.com/email/settings/autofill')) return 'duck-mail';
|
||||||
@@ -16,6 +23,14 @@ const SCRIPT_SOURCE = (() => {
|
|||||||
if (url.includes("2925.com")) return "mail-2925";
|
if (url.includes("2925.com")) return "mail-2925";
|
||||||
// VPS panel — detected dynamically since URL is configurable
|
// VPS panel — detected dynamically since URL is configurable
|
||||||
return 'vps-panel';
|
return 'vps-panel';
|
||||||
|
}
|
||||||
|
|
||||||
|
const SCRIPT_SOURCE = (() => {
|
||||||
|
return detectScriptSource({
|
||||||
|
injectedSource: window.__MULTIPAGE_SOURCE,
|
||||||
|
url: location.href,
|
||||||
|
hostname: location.hostname,
|
||||||
|
});
|
||||||
})();
|
})();
|
||||||
|
|
||||||
const LOG_PREFIX = `[MultiPage:${SCRIPT_SOURCE}]`;
|
const LOG_PREFIX = `[MultiPage:${SCRIPT_SOURCE}]`;
|
||||||
|
|||||||
@@ -0,0 +1,80 @@
|
|||||||
|
const HOTMAIL_PROVIDER = 'hotmail-api';
|
||||||
|
const NETEASE_LIST_PATH = '/js6/main.jsp?df=mail163_letter#module=mbox.ListModule%7C%7B%22fid%22%3A1%2C%22order%22%3A%22date%22%2C%22desc%22%3Atrue%7D';
|
||||||
|
|
||||||
|
function normalizeMailProvider(value = '') {
|
||||||
|
const normalized = String(value || '').trim().toLowerCase();
|
||||||
|
switch (normalized) {
|
||||||
|
case HOTMAIL_PROVIDER:
|
||||||
|
case '163':
|
||||||
|
case '163-vip':
|
||||||
|
case '126':
|
||||||
|
case 'qq':
|
||||||
|
case 'inbucket':
|
||||||
|
return normalized;
|
||||||
|
default:
|
||||||
|
return '163';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getMailProviderConfig(state = {}, options = {}) {
|
||||||
|
const provider = normalizeMailProvider(state.mailProvider);
|
||||||
|
const normalizeInbucketOrigin = options.normalizeInbucketOrigin || (() => '');
|
||||||
|
|
||||||
|
if (provider === HOTMAIL_PROVIDER) {
|
||||||
|
return { provider: HOTMAIL_PROVIDER, label: 'Hotmail(微软 Graph)' };
|
||||||
|
}
|
||||||
|
if (provider === '163') {
|
||||||
|
return {
|
||||||
|
source: 'mail-163',
|
||||||
|
url: `https://mail.163.com${NETEASE_LIST_PATH}`,
|
||||||
|
label: '163 邮箱',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
if (provider === '163-vip') {
|
||||||
|
return {
|
||||||
|
source: 'mail-163',
|
||||||
|
url: `https://webmail.vip.163.com${NETEASE_LIST_PATH}`,
|
||||||
|
label: '163 VIP 邮箱',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
if (provider === '126') {
|
||||||
|
return {
|
||||||
|
source: 'mail-163',
|
||||||
|
url: `https://mail.126.com${NETEASE_LIST_PATH}`,
|
||||||
|
label: '126 邮箱',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
if (provider === 'inbucket') {
|
||||||
|
const host = normalizeInbucketOrigin(state.inbucketHost);
|
||||||
|
const mailbox = String(state.inbucketMailbox || '').trim();
|
||||||
|
if (!host) {
|
||||||
|
return { error: 'Inbucket 主机地址为空或无效。' };
|
||||||
|
}
|
||||||
|
if (!mailbox) {
|
||||||
|
return { error: 'Inbucket 邮箱名称为空。' };
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
source: 'inbucket-mail',
|
||||||
|
url: `${host}/m/${encodeURIComponent(mailbox)}/`,
|
||||||
|
label: `Inbucket 邮箱(${mailbox})`,
|
||||||
|
navigateOnReuse: true,
|
||||||
|
inject: ['content/activation-utils.js', 'content/utils.js', 'content/inbucket-mail.js'],
|
||||||
|
injectSource: 'inbucket-mail',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return { source: 'qq-mail', url: 'https://wx.mail.qq.com/', label: 'QQ 邮箱' };
|
||||||
|
}
|
||||||
|
|
||||||
|
const api = {
|
||||||
|
HOTMAIL_PROVIDER,
|
||||||
|
getMailProviderConfig,
|
||||||
|
normalizeMailProvider,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (typeof module !== 'undefined' && module.exports) {
|
||||||
|
module.exports = api;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof self !== 'undefined') {
|
||||||
|
self.MailProviderUtils = api;
|
||||||
|
}
|
||||||
+2
-1
@@ -69,7 +69,8 @@
|
|||||||
"matches": [
|
"matches": [
|
||||||
"https://mail.163.com/*",
|
"https://mail.163.com/*",
|
||||||
"https://*.mail.163.com/*",
|
"https://*.mail.163.com/*",
|
||||||
"https://webmail.vip.163.com/*"
|
"https://webmail.vip.163.com/*",
|
||||||
|
"https://mail.126.com/*"
|
||||||
],
|
],
|
||||||
"js": [
|
"js": [
|
||||||
"content/activation-utils.js",
|
"content/activation-utils.js",
|
||||||
|
|||||||
@@ -169,6 +169,7 @@
|
|||||||
<option value="icloud">iCloud 邮箱</option>
|
<option value="icloud">iCloud 邮箱</option>
|
||||||
<option value="163">163 邮箱 (mail.163.com)</option>
|
<option value="163">163 邮箱 (mail.163.com)</option>
|
||||||
<option value="163-vip">163 VIP 邮箱 (vip.163.com)</option>
|
<option value="163-vip">163 VIP 邮箱 (vip.163.com)</option>
|
||||||
|
<option value="126">126 邮箱 (mail.126.com)</option>
|
||||||
<option value="qq">QQ 邮箱 (wx.mail.qq.com)</option>
|
<option value="qq">QQ 邮箱 (wx.mail.qq.com)</option>
|
||||||
<option value="inbucket">Inbucket(自定义主机)</option>
|
<option value="inbucket">Inbucket(自定义主机)</option>
|
||||||
<option value="2925">2925 邮箱 (2925.com)</option>
|
<option value="2925">2925 邮箱 (2925.com)</option>
|
||||||
|
|||||||
@@ -444,6 +444,11 @@ const MAIL_PROVIDER_LOGIN_CONFIGS = {
|
|||||||
url: 'https://webmail.vip.163.com/',
|
url: 'https://webmail.vip.163.com/',
|
||||||
buttonLabel: '登录',
|
buttonLabel: '登录',
|
||||||
},
|
},
|
||||||
|
'126': {
|
||||||
|
label: '126 邮箱',
|
||||||
|
url: 'https://mail.126.com/',
|
||||||
|
buttonLabel: '登录',
|
||||||
|
},
|
||||||
qq: {
|
qq: {
|
||||||
label: 'QQ 邮箱',
|
label: 'QQ 邮箱',
|
||||||
url: 'https://wx.mail.qq.com/',
|
url: 'https://wx.mail.qq.com/',
|
||||||
@@ -1693,7 +1698,7 @@ function applySettingsState(state) {
|
|||||||
inputSub2ApiGroup.value = state?.sub2apiGroupName || '';
|
inputSub2ApiGroup.value = state?.sub2apiGroupName || '';
|
||||||
inputSub2ApiDefaultProxy.value = state?.sub2apiDefaultProxyName || '';
|
inputSub2ApiDefaultProxy.value = state?.sub2apiDefaultProxyName || '';
|
||||||
const restoredMailProvider = isCustomMailProvider(state?.mailProvider)
|
const restoredMailProvider = isCustomMailProvider(state?.mailProvider)
|
||||||
|| [ICLOUD_PROVIDER, 'hotmail-api', GMAIL_PROVIDER, 'luckmail-api', '163', '163-vip', 'qq', 'inbucket', '2925', 'cloudflare-temp-email'].includes(String(state?.mailProvider || '').trim())
|
|| [ICLOUD_PROVIDER, 'hotmail-api', GMAIL_PROVIDER, 'luckmail-api', '163', '163-vip', '126', 'qq', 'inbucket', '2925', 'cloudflare-temp-email'].includes(String(state?.mailProvider || '').trim())
|
||||||
? String(state?.mailProvider || '163').trim()
|
? String(state?.mailProvider || '163').trim()
|
||||||
: (String(state?.emailGenerator || '').trim().toLowerCase() === 'custom'
|
: (String(state?.emailGenerator || '').trim().toLowerCase() === 'custom'
|
||||||
|| String(state?.emailGenerator || '').trim().toLowerCase() === 'manual'
|
|| String(state?.emailGenerator || '').trim().toLowerCase() === 'manual'
|
||||||
|
|||||||
@@ -0,0 +1,66 @@
|
|||||||
|
const test = require('node:test');
|
||||||
|
const assert = require('node:assert/strict');
|
||||||
|
const fs = require('node:fs');
|
||||||
|
|
||||||
|
const source = fs.readFileSync('content/utils.js', 'utf8');
|
||||||
|
|
||||||
|
function extractFunction(name) {
|
||||||
|
const start = source.indexOf(`function ${name}(`);
|
||||||
|
if (start < 0) {
|
||||||
|
throw new Error(`missing function ${name}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
let parenDepth = 0;
|
||||||
|
let signatureEnded = false;
|
||||||
|
let braceStart = -1;
|
||||||
|
for (let index = start; index < source.length; index += 1) {
|
||||||
|
const ch = source[index];
|
||||||
|
if (ch === '(') {
|
||||||
|
parenDepth += 1;
|
||||||
|
} else if (ch === ')') {
|
||||||
|
parenDepth -= 1;
|
||||||
|
if (parenDepth === 0) {
|
||||||
|
signatureEnded = true;
|
||||||
|
}
|
||||||
|
} else if (ch === '{' && signatureEnded) {
|
||||||
|
braceStart = index;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (braceStart < 0) {
|
||||||
|
throw new Error(`missing body for function ${name}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
let depth = 0;
|
||||||
|
let end = braceStart;
|
||||||
|
for (; end < source.length; end += 1) {
|
||||||
|
const ch = source[end];
|
||||||
|
if (ch === '{') depth += 1;
|
||||||
|
if (ch === '}') {
|
||||||
|
depth -= 1;
|
||||||
|
if (depth === 0) {
|
||||||
|
end += 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return source.slice(start, end);
|
||||||
|
}
|
||||||
|
|
||||||
|
test('detectScriptSource maps 126 mail hosts to the shared 163 mail source', () => {
|
||||||
|
const bundle = [extractFunction('detectScriptSource')].join('\n');
|
||||||
|
const api = new Function(`
|
||||||
|
${bundle}
|
||||||
|
return { detectScriptSource };
|
||||||
|
`)();
|
||||||
|
|
||||||
|
assert.equal(
|
||||||
|
api.detectScriptSource({
|
||||||
|
url: 'https://mail.126.com/js6/main.jsp',
|
||||||
|
hostname: 'mail.126.com',
|
||||||
|
}),
|
||||||
|
'mail-163'
|
||||||
|
);
|
||||||
|
});
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
const test = require('node:test');
|
||||||
|
const assert = require('node:assert/strict');
|
||||||
|
|
||||||
|
const {
|
||||||
|
HOTMAIL_PROVIDER,
|
||||||
|
getMailProviderConfig,
|
||||||
|
normalizeMailProvider,
|
||||||
|
} = require('../mail-provider-utils.js');
|
||||||
|
|
||||||
|
test('normalizeMailProvider accepts 126 and falls back to 163', () => {
|
||||||
|
assert.equal(normalizeMailProvider('126'), '126');
|
||||||
|
assert.equal(normalizeMailProvider('163-vip'), '163-vip');
|
||||||
|
assert.equal(normalizeMailProvider('unknown-provider'), '163');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('getMailProviderConfig returns the shared NetEase source for 126 mail', () => {
|
||||||
|
assert.deepEqual(
|
||||||
|
getMailProviderConfig({ mailProvider: '126' }),
|
||||||
|
{
|
||||||
|
source: 'mail-163',
|
||||||
|
url: 'https://mail.126.com/js6/main.jsp?df=mail163_letter#module=mbox.ListModule%7C%7B%22fid%22%3A1%2C%22order%22%3A%22date%22%2C%22desc%22%3Atrue%7D',
|
||||||
|
label: '126 邮箱',
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('getMailProviderConfig preserves the hotmail provider sentinel', () => {
|
||||||
|
assert.deepEqual(
|
||||||
|
getMailProviderConfig({ mailProvider: HOTMAIL_PROVIDER }),
|
||||||
|
{
|
||||||
|
provider: HOTMAIL_PROVIDER,
|
||||||
|
label: 'Hotmail(微软 Graph)',
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user