使用 Google Apps 脚本删除 Gmail 电子邮件的附件

问题描述 投票:0回答:2

使用 Google Apps 脚本 (http://script.google.com),我从 文档知道如何发送、转发、移至垃圾邮件等,但我没有找到 如何删除电子邮件的文件附件,即:

  1. 保留文本内容(HTML 或纯文本都可以)
  2. 保留原始发件人,保留收件人
  3. 保留原始消息日期/时间(重要!)
  4. 删除附件

如果无法通过 API 实现,有没有办法将消息重新发送给自己,同时保留 1、2 和 3?


注意:

GmailAttachment
类看起来很有趣,并允许列出收件人:

var threads = GmailApp.getInboxThreads(0, 10);
 var msgs = GmailApp.getMessagesForThreads(threads);
 for (var i = 0 ; i < msgs.length; i++) {
   for (var j = 0; j < msgs[i].length; j++) {
     var attachments = msgs[i][j].getAttachments();
     for (var k = 0; k < attachments.length; k++) {
       Logger.log('Message "%s" contains the attachment "%s" (%s bytes)',
                  msgs[i][j].getSubject(), attachments[k].getName(), attachments[k].getSize());
     }
   }
 }

但我不知道如何删除附件。

注意:我已经研究了许多其他解决方案来执行此操作,我已经阅读了几乎所有关于此的文章(具有专用 Web 服务的解决方案,具有本地客户端,如 Thunderbird + 附件提取器插件等),但没有一个他们真的很酷。这就是为什么我正在寻找一种通过 Google Apps 脚本手动执行此操作的解决方案。

javascript email google-apps-script gmail gmail-api
2个回答
10
投票

看起来消息必须被重新创建

消息是不可变的:它们只能被创建和删除。除了应用于给定消息的标签之外,无法更改任何消息属性。

使用高级 Gmail 服务Gmail API insert(),您可以使用以下方法破解它:

Gmail.Users.Messages.insert(resource, userId)

此高级服务必须在使用前启用

示例:[用

EMAIL_ID
或您想要获取电子邮件的任何方式填写
email_id
]

function removeAttachments () {
  // Get the `raw` email
  var email = GmailApp.getMessageById("EMAIL_ID").getRawContent();

  // Find the end boundary of html or plain-text email
  var re_html = /(-*\w*)(\r)*(\n)*(?=Content-Type: text\/html;)/.exec(email);
  var re = re_html || /(-*\w*)(\r)*(\n)*(?=Content-Type: text\/plain;)/.exec(email);

  // Find the index of the end of message boundary
  var start = re[1].length + re.index;
  var boundary = email.indexOf(re[1], start);

  // Remove the attachments & Encode the attachment-free RFC 2822 formatted email string
  var base64_encoded_email = Utilities.base64EncodeWebSafe(email.substr(0, boundary));
  // Set the base64Encoded string to the `raw` required property
  var resource = {'raw': base64_encoded_email}

  // Re-insert the email into the user gmail account with the insert time
  /* var response = Gmail.Users.Messages.insert(resource, 'me'); */

  // Re-insert the email with the original date/time 
  var response = Gmail.Users.Messages.insert(resource, 'me', 
                      null, {'internalDateSource': 'dateHeader'});

  Logger.log("The inserted email id is: %s",response.id)
}

这将从电子邮件中删除附件并将其重新插入您的邮箱。

编辑/更新: 新的正则表达式仅适用于 html 和纯文本电子邮件 - 现在应该适用于多个边界字符串


0
投票

这有点题外话,但既然OP说“如果无法通过API实现,有没有办法在保留1、2和3的同时将消息重新发送给自己?”我决定提出使用Python解决方案,该解决方案主要遵循random-parts的答案。

完整代码可在此处获取:https://gist.github.com/davidair/cac8a7fb130959b3110ef29aa7d0bbac

关键组件是调用 insert(),与原始答案相同:

    raw_message = urlsafe_b64encode(modified_message.as_bytes()).decode()
    service.users().messages().insert(
        userId='me',
        body={'raw': raw_message},
        internalDateSource='dateHeader'
    ).execute()

我的工具可以更轻松地查找邮件(只需传递 Gmail 查询)和批量删除附件。该工具还会在本地保存原始邮件将其丢弃在 Gmail 上(因此它们最终将被删除)。

代码已经过测试,但只是勉强测试,因此使用风险自负。需要 GCP 项目(Gist 在描述中提供了一些有关设置的指示)。

© www.soinside.com 2019 - 2024. All rights reserved.