【问题标题】:Emails sent with the Gmail API are not grouped in threads?使用 Gmail API 发送的电子邮件未按线程分组?
【发布时间】:2023-01-29 08:17:21
【问题描述】:

我正在使用gmail API 发送电子邮件。这是我用来创建电子邮件的功能:

    def createEmailNoAttachments(self, send_to_emails, subject_text, main_message_text, msgID=None, inReplyTo=None, html=False):
        try:
            fromEmail = self.from_email_total
            
            
            if (type(main_message_text) == list) or (type(main_message_text) == tuple): 
                total_text = ""
                for line in main_message_text:
                    if type(line) == str: 
                        total_text = total_text + line + "\n"
                main_message_text = total_text
                        
            mimeMessage = MIMEMultipart()
            if type(send_to_emails) == list: 
                mimeMessage['to'] = ", ".join(send_to_emails)
            else: 
                mimeMessage['to'] = send_to_emails

            mimeMessage['from'] = fromEmail
            mimeMessage['subject'] = subject_text
            if inReplyTo != None: 
                mimeMessage["In-Reply-To"] = inReplyTo
                mimeMessage["References"] = inReplyTo
            if msgID != None: 
                mimeMessage['Message-ID'] = msgID
            if html: 
                msg= MIMEText(main_message_text, 'html')
            else: 
                msg= MIMEText(main_message_text, "plain")
            mimeMessage.attach(msg)

            raw = base64.urlsafe_b64encode(mimeMessage.as_bytes())
            raw = raw.decode()
            body = {'raw': raw}

            return body
        except:
            self.myLogger.error("An error was encountered while attempting to create gmail email")
            tb = traceback.format_exc()
            self.myLogger.exception(tb)
            return False
            

然后我发送电子邮件

    def gmailAPISendEmail(self, email_message, deleteFromInbox=False, userID="me"):
        try:
            self.refreshGmailService()
            
            self.myLogger.info("Attempting to send email message")

            request = self.service.users().messages().send(userId=userID, body=email_message)
            response = self.executeGmailAPI_withretry(request=request)
            if response == False: 
                self.myLogger.error("An error occurred in executeGmailAPI_withretry while trying to send email message")
                return False
            else:
                try: 
                    responseID = str(response['id'])

                    if deleteFromInbox == True: 
                        delete_result = self.deleteEmail(emailID=responseID)
                        if delete_result == False: 
                            self.myLogger.error(f"An error occurred in deleteEmail with responseID ({responseID})")
                
                    self.myLogger.info("Successfully sent email message with ID (" + responseID +")")
                    return responseID
                except: 
                    return "CouldNotExtractID"
        except:
            self.myLogger.error("An error occurred in gmailAPISendEmail")
            tb = traceback.format_exc()
            self.myLogger.exception(tb)
            return False

我注意到的问题是,在使用上述功能(gmail API)发送时,具有相同电子邮件主题和相同发件人和收件人的类似电子邮件不会被分组在一个线程下。在收件人电子邮件收件箱中,每封单独的电子邮件都会单独显示,即使它们具有相同的主题以及相同的发件人和收件人电子邮件地址。

我相信下一步是手动分配threadid。然而,这远非理想,因为我需要结合一些逻辑来完成所有这些。

在我使用SMTP 之前,我不必设置threadid 或类似的东西。使用SMTP 发送邮件时,邮件会根据相同的邮件主题和相同的收件人自动分组。

之前和现在之间没有任何变化,除了我发送相同的电子邮件时使用 gmail API 代替 SMTP

为什么 gmail API 的行为与 SMTP 不相似,即使我创建的电子邮件非常相似?我可以做些什么来让Gmail收件箱像SMTP一样对电子邮件进行分组,而无需构建逻辑并跟踪threadids?

【问题讨论】:

  • 您似乎对“线程”的含义感到困惑。线程中的消息是对线程中较早消息的回复,返回到启动线程的原始消息。 Microsoft 有一个“线程 ID”的概念,但它不是 SMTP 的一部分,或者据我所知,它没有用处。
  • 明白了,谢谢相似的电子邮件过去常常在 Gmail 线程中自动分组在一起。 Gmail 会自动执行此操作,仅仅是因为电子邮件相似(主题相同、消息相似、收件人相同等)。对于 SMTP,我对线程 ID 没有做任何事情。我刚刚发送了电子邮件。 Gmail 然后会将电子邮件分组在一起。
  • 我有完全相同的问题。就我而言,与 OP 一样,这些不是回复消息。它们只是一系列具有相同主题、发件人和收件人的消息。通过 gmail SMTP 服务器发送的邮件在 Gmail Web 电子邮件客户端中被分组到一个“线程”中。通过 Gmail API 发送的邮件不是。这个问题有什么进展吗?
  • 无论您是否分配它,您发送的每封电子邮件都将包含 in-relpy-to、引用、threadID 以及可能的其他 ID。如果您不分配它,它将随机生成。 Gmail 将其视为不对应任何电子邮件线程的唯一 ID,因此将单独显示。 SMTP 没有这些 ID,因此 Gmail 进行了推理逻辑。但是对于特定和定义的 ID,Gmail 将基于这些 ID 进行分组。

标签: python gmail-api google-api-python-client


【解决方案1】:

来自sending

如果您尝试发送回复并希望电子邮件与主题串连,请确保:

  • 主题标头匹配
  • References 和 In-Reply-To 标头遵循 RFC 2822 标准。
  • 有关从草稿发送消息的信息,请参阅Creating Drafts

因此,您需要回复的原始消息的消息 ID。这与线程 ID 不同。

message['In-Reply-To'] = message_id
message['References'] = message_id

【讨论】:

  • References:的正确处理是从你回复的消息中复制References:,并添加它的Message-Id,但如果它长得太长,则修剪结果,留下根Message-Id和最新的。
  • @tripleee 不确定我理解你的意思。随意编辑这个或打开你自己的答案,如果你能更好地解释它,我很乐意删除它。
  • 我不在可以测试解决方案的地方。通过在末尾添加另一个字符串来扩展之前的 References: 应该足够简单;也许将长值的修剪作为一种练习。
【解决方案2】:

有人知道在哪里以及如何在电子邮件标题中放置对引用的回复吗? 我写在正文电子邮件中,但它不会在同一线程中放置新电子邮件

【讨论】:

    猜你喜欢
    • 2019-04-08
    • 1970-01-01
    • 2018-01-26
    • 2021-09-11
    • 2015-01-02
    • 2017-04-14
    • 2019-10-16
    • 2014-10-30
    • 2017-03-07
    相关资源
    最近更新 更多