mail.js 2.44 KB
import nodemailer from 'nodemailer'
import fs from 'fs'
import path from 'path'
import { fileURLToPath } from 'url'

const __dirname = path.dirname(fileURLToPath(import.meta.url))
const SMTP_CONFIG_FILE = path.join(__dirname, '..', 'smtp-config.json')

// 读取SMTP配置
export function loadSmtpConfig() {
  try {
    if (fs.existsSync(SMTP_CONFIG_FILE)) {
      return JSON.parse(fs.readFileSync(SMTP_CONFIG_FILE, 'utf-8'))
    }
  } catch (e) {
    console.error('读取SMTP配置失败:', e.message)
  }
  return null
}

// 保存SMTP配置
export function saveSmtpConfig(config) {
  fs.writeFileSync(SMTP_CONFIG_FILE, JSON.stringify(config, null, 2), 'utf-8')
}

// 创建邮件传输器
function createTransporter(config) {
  return nodemailer.createTransport({
    host: config.host,
    port: Number(config.port) || 465,
    secure: Number(config.port) === 465, // 465为SSL,587为TLS
    auth: {
      user: config.user,
      pass: config.pass,
    },
  })
}

// 测试SMTP连接
export async function testSmtpConnection(config) {
  try {
    const transporter = createTransporter(config)
    await transporter.verify()
    transporter.close()
    return { success: true, message: 'SMTP连接测试成功' }
  } catch (e) {
    return { success: false, message: `SMTP连接失败: ${e.message}` }
  }
}

/**
 * 发送报表邮件
 * @param {Object} options
 * @param {string} options.to - 收件人,多个用逗号分隔
 * @param {string} options.subject - 邮件主题
 * @param {string} options.html - 邮件正文HTML
 * @param {Buffer} options.excelBuffer - Excel文件Buffer
 * @param {string} options.fileName - 附件文件名
 */
export async function sendReportMail({ to, subject, html, excelBuffer, fileName }) {
  const config = loadSmtpConfig()
  if (!config) {
    throw new Error('未配置SMTP邮件服务,请先在"邮件配置"中设置')
  }

  const transporter = createTransporter(config)

  try {
    const result = await transporter.sendMail({
      from: `"${config.senderName || 'SQL报表工具'}" <${config.user}>`,
      to,
      subject,
      html,
      attachments: [
        {
          filename: fileName || 'report.xlsx',
          content: excelBuffer,
          contentType: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
        },
      ],
    })
    return { success: true, messageId: result.messageId }
  } catch (e) {
    throw new Error(`邮件发送失败: ${e.message}`)
  } finally {
    transporter.close()
  }
}