当前位置: 首页 记笔 使用Google Apps Script服务推送gmail邮件

在v2ex上看到可以曲线的方法推送邮件,经过测试也是推送比较及时,除了默认的定时触发器外限制每分钟执行几乎也没什么延迟,当然也可以修改脚本文件内置定时器来更频繁的检查新邮件信息。

访问script.google.com链接,新建项目,然后复制下面的脚本文件粘贴到脚本中,只需修改配置项 WEBHOOK_URL 推送链接即可,Ctrl+S保存文件,直接点击运行(不用点击部署)。

首次运行会弹出谷歌授权窗口,全部允许后(Gmail和外部连接权限)会返回之前的页面开始执行,底部可以查看执行日志。

20251012162806.png

准备就绪,可以在左侧边栏找到设置触发器定时任务,选择分钟执行器,每分钟执行一次,其它默认或按需设置。

点击保存会再次跳出谷歌授权页面,也是全部允许就可以。等待一分钟,可以在左侧边栏找到 脚本执行 页面查看自动化执行的日志信息。

一切正常可以关闭页面了,后续会按照配置的定时触发器自动化执行,不用点击部署。

/**
 * Gmail 未读邮件推送脚本
 * 功能:获取收件箱中的未读邮件,将主题和正文推送到指定 Webhook,并标记为已读
 */

// ========== 配置项 ==========
var WEBHOOK_URL = 'https://WEBHOOK_URL';
// ============================

function pushUnreadEmails() {
  try {
    // 查询收件箱中的未读邮件
    var query = 'in:inbox is:unread';
    var threads = GmailApp.search(query);
    
    // 如果没有未读邮件
    if (threads.length === 0) {
      Logger.log('没有未读邮件');
      return;
    }
    
    Logger.log('找到 ' + threads.length + ' 个未读邮件线程');
    
    var totalMessages = 0;
    var successCount = 0;
    
    // 遍历每个邮件线程
    for (var i = 0; i < threads.length; i++) {
      var messages = threads[i].getMessages();
      
      // 遍历线程中的每封邮件
      for (var j = 0; j < messages.length; j++) {
        var message = messages[j];
        
        // 只处理未读邮件
        if (message.isUnread()) {
          totalMessages++;
          
          // 获取邮件主题
          var subject = message.getSubject();
          
          // 获取邮件正文(HTML)
          var body = message.getBody();
          
          // 去除 HTML 标签,提取纯文本
          body = stripHTMLTags(body);
          
          // 获取发件人和收件人
          var from = message.getFrom();
          var to = message.getTo();
          
          // 转义尖括号,防止在 Webhook 接收端被当作 HTML 标签
          from = from.replace(/</g, '&lt;').replace(/>/g, '&gt;');
          
          // 获取邮件接收时间
          var date = message.getDate();
          var dateStr = Utilities.formatDate(date, Session.getScriptTimeZone(), 'yyyy-MM-dd HH:mm:ss');
          
          // 检查是否有附件
          var attachments = message.getAttachments();
          if (attachments.length > 0) {
            body += '\n\n[提示:此邮件包含 ' + attachments.length + ' 个附件]';
            Logger.log('处理邮件 ' + totalMessages + ': ' + subject + ' (包含 ' + attachments.length + ' 个附件)');
          } else {
            Logger.log('处理邮件 ' + totalMessages + ': ' + subject);
          }
          
          // 在正文底部添加发件人、收件人和时间信息
          body += '\n\n---\n发件人: ' + from + '\n收件人: ' + to + '\n时间: ' + dateStr;
          
          // 推送到 Webhook
          var pushed = pushToWebhook(subject, body);
          
          if (pushed) {
            // 推送成功后标记为已读
            message.markRead();
            successCount++;
            Logger.log('  ✓ 推送成功并已标记为已读');
          } else {
            Logger.log('  ✗ 推送失败');
          }
        }
      }
    }
    
    Logger.log('所有未读邮件已处理完毕');
    Logger.log('共处理 ' + totalMessages + ' 封邮件,成功推送 ' + successCount + ' 封');
    
  } catch (error) {
    Logger.log('执行出错: ' + error.toString());
  }
}

/**
 * 去除 HTML 标签,提取纯文本内容
 * @param {string} htmlContent - HTML 内容
 * @return {string} - 纯文本内容
 */
function stripHTMLTags(htmlContent) {
  if (!htmlContent) {
    return '';
  }
  
  var content = htmlContent;
  
  // 1. 去除 <style> 标签及其内容(包括 CSS)
  content = content.replace(/<style[^>]*>[\s\S]*?<\/style>/gi, '');
  
  // 2. 去除 <script> 标签及其内容(JavaScript)
  content = content.replace(/<script[^>]*>[\s\S]*?<\/script>/gi, '');
  
  // 3. 去除 HTML 注释
  content = content.replace(/<!--[\s\S]*?-->/g, '');
  
  // 4. 将 <br>、<br/>、</p>、</div> 等换行标签替换为换行符
  content = content.replace(/<br\s*\/?>/gi, '\n');
  content = content.replace(/<\/p>/gi, '\n');
  content = content.replace(/<\/div>/gi, '\n');
  
  // 5. 去除所有 HTML 标签
  content = content.replace(/<[^>]*>/g, '');
  
  // 6. 解码 HTML 实体
  content = decodeHTMLEntities(content);
  
  // 7. 清理空白字符 - 将多个连续换行替换为单个换行
  content = content.replace(/\n\s*\n\s*\n+/g, '\n');
  
  // 8. 去除每行前后的空格,并过滤空行
  var lines = content.split('\n');
  var cleanLines = [];
  for (var i = 0; i < lines.length; i++) {
    var line = lines[i].trim();
    if (line !== '') {
      cleanLines.push(line);
    }
  }
  content = cleanLines.join('\n');
  
  // 9. 去除首尾空白
  content = content.trim();
  
  return content;
}

/**
 * 解码 HTML 实体
 * @param {string} text - 包含 HTML 实体的文本
 * @return {string} - 解码后的文本
 */
function decodeHTMLEntities(text) {
  var entities = {
    '&nbsp;': ' ',
    '&amp;': '&',
    '&lt;': '<',
    '&gt;': '>',
    '&quot;': '"',
    '&#39;': "'",
    '&apos;': "'",
    '&cent;': '¢',
    '&pound;': '£',
    '&yen;': '¥',
    '&euro;': '€',
    '&copy;': '©',
    '&reg;': '®',
    '&hellip;': '...',
    '&mdash;': '-',
    '&ndash;': '-',
    '&lsquo;': "'",
    '&rsquo;': "'",
    '&ldquo;': '"',
    '&rdquo;': '"'
  };
  
  var result = text;
  for (var entity in entities) {
    result = result.replace(new RegExp(entity, 'g'), entities[entity]);
  }
  
  // 解码数字实体(如 &#123; 或 &#x7B;)
  result = result.replace(/&#(\d+);/g, function(match, dec) {
    return String.fromCharCode(dec);
  });
  result = result.replace(/&#x([0-9a-f]+);/gi, function(match, hex) {
    return String.fromCharCode(parseInt(hex, 16));
  });
  
  return result;
}

/**
 * 推送邮件内容到 Webhook
 * @param {string} title - 邮件主题
 * @param {string} msg - 邮件正文
 * @return {boolean} - 是否推送成功
 */
function pushToWebhook(title, msg) {
  try {
    // 构建表单数据
    var payload = {
      'title': title,
      'msg': msg
    };
    
    // 发送 POST 请求
    var options = {
      'method': 'post',
      'payload': payload,
      'muteHttpExceptions': true  // 忽略 HTTP 异常,继续执行
    };
    
    var response = UrlFetchApp.fetch(WEBHOOK_URL, options);
    
    var statusCode = response.getResponseCode();
    var content = response.getContentText();
    
    // 输出返回值
    Logger.log('    返回: [' + statusCode + '] ' + content);
    
    // 只有状态码为 200 才算推送成功
    return statusCode === 200;
    
  } catch (error) {
    Logger.log('    推送异常: ' + error.toString());
    return false;
  }
} 

Special Thanks To:
利用谷歌的 GAS 转发 gmail 邮件到 tg
国内最优雅的收取 google voice 短信的方式

标签:无

使用Google Apps Script服务推送gmail邮件》 © 2025 by 吃蛋的小子 依据 CC BY-SA 4.0 许可协议授权

你的评论