如何使用 Gmail API 发送回复

Posted

技术标签:

【中文标题】如何使用 Gmail API 发送回复【英文标题】:How To Send A Reply With Gmail API 【发布时间】:2015-12-11 21:52:15 【问题描述】:

我有两个 gmail 帐户,我创建了一个包含 5 条消息的线程,并在此页面 https://developers.google.com/gmail/api/v1/reference/users/threads/get 上使用 gmail gapi 检索了它们。

这是我得到的:

如您所见,尽管标识完全相同的字母,但 id 并不匹配。为什么会发生这种情况,我怎样才能获得统一的 id?

附:我这样做的真正原因是我需要使用 gmail API 发送对消息的回复,但要做到这一点,您需要知道您回复的消息的 ID。如果我用我拥有的 id(不是接收者拥有的消息 id)回复消息,它只会发送一条“新”消息。

提前谢谢你。

【问题讨论】:

您要回复单个消息还是回复主题? 我想回复一条消息。 【参考方案1】:

作为docs say,如果您尝试发送回复并希望将电子邮件发送到线程中,请确保:

    Subject 标头匹配 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

为了遵循 RFC 2822 标准,我们在References-header 中添加了我们想要响应的消息的Message-ID,并用空格分隔。 In-Reply-To-header 还具有我们想要响应的消息的值。我们还将Re: 添加到我们的Subject-header 以表明它是一个响应。

// 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>"
  )
);

【讨论】:

我尝试了你给出的第一个解决方案,但我收到了 2 封邮件。一个作为邮件线程的一部分,另一个是新的。第二种方法失败并出现错误“无效参数”。我正在尝试将草稿添加到线程中,但到目前为止没有成功。 Google API 文档似乎也不正确。 @vikramaditya234 你可以试试this。 如果我想要回复的现有消息没有标头 References/In-Reply-To 会怎样? ***.com/questions/44880439/… 感谢您的精彩解释和参考,它真的帮助了我。不幸的是,第一种方法不起作用 - 我收到了单独的电子邮件。但是,一旦我按照您在第二个解决方案中的建议添加了 threadId,我就得到了电子邮件链! @Tholle 在消息对象中传递 'ThreadID' 的解决方法不再起作用,并且消息没有线程化。是因为 Google 引入了新的线程更改【参考方案2】:

@Tholle 的回答(谢谢!)是正确的,让我走上了正轨,但在最近的变化之后:

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

我不得不把他的两条路混为一谈。

在我的程序中,我必须回复一个线程,但如果我只包含 threadId(如 #2),则新邮件将由 Gmail 仅在回复者的邮件中放入线程中,而在原始邮件中发件人(也是 gmail)作为新线程出现。

我通过在最后一条消息的 id 中包含 threadId 和标头“References”和“In-Reply-To”来解决。

【讨论】:

以上是关于如何使用 Gmail API 发送回复的主要内容,如果未能解决你的问题,请参考以下文章

如何在 C# 中使用带有服务帐户的 gmail api 或 google Oauth 来发送邮件?

尝试使用 gmail API 回复现有电子邮件

您如何使用 gmail api 查询已发送的项目?

如何在 django 中使用 gmail smtp 更改回复和返回路径标头

使用 gmail API 设置用户签名 - 如何

如何使用新的 Gmail REST API 成功发送消息?