【问题标题】:Gmail API throws error while sending email, but still sends emailGmail API 在发送电子邮件时抛出错误,但仍会发送电子邮件
【发布时间】:2021-10-09 17:10:51
【问题描述】:

我使用以下内容创建电子邮件。

def createGmailEmailNoAttachments(self, messageBody, subject, toEmail, fromEmail, html=False):
    try:
        newMessage = MIMEMultipart()
        newMessage['to']=toEmail
        newMessage['from'] = fromEmail
        newMessage['subject'] = subject
        if html: 
            msg= MIMEText(messageBody, 'html')
        else: 
            msg= MIMEText(messageBody)
        newMessage.attach(msg)

        raw = base64.urlsafe_b64encode(newMessage.as_bytes())
        raw = raw.decode()
        body = {'raw': raw}
        return body
    except:
        self.GLogger.error("An error was encountered while attempting to create gmail email")
        tb = traceback.format_exc()
        self.GLogger.exception(tb)
        return False

我发送一封包含以下内容的电子邮件。

def gmailAPISendEmail(self, message, userID="me"):
    try:
        service = self.gmailAPIService
        self.GLogger.info("Attempting to send email message")
        request = service.users().messages().send(userId=userID, body=message)
        response = self.executeGmailAPI_withretry(request)
        if response is False: 
            return False

        responseID = str(response['id'])
        self.GLogger.info("Successfully sent email message with ID (" + responseID +")")
        return responseID
    except:
        self.GLogger.error("Failed to send email message")
        tb = traceback.format_exc()
        self.GLogger.exception(tb)
        return False

我在函数executeGmailAPI_withretry(request)中执行请求的地方

def executeGmailAPI_withretry(self, request, withHTTPObject = False):
    try: 
        response_valid = False
        num_retries = 0
        while num_retries < 30: 
            try: 
                if withHTTPObject is True: 
                    response = request.execute(http=self.http_toUse)
                else: 
                    response = request.execute()
                response_valid = True
                break
            except socket.timeout:
                num_retries = num_retries + 1 
                time.sleep(0.5*num_retries)
            except: 
                self.GLogger.error("An error was encounrtered in executeGmailAPI_withretry")
                try: 
                    self.GLogger.error(f"The Method ID : {request.methodId}")
                except: 
                    pass
                try: 
                    self.GLogger.error(f"The uri : {request.uri}")
                except: 
                    pass
                tb = traceback.format_exc()
                self.GLogger.exception(tb)
                num_retries = num_retries + 1 
                time.sleep(0.5*num_retries)

        if response_valid is False: 
            self.GLogger.error(f"Could not resolve issue in 15 requests [{request}]")
            return False
        else: 
            return response
    except: 
        self.GLogger.error("An error was encounrtered in executeGmailAPI_withretry")
        tb = traceback.format_exc()
        self.GLogger.exception(tb)
        return False

我遇到的问题如下。有时,当我想用​​这三个函数发送电子邮件时,在执行service.users().messages().send(userId=userID, body=message) 的过程中会出现socket.timeout 错误。我的重试功能将尝试发送最多 30 次,中间会有一些时间延迟。但是,有时,当发生 socket.timeout 错误时,电子邮件仍然发送。这可能会导致发送多封相同的电子邮件。从代码的角度来看,只发送了一封电子邮件,因为service.users().messages().send(userId=userID, body=message) 只成功运行了一次而没有抛出错误。

因此,例如,我收到了 4 封相同的电子邮件,这意味着至少 3 次发送尝试出现了 socket.timeout 错误,其中 Gmail 确实发送了电子邮件,并且执行了第 4 次(或更多)尝试而没有抛出套接字.timeout 错误。

为什么Gmail API在发送邮件的时候会抛出socket.timeout错误,但还是继续发送邮件?

这在当前情况下造成了两难境地。

  1. 如果我处理了错误,那么它可以确保在第一次尝试时确实无法发送的电子邮件将被发送。但是,由于错误错误,它可能会导致发送多封相同的电子邮件。

  2. 如果我不处理错误,那么可以肯定的是,最多只会发送一封电子邮件。但是,如果邮件真的发不出去,那肯定是发不出去的。

理想的解决方案是,Gmail API 应该只在电子邮件确实无法发送时抛出错误。

【问题讨论】:

    标签: python python-3.x gmail gmail-api gmail-imap


    【解决方案1】:

    您可能想尝试设置更长的超时时间,使其位于timeout mode。见socket.setdefaulttimeout(timeout)

    这将强制脚本在引发超时异常之前等到指定的超时。这样,您也许可以防止过早的超时异常。

    如果还是不行,也许你可以在issue tracker 上将它作为一个错误提交。

    参考:

    【讨论】:

    • 谢谢。我已将其设置为 10 分钟。更改超时值似乎确实会改变 socket.timeout 错误的频率和性质。但是,根据我的经验,socket.timeout 错误肯定会在某个时间点发生,而不管超时值如何。 socket.timeout 错误并不总是发生在程序中或发送消息时。但是当它发生时,它似乎会抛出错误,但无论如何都会发送电子邮件。因为我处理了错误,所以这会转化为发送多封电子邮件。
    • 如果它仍然不起作用,我想你可能想在issue tracker 上发布这个。可能有一些东西导致了谷歌知道的错误。
    • 我现在向 Google 提交了一个错误
    • 嗨@geekygeek,如果我们的回答对您有所帮助,请随时支持/接受答案。通过这样做,社区中可能与您有同样担忧的其他人将知道他们的问题可以得到解决。如果您无法使用接受按钮,请随时告诉我。 how to accept answer
    猜你喜欢
    • 2021-09-11
    • 2014-09-24
    • 2014-10-30
    • 1970-01-01
    • 2016-06-03
    • 1970-01-01
    • 1970-01-01
    • 2018-01-26
    • 1970-01-01
    相关资源
    最近更新 更多