Skip to content

Nuxt.js 项目 GitHub Actions 自动化 CI/CD 实践(三):邮件通知

前言

承接前两篇文章,我们已经实现了创建 Release 时自动构建、打包、部署,并通过 PM2 重启服务。本文将讲解如何配置邮件通知,让团队在 CI/CD 执行成功或失败时及时收到邮件提醒,实现全流程可感知。

本系列文章回顾:

部分目标状态
第一部分构建、打包并上传到 GitHub Release✅ 已完成
第二部分自动部署到远程服务器,PM2 重启服务✅ 已完成
第三部分(本文)CI/CD 邮件通知📍 当前

达成效果:

当你创建一个 Release 后,整个流程将全自动运行,并在以下节点发送邮件通知:

  1. 构建成功 → 收到成功邮件
  2. 构建失败 → 收到告警邮件(含错误日志链接)
  3. 部署成功 → 收到成功邮件(含访问地址)
  4. 部署失败 → 收到告警邮件(需立即检查)

整个过程无需人工干预,真正做到一键发布、自动上线、实时感知

NOTICE

本文为系列文章的第三部分,聚焦于 CI/CD 邮件通知环节。建议先完成前两部分的配置再继续本文。

第三部分目标

在 CI/CD 流程的关键节点自动发送邮件通知:

  • 构建成功/失败通知
  • 部署成功/失败通知
  • 邮件内容包含版本、触发者、时间、详情链接
  • 部署成功邮件包含访问地址

目录结构(延续前两部分)

.github/
└── workflows/
    └── release-bump.yaml   # 包含构建、部署、通知的完整工作流

完整配置文件

在前两部分的基础上,添加邮件通知步骤:

.github/workflows/release-bump.yaml
yaml
name: Auto Bump Version on Release

on:
  release:
    types: [created]

jobs:
  # Job 1: 构建和发布
  build-and-release:
    runs-on: ubuntu-latest
    permissions:
      contents: write
    outputs:
      version: ${{ steps.extract-version.outputs.version }}
      project_name: ${{ steps.project-name.outputs.project_name }}

    steps:
      # ... 前 14 个步骤(检出、安装依赖、构建、打包、上传等)...

      # 15. 构建成功邮件
      - name: Send build success email
        if: success()
        uses: dawidd6/action-send-mail@v3
        with:
          server_address: smtp.gmail.com
          server_port: 587
          username: ${{ vars.GMAIL_SMTP_USER }}
          password: ${{ secrets.GMAIL_SMTP_PASSWORD }}
          subject: "✅ Nuxt 构建成功 - ${{ github.repository }}"
          to: ${{ vars.NOTIFY_EMAILS }}
          from: "GitHub Actions <${{ vars.GMAIL_SMTP_USER }}>"
          body: |
            🎉 Nuxt 项目构建成功!

            仓库:${{ github.repository }}
            版本:${{ steps.extract-version.outputs.version }}
            触发者:${{ github.actor }}
            时间:${{ github.event.repository.updated_at }}
            状态:✅ 成功

            详情:${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}

      # 16. 构建失败邮件
      - name: Send build failure email
        if: failure()
        uses: dawidd6/action-send-mail@v3
        with:
          server_address: smtp.gmail.com
          server_port: 587
          username: ${{ vars.GMAIL_SMTP_USER }}
          password: ${{ secrets.GMAIL_SMTP_PASSWORD }}
          subject: "❌ Nuxt 构建失败 - ${{ github.repository }}"
          to: ${{ vars.NOTIFY_EMAILS }}
          from: "GitHub Actions <${{ vars.GMAIL_SMTP_USER }}>"
          body: |
            🚨 Nuxt 项目构建失败,请立即检查!

            仓库:${{ github.repository }}
            版本:${{ steps.extract-version.outputs.version }}
            触发者:${{ github.actor }}
            时间:${{ github.event.repository.updated_at }}
            状态:❌ 失败

            详情:${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
            请点击上方链接查看详细错误信息。

  # Job 2: 远程部署
  remote-deploy:
    runs-on: ubuntu-latest
    needs: build-and-release
    if: github.event_name == 'release' && success()
    permissions:
      actions: read

    steps:
      # ... 前 6 个步骤(下载、解压、SCP 传输、SSH 部署等)...

      # 7. 部署成功邮件
      - name: Send deploy success email
        if: success()
        uses: dawidd6/action-send-mail@v3
        with:
          server_address: smtp.gmail.com
          server_port: 587
          username: ${{ vars.GMAIL_SMTP_USER }}
          password: ${{ secrets.GMAIL_SMTP_PASSWORD }}
          subject: "✅ Nuxt 部署成功 - ${{ github.repository }}"
          to: ${{ vars.NOTIFY_EMAILS }}
          from: "GitHub Actions <${{ vars.GMAIL_SMTP_USER }}>"
          body: |
            🎉 Nuxt 项目部署成功!

            仓库:${{ github.repository }}
            版本:${{ needs.build-and-release.outputs.version }}
            触发者:${{ github.actor }}
            时间:${{ github.event.repository.updated_at }}
            状态:✅ 成功

            🌐 访问地址:${{ vars.DEPLOY_WEBSITE_DOMAIN }}
            详情:${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}

      # 8. 部署失败邮件
      - name: Send deploy failure email
        if: failure()
        uses: dawidd6/action-send-mail@v3
        with:
          server_address: smtp.gmail.com
          server_port: 587
          username: ${{ vars.GMAIL_SMTP_USER }}
          password: ${{ secrets.GMAIL_SMTP_PASSWORD }}
          subject: "❌ Nuxt 部署失败 - ${{ github.repository }}"
          to: ${{ vars.NOTIFY_EMAILS }}
          from: "GitHub Actions <${{ vars.GMAIL_SMTP_USER }}>"
          body: |
            🚨 Nuxt 项目部署失败,请立即检查!

            仓库:${{ github.repository }}
            版本:${{ needs.build-and-release.outputs.version }}
            触发者:${{ github.actor }}
            时间:${{ github.event.repository.updated_at }}
            状态:❌ 失败

            详情:${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
            请点击上方链接查看详细错误信息。

必需的 Secrets 和 Variables 配置

在 GitHub 仓库的 Settings -> Secrets and variables -> Actions 中添加:

Secrets(敏感信息)

Secret 名称说明示例
GMAIL_SMTP_PASSWORDGmail SMTP 密码(应用专用密码)xxxxxxxxxxxx
ACCESS_TOKENGitHub Personal Access Token(用于上传 Release)github_pat_xxx
DEPLOY_HOST服务器 IP 或域名192.168.1.100
DEPLOY_USERSSH 登录用户名rootubuntu
DEPLOY_SSH_KEYSSH 私钥内容-----BEGIN OPENSSH PRIVATE KEY-----

Variables(非敏感配置)

Variable 名称说明示例
GMAIL_SMTP_USERGmail 邮箱地址your-email@gmail.com
NOTIFY_EMAILS通知邮箱列表(多个用逗号分隔)admin@gmail.com,team@gmail.com
DEPLOY_WEBSITE_DOMAIN部署的网站域名https://example.com
DEPLOY_PORTSSH 端口(可选)22

如何获取 Gmail 应用专用密码

  1. 登录 Gmail 账号
  2. 进入 Google 账号安全性两步验证(需开启)
  3. 进入 应用专用密码
  4. 选择应用:邮件,设备:GitHub Actions
  5. 生成 16 位密码,复制保存

⚠️ 注意:Gmail 普通密码无法用于 SMTP,必须使用应用专用密码。

关键步骤详解

1. 条件触发

yaml
- name: Send build success email
  if: success()
  • if: success():仅当上一个步骤成功时执行
  • if: failure():仅当上一个步骤失败时执行
  • 确保成功和失败都能收到通知

2. 邮件配置

yaml
with:
  server_address: smtp.gmail.com   # Gmail SMTP 服务器
  server_port: 587                 # TLS 端口
  username: ${{ vars.GMAIL_SMTP_USER }}      # 发件人邮箱(Variable)
  password: ${{ secrets.GMAIL_SMTP_PASSWORD }} # SMTP 密码(Secret)
  to: ${{ vars.NOTIFY_EMAILS }}    # 收件人列表(Variable)
  from: "GitHub Actions <${{ vars.GMAIL_SMTP_USER }}>"

为什么用 Variable 而不用 Secret?

  • 邮箱地址和收件人列表不是敏感信息,可以使用 Variable
  • SMTP 密码是敏感信息,必须使用 Secret

3. 动态邮件内容

yaml
body: |
  🎉 Nuxt 项目构建成功!

  仓库:${{ github.repository }}
  版本:${{ steps.extract-version.outputs.version }}
  触发者:${{ github.actor }}
  时间:${{ github.event.repository.updated_at }}
  状态:✅ 成功

  详情:${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}

GitHub Context 说明:

Context说明示例
github.repository仓库名称owner/repo
github.actor触发者operator-username
github.run_id运行 ID26586293547
github.server_urlGitHub 服务器地址https://github.com
github.event.repository.updated_atRelease 更新时间2026-05-28T16:00:00Z

4. 多收件人支持

yaml
to: ${{ vars.NOTIFY_EMAILS }}

NOTIFY_EMAILS 支持多种格式:

bash
# 单个邮箱
admin@gmail.com

# 多个邮箱(逗号分隔)
admin@gmail.com,tech-lead@gmail.com,ops@gmail.com

# 带名称的多个邮箱
"Admin <admin@gmail.com>,Tech Lead <tech-lead@gmail.com>"

5. 构建与部署通知的区分

通知类型成功主题失败主题特有字段
构建✅ Nuxt 构建成功❌ Nuxt 构建失败
部署✅ Nuxt 部署成功❌ Nuxt 部署失败访问地址

运行流程

  1. 在 GitHub 仓库中创建新的 Release
  2. 第一部分:自动构建、打包、上传
  3. 构建成功 → 发送构建成功邮件
  4. 构建失败 → 发送构建失败邮件(含日志链接)
  5. 第二部分:自动部署(仅在构建成功时执行)
  6. 部署成功 → 发送部署成功邮件(含访问地址)
  7. 部署失败 → 发送部署失败邮件(需立即检查)

常见问题

Q: 邮件发送失败,提示 "At least one of 'to', 'cc' or 'bcc' must be specified"?

A: NOTIFY_EMAILS Variable 未配置或值为空。检查:

  • Variable 名称是否正确(区分大小写)
  • Variable 值是否为有效邮箱
  • 添加 Variable 后重新运行 workflow

Q: Gmail SMTP 认证失败,提示 "Username and Password not accepted"?

A: 可能原因及解决方案:

  • 未使用应用专用密码:生成应用专用密码
  • 账号未开启两步验证:需先开启
  • 密码复制不完整:重新生成并复制

Q: 如何测试邮件配置是否正确?

A: 可以临时添加一个测试步骤:

yaml
- name: Test email
  uses: dawidd6/action-send-mail@v3
  with:
    server_address: smtp.gmail.com
    server_port: 587
    username: ${{ vars.GMAIL_SMTP_USER }}
    password: ${{ secrets.GMAIL_SMTP_PASSWORD }}
    subject: "Test email from GitHub Actions"
    to: ${{ vars.NOTIFY_EMAILS }}
    from: "GitHub Actions <${{ vars.GMAIL_SMTP_USER }}>"
    body: |
      This is a test email to verify SMTP configuration.

Q: 能否使用其他邮件服务商(如 Outlook、QQ 邮箱)?

A: 可以,修改以下配置:

yaml
# Outlook
server_address: smtp-mail.outlook.com
server_port: 587

# QQ 邮箱
server_address: smtp.qq.com
server_port: 587

同时需要获取对应服务商的 SMTP 授权码。

总结

本文完成了系列文章的第三部分——邮件通知。通过配置 GitHub Actions,我们实现了:

  • 构建成功/失败自动发送邮件通知
  • 部署成功/失败自动发送邮件通知
  • 部署成功邮件包含访问地址
  • 失败邮件包含错误日志链接

至此,完整的 CI/CD 流水线已全部打通:

创建 Release

自动构建 → 发送构建通知

自动打包 → 上传 Release

自动部署 → PM2 重启

发送部署通知(含访问地址)

系列文章回顾

文章内容状态
第一篇构建与发布自动化✅ 已完成
第二篇远程部署自动化✅ 已完成
第三篇(本文)邮件通知✅ 已完成

三篇文章,从零搭建了一套完整的 Nuxt.js 项目 CI/CD 流水线!

💡 确认点

运行此 workflow 后,邮箱应收到两封邮件:构建通知和部署通知。部署成功邮件中应包含正确的访问地址。

附件

为了方便您查看完整的 release-bump.yaml 配置文件,以下提供完整内容供参考:

点击查看完整配置文件 release-bump.yaml
.github/workflows/release-bump.yaml
yaml
name: Auto Bump Version on Release

on:
  release:
    types: [created]  # 仅在创建新 Release 时触发

jobs:
  # Job 1: 构建和发布
  build-and-release:
    runs-on: ubuntu-latest
    permissions:
      contents: write  # 允许推送代码和创建 Release
    outputs:
      version: ${{ steps.extract-version.outputs.version }}
      project_name: ${{ steps.project-name.outputs.project_name }} # 传递给后续部署 Job

    steps:
      # 1. 检出代码
      - uses: actions/checkout@v6
        with:
          ref: ${{ github.event.release.target_commitish }}
          fetch-depth: 0

      # 2. 安装 pnpm
      - name: Install pnpm
        uses: pnpm/action-setup@v4

      # 3. 设置 Node.js
      - name: Setup Node.js
        uses: actions/setup-node@v5
        with:
          node-version: 20
          cache: 'pnpm'

      # 4. 安装依赖
      - name: Install dependencies
        run: pnpm install --frozen-lockfile

      # 5. 代码检查
      - name: Lint
        run: pnpm run lint

      # 6. 类型检查
      - name: Typecheck
        run: pnpm run typecheck

      # 7. 提取版本号
      - name: Extract Version
        id: extract-version
        run: |
          TAG=${GITHUB_REF#refs/tags/}
          VERSION=$(echo "$TAG" | sed 's/^v//')
          echo "version=$VERSION" >> $GITHUB_OUTPUT

      # 8. 提取项目名称(从 package.json 动态获取)
      - name: Extract Project Name
        id: project-name
        run: |
          PROJECT_NAME=$(node -p "require('./package.json').name")
          echo "project_name=$PROJECT_NAME" >> $GITHUB_OUTPUT

      # 9. 更新 package.json 版本号
      - name: Update Version
        run: |
          pnpm version ${{ steps.extract-version.outputs.version }} --no-git-tag-version
          cat package.json | grep version

      # 10. 构建 Nuxt.js 项目
      - name: Build Nuxt.js
        env:
          NODE_OPTIONS: "--max-old-space-size=4096"
        run: pnpm run build

      # 11. 创建压缩包(使用动态项目名称)
      - name: Create Distribution Archive
        run: |
          if [ ! -d ".output" ]; then
            echo "Error: .output directory not found!"
            exit 1
          fi

          echo "Contents of .output directory:"
          ls -la .output/

          PROJECT_NAME="${{ steps.project-name.outputs.project_name }}"
          VERSION="${{ steps.extract-version.outputs.version }}"

          tar -czf ${PROJECT_NAME}-${VERSION}.tar.gz -C .output .
          cd .output && zip -r ../${PROJECT_NAME}-${VERSION}.zip . && cd ..

          echo "Archive created successfully!"
          ls -la *.tar.gz *.zip

      # 12. 上传到 GitHub Release
      - name: Upload Release Assets
        uses: ncipollo/release-action@v1
        with:
          artifacts: "./${{ steps.project-name.outputs.project_name }}-${{ steps.extract-version.outputs.version }}.tar.gz,./${{ steps.project-name.outputs.project_name }}-${{ steps.extract-version.outputs.version }}.zip"
          allowUpdates: true
          omitBody: true
          omitName: true
          token: ${{ secrets.ACCESS_TOKEN }}

      # 13. 上传构建产物供后续 Job 使用
      - name: Upload Build Artifact
        uses: actions/upload-artifact@v7
        with:
          name: build-output
          path: ${{ steps.project-name.outputs.project_name }}-${{ steps.extract-version.outputs.version }}.tar.gz
          retention-days: 1
          if-no-files-found: error
          overwrite: true

      # 14. 提交版本号变更
      - name: Commit Changes
        run: |
          git config user.name "GitHub Actions"
          git config user.email "actions@github.com"
          git add package.json pnpm-lock.yaml
          git commit -m "chore(release): bump to ${{ steps.extract-version.outputs.version }} [skip ci]"
          git push origin HEAD:${{ github.event.release.target_commitish }}

      # 15. 构建成功邮件
      - name: Send build success email
        if: success()
        uses: dawidd6/action-send-mail@v3
        with:
          server_address: smtp.gmail.com
          server_port: 587
          username: ${{ vars.GMAIL_SMTP_USER }}
          password: ${{ secrets.GMAIL_SMTP_PASSWORD }}
          subject: "✅ Nuxt 构建成功 - ${{ github.repository }}"
          to: ${{ vars.NOTIFY_EMAILS }}
          from: "GitHub Actions <${{ vars.GMAIL_SMTP_USER }}>"
          body: |
            🎉 Nuxt 项目构建成功!

            仓库:${{ github.repository }}
            版本:${{ steps.extract-version.outputs.version }}
            触发者:${{ github.actor }}
            时间:${{ github.event.repository.updated_at }}
            状态:✅ 成功

            详情:${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}

      # 16. 构建失败邮件
      - name: Send build failure email
        if: failure()
        uses: dawidd6/action-send-mail@v3
        with:
          server_address: smtp.gmail.com
          server_port: 587
          username: ${{ vars.GMAIL_SMTP_USER }}
          password: ${{ secrets.GMAIL_SMTP_PASSWORD }}
          subject: "❌ Nuxt 构建失败 - ${{ github.repository }}"
          to: ${{ vars.NOTIFY_EMAILS }}
          from: "GitHub Actions <${{ vars.GMAIL_SMTP_USER }}>"
          body: |
            🚨 Nuxt 项目构建失败,请立即检查!

            仓库:${{ github.repository }}
            版本:${{ steps.extract-version.outputs.version }}
            触发者:${{ github.actor }}
            时间:${{ github.event.repository.updated_at }}
            状态:❌ 失败

            详情:${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
            请点击上方链接查看详细错误信息。

  # Job 2: 远程部署
  remote-deploy:
    runs-on: ubuntu-latest
    needs: build-and-release  # 等待构建完成
    if: github.event_name == 'release' && success()
    permissions:
      actions: read  # 允许下载 artifacts

    steps:
      # 1. 下载构建产物
      - name: Download Artifact
        uses: actions/download-artifact@v8
        with:
          name: build-output
          path: ./

      # 2. 解压 artifact
      - name: Extract Artifact
        run: |
          echo "Contents before extract:"
          ls -la
          echo ""
          echo "Extracting tar.gz..."
          # 直接解压到当前目录,包含 nitro.json 文件及 public、server 目录
          tar -xzf ${{ needs.build-and-release.outputs.project_name }}-${{ needs.build-and-release.outputs.version }}.tar.gz
          echo "Extracted contents:"
          ls -la
          echo "Total files: $(find . -maxdepth 1 -type f | wc -l)"

      # 3. 验证提取的内容
      - name: Verify Extracted Content
        run: |
          if [ ! -f "nitro.json" ]; then
            echo "ERROR: nitro.json not found after extraction!"
            exit 1
          fi
          echo "✅ Artifact extracted successfully"

      # 4. SCP 传输到服务器(传输当前目录下的所有文件)
      - name: Deploy to Server
        uses: appleboy/scp-action@v0.1.7
        with:
          host: ${{ secrets.DEPLOY_HOST }}
          username: ${{ secrets.DEPLOY_USER }}
          key: ${{ secrets.DEPLOY_SSH_KEY }}
          port: ${{ secrets.DEPLOY_PORT || 22 }}
          source: "./"  # 传输当前目录下的所有内容
          target: "/tmp/${{ needs.build-and-release.outputs.project_name }}-build-${{ needs.build-and-release.outputs.version }}/"

      # 5. SSH 执行远程部署
      - name: Execute Remote Deployment
        uses: appleboy/ssh-action@v1.2.0
        with:
          host: ${{ secrets.DEPLOY_HOST }}
          username: ${{ secrets.DEPLOY_USER }}
          key: ${{ secrets.DEPLOY_SSH_KEY }}
          port: ${{ secrets.DEPLOY_PORT || 22 }}
          script: |
            set -e  # 遇到错误立即退出

            PROJECT_NAME="${{ needs.build-and-release.outputs.project_name }}"
            VERSION="${{ needs.build-and-release.outputs.version }}"
            DEPLOY_DIR="/var/www/${PROJECT_NAME}"
            BUILD_DIR="/tmp/${PROJECT_NAME}-build-${VERSION}"

            echo "=========================================="
            echo "Deploying ${PROJECT_NAME} version ${VERSION}"
            echo "=========================================="

            # 1. 备份当前版本
            if [ -d "$DEPLOY_DIR" ]; then
              BACKUP_DIR="/var/www/${PROJECT_NAME}-backup-$(date +%Y%m%d_%H%M%S)"
              echo "📦 Creating backup: ${BACKUP_DIR}"
              cp -r "$DEPLOY_DIR" "$BACKUP_DIR"
              # 保留最近 5 个备份
              ls -t /var/www/${PROJECT_NAME}-backup-* 2>/dev/null | tail -n +6 | xargs rm -rf || true
            else
              echo "📁 Creating deployment directory: ${DEPLOY_DIR}"
              mkdir -p "$DEPLOY_DIR"
            fi

            # 2. 部署新文件
            # 注意:解压后文件直接在 BUILD_DIR 下,没有 .output 层
            echo "📤 Deploying files..."
            rm -rf ${DEPLOY_DIR}/*
            cp -r ${BUILD_DIR}/* ${DEPLOY_DIR}/

            # 3. 设置权限
            chown -R www-data:www-data ${DEPLOY_DIR}
            chmod -R 755 ${DEPLOY_DIR}

            # 4. 重启 PM2 服务
            echo "🔄 Restarting PM2 service..."
            pm2 restart ${PROJECT_NAME}

            # 5. 清理临时文件
            echo "🧹 Cleaning up..."
            rm -rf ${BUILD_DIR}

            # 6. 显示部署结果
            echo "=========================================="
            echo "✅ Deployment completed successfully!"
            echo "📍 Deployed to: ${DEPLOY_DIR}"
            echo "📌 Version: ${VERSION}"
            echo "=========================================="
            pm2 status ${PROJECT_NAME}

      # 6. 输出部署概览
      - name: Build Summary
        run: |
          echo "=========================================="
          echo "🎉 DEPLOYMENT SUMMARY"
          echo "=========================================="
          echo "Project: ${{ needs.build-and-release.outputs.project_name }}"
          echo "Version: ${{ needs.build-and-release.outputs.version }}"
          echo "Status: ${{ job.status }}"
          echo ""
          echo "📊 Directory Statistics:"
          echo "  JSON files (root): $(find . -maxdepth 1 -type f -name "*.json" | wc -l) files"
          echo "  Total directories (root): $(find . -maxdepth 1 -type d | wc -l) directories"
          echo ""
          echo "🔍 Key Files Check:"
          echo "  nitro.json: $([ -f "nitro.json" ] && echo '✅ YES' || echo '❌ NO')"
          echo "  public/: $([ -d "public" ] && echo '✅ EXISTS' || echo '❌ NOT FOUND')"
          echo "  server/: $([ -d "server" ] && echo '✅ EXISTS' || echo '❌ NOT FOUND')"
          echo ""
          echo "⏱️  Time: $(date)"
          echo "=========================================="

      # 7. 部署成功邮件
      - name: Send deploy success email
        if: success()
        uses: dawidd6/action-send-mail@v3
        with:
          server_address: smtp.gmail.com
          server_port: 587
          username: ${{ vars.GMAIL_SMTP_USER }}
          password: ${{ secrets.GMAIL_SMTP_PASSWORD }}
          subject: "✅ Nuxt 部署成功 - ${{ github.repository }}"
          to: ${{ vars.NOTIFY_EMAILS }}
          from: "GitHub Actions <${{ vars.GMAIL_SMTP_USER }}>"
          body: |
            🎉 Nuxt 项目部署成功!

            仓库:${{ github.repository }}
            版本:${{ needs.build-and-release.outputs.version }}
            触发者:${{ github.actor }}
            时间:${{ github.event.repository.updated_at }}
            状态:✅ 成功

            🌐 访问地址:${{ vars.DEPLOY_WEBSITE_DOMAIN }}
            详情:${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}

      # 8. 部署失败邮件
      - name: Send deploy failure email
        if: failure()
        uses: dawidd6/action-send-mail@v3
        with:
          server_address: smtp.gmail.com
          server_port: 587
          username: ${{ vars.GMAIL_SMTP_USER }}
          password: ${{ secrets.GMAIL_SMTP_PASSWORD }}
          subject: "❌ Nuxt 部署失败 - ${{ github.repository }}"
          to: ${{ vars.NOTIFY_EMAILS }}
          from: "GitHub Actions <${{ vars.GMAIL_SMTP_USER }}>"
          body: |
            🚨 Nuxt 项目部署失败,请立即检查!

            仓库:${{ github.repository }}
            版本:${{ needs.build-and-release.outputs.version }}
            触发者:${{ github.actor }}
            时间:${{ github.event.repository.updated_at }}
            状态:❌ 失败

            详情:${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
            请点击上方链接查看详细错误信息。