te')); return $arr; } /* 遍历用户所有主题 * @param $uid 用户ID * @param int $page 页数 * @param int $pagesize 每页记录条数 * @param bool $desc 排序方式 TRUE降序 FALSE升序 * @param string $key 返回的数组用那一列的值作为 key * @param array $col 查询哪些列 */ function thread_tid_find_by_uid($uid, $page = 1, $pagesize = 1000, $desc = TRUE, $key = 'tid', $col = array()) { if (empty($uid)) return array(); $orderby = TRUE == $desc ? -1 : 1; $arr = thread_tid__find($cond = array('uid' => $uid), array('tid' => $orderby), $page, $pagesize, $key, $col); return $arr; } // 遍历栏目下tid 支持数组 $fid = array(1,2,3) function thread_tid_find_by_fid($fid, $page = 1, $pagesize = 1000, $desc = TRUE) { if (empty($fid)) return array(); $orderby = TRUE == $desc ? -1 : 1; $arr = thread_tid__find($cond = array('fid' => $fid), array('tid' => $orderby), $page, $pagesize, 'tid', array('tid', 'verify_date')); return $arr; } function thread_tid_delete($tid) { if (empty($tid)) return FALSE; $r = thread_tid__delete(array('tid' => $tid)); return $r; } function thread_tid_count() { $n = thread_tid__count(); return $n; } // 统计用户主题数 大数量下严谨使用非主键统计 function thread_uid_count($uid) { $n = thread_tid__count(array('uid' => $uid)); return $n; } // 统计栏目主题数 大数量下严谨使用非主键统计 function thread_fid_count($fid) { $n = thread_tid__count(array('fid' => $fid)); return $n; } ?>javascript - Remove an attachment of a Gmail email with Google Apps Script - Stack Overflow
最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Remove an attachment of a Gmail email with Google Apps Script - Stack Overflow

programmeradmin3浏览0评论

Using Google Apps Script (), I know from the docs, how to send, forward, move to trash messages, etc. but I don't find how to remove a file attachement of an email, i.e.:

  1. keep the text content (either in HTML or just plain text would be fine)
  2. keep the original sender, keep the recipient
  3. keep the original message date/hour (important!)
  4. remove the attachment

If it's not possible via the API, is there a way to resend the message to myself, while keeping 1, 2 and 3?


Note: the GmailAttachment class looks interesting and allows to list recipients:

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());
     }
   }
 }

but I don't find how to remove an attachment.

Note: I've already studied many other solutions for doing this, I've already read nearly every article about this (solutions with dedicated web services, with local clients like Thunderbird + Attachment extractor plugin, etc.), but none of them are really really cool. That's why I was looking for a solution to do it manually via Google Apps Script.

Using Google Apps Script (http://script.google.), I know from the docs, how to send, forward, move to trash messages, etc. but I don't find how to remove a file attachement of an email, i.e.:

  1. keep the text content (either in HTML or just plain text would be fine)
  2. keep the original sender, keep the recipient
  3. keep the original message date/hour (important!)
  4. remove the attachment

If it's not possible via the API, is there a way to resend the message to myself, while keeping 1, 2 and 3?


Note: the GmailAttachment class looks interesting and allows to list recipients:

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());
     }
   }
 }

but I don't find how to remove an attachment.

Note: I've already studied many other solutions for doing this, I've already read nearly every article about this (solutions with dedicated web services, with local clients like Thunderbird + Attachment extractor plugin, etc.), but none of them are really really cool. That's why I was looking for a solution to do it manually via Google Apps Script.

Share Improve this question edited Oct 3, 2017 at 19:56 Basj asked Sep 26, 2017 at 19:28 BasjBasj 46.6k110 gold badges452 silver badges801 bronze badges 1
  • Can you provide fiddle? – artgb Commented Oct 5, 2017 at 17:06
Add a ment  | 

2 Answers 2

Reset to default 13 +150

Looks like messages will have to be re-created-ish:

Messages are immutable: they can only be created and deleted. No message properties can be changed other than the labels applied to a given message.

Using Advanced Gmail Service with the Gmail API insert() you can hack your way around it using: Gmail.Users.Messages.insert(resource, userId)

This advanced service must be enabled before use.

Example: [fill in the EMAIL_ID with an email_id or in whatever way you want to get the email]

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)
}

This will remove the attachments from the email and re-insert it into your mailbox.

edit/update: New RegExp to work with html&plain-text only emails - should now work on multiple boundary strings

"is there a way to resend the message to myself, while keeping 1, 2 and 3?"

Yes, I decided to e up with a Python solution which mostly follows the answer by random-parts.

The full code is available here: https://gist.github./davidair/cac8a7fb130959b3110ef29aa7d0bbac

The key ponent is calling insert(), same as in the original answer:

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

My tool makes it easier to find messages (just passing in Gmail queries) and removing attachments in bulk. The tool also saves original messages locally and trashes them on Gmail (so they will eventually be removed).

The code has been tested but just barely, so use at your own risk. Requires a GCP project (Gist has some pointers on setup in the description).

More information: the full implementation has two main mands: find_emails and remove_attachments. You first call find_emails passing in a search query, so you should be able to call it with label:remove_attachment, and using the -o flag will print email ids as ma-separated. Second, you call remove_attachments with the ma-separated list of ids, and it will download emails, strip attachments and then trash/recreate them. You have to pass the --make-changes flag to actually do the deletion, otherwise it will download emails and cache them locally but not make changes (it's a safety feature)

发布评论

评论列表(0)

  1. 暂无评论