Skip to content
Back to skills

1385 Inactive Email Domains Af21184a

ASecurity

通过 MCP 直接查询 `my_shell_prod` 数据库,查询历史上曾出现过的邮箱域名(排除临时邮箱),但在白名单更新时间点之后没有用户登录活跃的域名列表。

  • 9 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added October 11, 2026
developmentjavascriptgojavashellsql

Works with

  • mcp

Security analysis

A100/100

Scanned October 11, 2026

npx -y skills add tools-only/X-Skills --skill 1385-inactive-email-domains_af21184a --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of 1385 Inactive Email Domains Af21184a?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for 1385 Inactive Email Domains Af21184a
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/tools-only-1385-inactive-email-domains-af21184a/badge)](https://www.skillsdirectory.com/skills/tools-only-1385-inactive-email-domains-af21184a)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

SKILL.md
# 失活邮箱域名分析

## 目标

通过 MCP 直接查询 `my_shell_prod` 数据库,查询历史上曾出现过的邮箱域名(排除临时邮箱),但在白名单更新时间点之后没有用户登录活跃的域名列表。

**分析维度**: 基于 `user.lastLoginTime`(最后登录时间)而非账号创建时间,更准确反映用户真实活跃度。

如果在 base44 运行,则 @base44_prompt_mcphub.md

**用途**: 用于识别需要从白名单中移除的失活邮箱域名。

## 参数

| 参数 | 说明 | 默认值 |
|------|------|--------|
| `whitelist_update_time` | 白名单更新时间点 (YYYY-MM-DD HH:MM:SS) | 今天 10:00:00 |
| `active_since` | 近期活跃起点 (YYYY-MM-DD) | 最近1个月 |

**参数说明**:

### `active_since` (近期活跃起点)

定义一个时间窗口的起点,只分析在此时间点**之后**有过登录活动的域名。

**作用**:
1. **性能优化**: 避免查询全部历史数据,只关注近期数据
2. **分析相关性**: 只关注"最近还活跃,但现在失活了"的域名
3. **排除噪音**: 过滤掉很久以前就废弃的古老域名

**实际含义**:
- 只分析"在 `[active_since, whitelist_update_time)` 时间段内有过登录活动"的域名
- 如果一个域名的最后活跃时间早于 `active_since`,即使在 `whitelist_update_time` 之后也没活跃,也**不会**被纳入分析

**示例**:
```
whitelist_update_time = 2025-12-26 10:00:00
active_since = 2025-11-26  (近期活跃起点 = 最近1个月)

含义:只分析"在2025-11-26到2025-12-26 10:00这段时间内有过活跃,
      但在12-26 10:00之后就失活了"的域名

域名A: 最后活跃 = 2025-12-20 → ✅ 纳入分析(在窗口内且已失活)
域名B: 最后活跃 = 2025-10-01 → ❌ 不纳入(比近期活跃起点还早,早就失活了)
域名C: 最后活跃 = 2025-12-26 11:00 → ❌ 不纳入(仍然活跃)
```

## 数据源

- `my_shell_prod.user_privy` - 用户邮箱信息表
- `my_shell_prod.user` - 用户表,包含 `lastLoginTime` 字段(最后登录时间)

## 临时邮箱域名列表

以下域名被认定为临时邮箱(共 56 个),查询时将被排除:

```
protectsmail.net, roratu.com, mucate.com, mekuron.com, airsworld.net,
arugy.com, forexzig.com, fxzig.com, denipl.com, denipl.net, nctime.com,
fftube.com, correostemporales.org, yopmail.com, rosuper.com, ssgperf.com,
m3player.com, guerrillamail.com, guerrillamail.org, guerrillamailblock.com,
pokemail.net, spam4.me, grr.la, guerrillamail.biz, guerrillamail.de,
trbvm.com, mailinator.com, 10minutemail.com, temp-mail.org, throwaway.email,
getnada.com, maildrop.cc, trashmail.com, tempmailaddress.com, fakeinbox.com,
mytemp.email, tempmail.com, emailondeck.com, sharklasers.com, discard.email,
discardmail.com, mintemail.com, mailnesia.com, mohmal.com, crazymailing.com,
mailcatch.com, mailnator.com, tempr.email, tempinbox.com, spamgourmet.com,
mailexpire.com, dispostable.com, filzmail.com, getairmail.com,
harakirimail.com, anonymbox.com
```

## 查询逻辑

1. 获取所有历史域名及其统计信息(基于用户最后登录时间)
2. 筛选出 `whitelist_update_time` 之后没有登录活跃的域名
3. 过滤出最后登录时间在 `active_since` 之后的域名
4. 排除临时邮箱域名

---

## Step 1: 查询数据

使用 `mcp_mcphub_bytebase-execute_sql` 执行以下 SQL(替换 `{whitelist_update_time}`, `{active_since}`):

### 默认参数示例

```
whitelist_update_time = '2025-12-26 10:00:00'
active_since = '2025-11-26'  // 近期活跃起点(最近1个月)
```

拆分成两个简单查询,职责单一,方便理解和调试:

---

### 查询1: 所有域名的统计信息

```sql
-- 使用 CTE 优化,减少函数重复计算,提升 3-4 倍性能
WITH active_users AS (
  -- 先过滤时间范围,减少 JOIN 数据量
  SELECT id, lastLoginTime
  FROM my_shell_prod.user
  WHERE lastLoginTime >= '{active_since}'
),
email_data AS (
  -- 提前计算域名,避免在 GROUP BY 和 WHERE 中重复计算
  SELECT
    up.user_id,
    SUBSTRING_INDEX(
      COALESCE(
        NULLIF(up.email, ''),
        NULLIF(up.google_email, ''),
        NULLIF(up.apple_email, '')
      ),
      '@', -1
    ) as domain,
    au.lastLoginTime
  FROM my_shell_prod.user_privy up
  INNER JOIN active_users au ON up.user_id = au.id
  WHERE
    COALESCE(NULLIF(up.email, ''), NULLIF(up.google_email, ''), NULLIF(up.apple_email, '')) IS NOT NULL
)
SELECT
  domain,
  COUNT(DISTINCT user_id) as total_users,
  MIN(lastLoginTime) as first_appearance,
  MAX(lastLoginTime) as last_appearance
FROM email_data
WHERE
  domain NOT IN (
    'protectsmail.net', 'roratu.com', 'mucate.com', 'mekuron.com', 'airsworld.net',
    'arugy.com', 'forexzig.com', 'fxzig.com', 'denipl.com', 'denipl.net', 'nctime.com',
    'fftube.com', 'correostemporales.org', 'yopmail.com', 'rosuper.com', 'ssgperf.com',
    'm3player.com', 'guerrillamail.com', 'guerrillamail.org', 'guerrillamailblock.com',
    'pokemail.net', 'spam4.me', 'grr.la', 'guerrillamail.biz', 'guerrillamail.de',
    'trbvm.com', 'mailinator.com', '10minutemail.com', 'temp-mail.org', 'throwaway.email',
    'getnada.com', 'maildrop.cc', 'trashmail.com', 'tempmailaddress.com', 'fakeinbox.com',
    'mytemp.email', 'tempmail.com', 'emailondeck.com', 'sharklasers.com', 'discard.email',
    'discardmail.com', 'mintemail.com', 'mailnesia.com', 'mohmal.com', 'crazymailing.com',
    'mailcatch.com', 'mailnator.com', 'tempr.email', 'tempinbox.com', 'spamgourmet.com',
    'mailexpire.com', 'dispostable.com', 'filzmail.com', 'getairmail.com',
    'harakirimail.com', 'anonymbox.com'
  )
GROUP BY domain
HAVING total_users >= 3
ORDER BY total_users DESC;
```

**结果格式:**
```
domain | total_users | first_appearance | last_appearance
```

**字段说明:**
- `domain`: 邮箱域名
- `total_users`: 使用该域名的用户总数
- `first_appearance`: 该域名所有用户中**最早的登录时间**
- `last_appearance`: 该域名所有用户中**最后的登录时间**

---

### 查询2: 白名单更新时间后活跃的域名

```sql
-- 使用 CTE 优化,先过滤时间范围
WITH active_users AS (
  SELECT id
  FROM my_shell_prod.user
  WHERE lastLoginTime >= '{whitelist_update_time}'
)
SELECT DISTINCT
  SUBSTRING_INDEX(
    COALESCE(
      NULLIF(up.email, ''),
      NULLIF(up.google_email, ''),
      NULLIF(up.apple_email, '')
    ),
    '@', -1
  ) as domain
FROM my_shell_prod.user_privy up
INNER JOIN active_users au ON up.user_id = au.id
WHERE
  COALESCE(NULLIF(up.email, ''), NULLIF(up.google_email, ''), NULLIF(up.apple_email, '')) IS NOT NULL
ORDER BY domain;
```

**结果格式:**
```
domain
```

---

## Step 2: 合并数据

将两个查询结果进行处理:

### 数据过滤规则

从 **查询1** 的结果中,筛选出满足以下条件的域名:

1. `domain` **不在** 查询2 的结果中(白名单更新时间后未登录活跃)
2. `last_appearance >= '{active_since}'`(最后登录时间在范围内)
3. `last_appearance < '{whitelist_update_time}'`(最后登录时间早于白名单更新时间)

### 计算失活天数

```javascript
// 伪代码
const filteredDomains = query1Results.filter(row => {
  const isActive = query2Results.includes(row.domain);
  const inTimeRange = row.last_appearance >= active_since
                   && row.last_appearance < whitelist_update_time;
  return !isActive && inTimeRange;
});

// 计算失活天数(从最后活跃时间到现在,确保不为负数)
const now = new Date();
filteredDomains.forEach(row => {
  const lastLoginDate = new Date(row.last_appearance);
  // 失活天数 = 从该域名最后活跃时间到现在的天数
  row.days_inactive = Math.max(0, (now - lastLoginDate) / (1000 * 60 * 60 * 24));
});
```

**说明**: 失活天数表示从该域名最后活跃时间到现在经过的天数。使用 `Math.max(0, ...)` 确保不出现负数(避免时区或数据延迟导致的计算误差)。

---

## Step 3: 数据分类

将筛选后的结果按失活时间长度分类:

| 分类 | 条件 | 说明 |
|------|------|------|
| 近期失活 | `days_inactive <= 7` | 最近一周内失活 |
| 短期失活 | `7 < days_inactive <= 30` | 1周到1个月内失活 |
| 中期失活 | `30 < days_inactive <= 90` | 1个月到3个月内失活 |
| 长期失活 | `90 < days_inactive <= 180` | 3个月到6个月内失活 |
| 超长期失活 | `days_inactive > 180` | 6个月以上失活 |

---

## Step 4: 生成数据表格

### 输出格式

按用户数量降序展示所有失活域名:

```markdown
| 排名 | 域名 | 用户数 | 首次出现 | 最后活跃 | 失活天数 | 失活等级 |
|------|------|--------|----------|----------|----------|----------|
| 1 | 163.com | 9,560 | 2023-06-23 | 2025-12-25 23:07 | 0.3 | 近期失活 |
| 2 | googlemail.com | 1,917 | 2024-04-10 | 2025-12-26 06:01 | 0.2 | 近期失活 |
...
```

**列说明**:
- **首次出现**: 该域名所有用户中最早的登录时间
- **最后活跃**: 该域名所有用户中最后的登录时间(早于白名单更新时间)
- **失活天数**: 从该域名最后活跃时间到现在的天数

### 数据转换规则

```javascript
// 伪代码
const categories = {
  '近期失活': (days) => days <= 7,
  '短期失活': (days) => days > 7 && days <= 30,
  '中期失活': (days) => days > 30 && days <= 90,
  '长期失活': (days) => days > 90 && days <= 180,
  '超长期失活': (days) => days > 180
};

function getCategory(days_inactive) {
  for (const [name, check] of Object.entries(categories)) {
    if (check(days_inactive)) return name;
  }
  return '未知';
}

const tableData = queryResults.map((row, index) => ({
  rank: index + 1,
  domain: row.domain,
  users: row.total_users.toLocaleString(),
  firstAppearance: row.first_appearance.substring(0, 10),      // 首次出现
  lastActive: row.last_appearance.substring(0, 16).replace('T', ' '),  // 最后活跃
  days: row.days_inactive.toFixed(1),
  category: getCategory(row.days_inactive)
}));
```

---

## 使用场景

### 场景1: 查询今天10:00后失活的域名(最近半年有登录)

```
whitelist_update_time = '2025-12-26 10:00:00'
active_since = '2025-06-26'  // 近期活跃起点(最近半年)
```

### 场景2: 查询本周失活的域名(最近1个月有登录)

```
whitelist_update_time = '2025-12-20 00:00:00'  // 本周一
active_since = '2025-11-20'  // 近期活跃起点(最近1个月)
```

### 场景3: 查询本月失活的域名(最近3个月有登录)

```
whitelist_update_time = '2025-12-01 00:00:00'  // 本月1号
active_since = '2025-09-01'  // 近期活跃起点(最近3个月)
```

---

## 核心指标

- **失活域名总数** = 查询结果总行数
- **失活用户总数** = SUM(total_users)
- **主流邮箱失活数** = 统计常见邮箱域名(gmail.com, outlook.com, 163.com 等)的失活情况
- 目标: 识别异常失活模式,监控用户登录活跃度,优化白名单管理 📊

## 重要说明

### 字段含义
- **首次出现/最后活跃**: 指该域名**所有用户**中最早/最晚的登录时间(非单个用户)
- **失活天数**: 从该域名最后活跃时间到现在的天数
  - 计算公式: `(当前时间 - 最后活跃时间) / (1000 * 60 * 60 * 24)`
  - 使用 `Math.max(0, ...)` 确保不出现负数(避免时区差异或数据延迟)

### 分析维度
本分析基于用户最后登录时间 (`user.lastLoginTime`),而非账号创建时间,更准确反映用户真实活跃情况。

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.