如何使用Gmail API发送回复

12
我有两个Gmail账户。我创建了一个包含五个邮件的线程,并在此页面https://developers.google.com/gmail/api/v1/reference/users/threads/get中使用Gmail gapi检索了它们。
这是我的结果: enter image description here 如您所见,虽然它们标识完全相同的信件,但ID不匹配。为什么会这样,并且我该如何获取统一的ID呢?
顺便说一下,我这么做的真正原因是我需要使用Gmail API回复邮件,但是要这样做,您需要知道要回复的邮件的ID。如果我回复具有我拥有的ID(而不是接收者拥有的邮件ID),它只会发送“新”邮件。
我该如何使用Gmail API发送回复邮件呢?
非常感谢。

你想回复单个消息还是回复整个讨论串? - Tholle
我想要回复一条单独的消息。 - Vlas Bashynskyi
2个回答

43

根据文档,如果您想要发送回复并使邮件进入同一线程,请确保:

  1. Subject标题相同。
  2. ReferencesIn-Reply-To头遵循RFC 2822标准。

如果您想自己完成此操作,可以获取要回复的消息的SubjectReferencesMessage-ID头:

请求:

userId = me
id = 14fd1c555a1352b7 // id of the message I want to respond to.
format = metadata
metadataHeaders = Subject,References,Message-ID

GET https://www.googleapis.com/gmail/v1/users/me/messages/14fd1c555a1352b7?format=metadata&metadataHeaders=Subject&metadataHeaders=References&metadataHeaders=Message-ID

响应:

{
 "id": "14fd1c555a1352b7",
 "threadId": "14fd1c52911f0f64",
 "labelIds": [
  "SENT",
  "INBOX",
  "IMPORTANT",
  "UNREAD"
 ],
 "snippet": "Next level dude 2015-09-15 18:10 GMT+02:00 Emil Tholin <emtholin@gmail.com>: wow 2015-09-15 18:",
 "historyId": "575289",
 "internalDate": "1442333414000",
 "payload": {
  "mimeType": "multipart/alternative",
  "headers": [
   {
    "name": "In-Reply-To",
    "value": "<CADsZLRyzVPLRQuTthGSHKMCXL7Ora1jNW7h0jvoNgR+hU59BYg@mail.gmail.com>"
   },
   {
    "name": "References",
    "value": "<CADsZLRxZDUGn4Frx80qe2_bE5H5bQhgcqGk=GwFN9gs7Z_8oZw@mail.gmail.com> <CADsZLRyzVPLRQuTthGSHKMCXL7Ora1jNW7h0jvoNgR+hU59BYg@mail.gmail.com>"
   },
   {
    "name": "Message-ID", // This is the same for both users, as you were asking about.
    "value": "<CADsZLRwQWzLB-uq4_4G2E64NX9G6grn0cEeO0L=avY7ajzuAFg@mail.gmail.com>"
   },
   {
    "name": "Subject",
    "value": "Re: Cool"
   }
  ]
 },
 "sizeEstimate": 1890
}
为遵循RFC2822标准,我们已将要回复的邮件的Message-ID添加到References标头中,并用空格分隔。In-Reply-To标头也具有我们要回复的邮件的值。我们还在Subject标头中添加了Re:以表示这是一封回复邮件。
// Base64-encode the mail and make it URL-safe 
// (replace "+" with "-", replace "/" with "_", remove trailing "=")
var encodedResponse = btoa(
  "Content-Type: text/plain; charset=\"UTF-8\"\n" +
  "MIME-Version: 1.0\n" +
  "Content-Transfer-Encoding: 7bit\n" +
  "References: <CADsZLRxZDUGn4Frx80qe2_bE5H5bQhgcqGk=GwFN9gs7Z_8oZw@mail.gmail.com> <CADsZLRyzVPLRQuTthGSHKMCXL7Ora1jNW7h0jvoNgR+hU59BYg@mail.gmail.com> <CADsZLRwQWzLB-uq4_4G2E64NX9G6grn0cEeO0L=avY7ajzuAFg@mail.gmail.com>\n" +
  "In-Reply-To: <CADsZLRwQWzLB-uq4_4G2E64NX9G6grn0cEeO0L=avY7ajzuAFg@mail.gmail.com>\n" +
  "Subject: Re:Cool\n" +
  "From: sender@gmail.com\n" +
  "To: reciever@gmail.com\n\n" +

  "This is where the response text will go"
).replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '');

$.ajax({
  url: "https://www.googleapis.com/gmail/v1/users/me/messages/send?access_token=<USER_ACCESS_TOKEN>",
  method: "POST",
  contentType: "application/json",
  data: JSON.stringify({
    raw: encodedResponse
  })
});

正如你所看到的,这是一个手动繁琐的过程。你也可以简单地回复该线程。然而,这可能不足以满足你的使用情况。

通过这种方式,你只需要提供邮件和threadId,并确保Subject相同,Google会正确地为你显示它。

// Base64-encode the mail and make it URL-safe 
// (replace "+" with "-", replace "/" with "_", remove trailing "=")
var encodedResponse = btoa(
  "Content-Type: text/plain; charset=\"UTF-8\"\n" +
  "MIME-Version: 1.0\n" +
  "Content-Transfer-Encoding: 7bit\n" +
  "Subject: Subject of the original mail\n" +
  "From: sender@gmail.com\n" +
  "To: reciever@gmail.com\n\n" +

  "This is where the response text will go"
).replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '');

$.ajax({
  url: "https://www.googleapis.com/gmail/v1/users/me/messages/send?access_token=<USER_ACCESS_TOKEN>",
  method: "POST",
  contentType: "application/json",
  data: JSON.stringify({           
    raw: encodedResponse,
    threadId: "<THREAD_ID_OF_MESSAGE_TO_RESPOND_TO>"
  })
});

1
我尝试了你给出的第一个解决方案,但是我收到了两封邮件。一封是作为邮件线程的一部分,另一封是新的。第二种方法失败并显示“无效参数”错误。我正在尝试将草稿添加到线程中,但迄今为止没有成功。Google API文档似乎也不正确。 - vikramaditya234
1
@vikramaditya234 你可以尝试 这个链接 - Tholle
如果我想回复的现有消息没有参考/回复头,会发生什么?https://stackoverflow.com/questions/44880439/trying-to-reply-to-an-existing-email-with-gmail-api - Tal Avissar
将threadid传递到消息对象中对我来说是有效的,实际上,这个方法唯一的问题是如果我设置了一个新主题,那么主题将不会得到更新,这很奇怪。 - WtFudgE
我想知道在sendMessage之后立即使用get方法是否可以获取到消息,或者这是一个异步过程,消息不会立即可用。我问这个问题是因为我想在发送后立即将消息ID头保存在数据库中。 - Gal Morad
显示剩余3条评论

4

@Tholle(谢谢!)的答案是正确的,让我走上了正确的轨道,但是最近发生了一些变化:

https://gsuiteupdates.googleblog.com/2019/03/threading-changes-in-gmail-conversation-view.html

我必须合并他的两个路径。
在我的程序中,我需要回复一个线程,但如果我只包含线程ID(如#2),新消息仅会在Gmail的回复者邮件中置于线程中,而在原始发送者(也是Gmail)的邮件中则显示为新线程。
我通过同时包含threadId和标题“References”和“In-Reply-To”以及最后一条消息的id来解决了这个问题。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接