使用 Gmail API 发送大型附件时出现错误 10053

Posted

技术标签:

【中文标题】使用 Gmail API 发送大型附件时出现错误 10053【英文标题】:Error 10053 When Sending Large Attachments using Gmail API 【发布时间】:2015-03-08 16:14:44 【问题描述】:

我正在尝试使用 Gmail API 和以下函数发送各种大小的电子邮件。

通常这很有效,但是对于超过 10MB 的附件(这种情况很少见但会发生),我收到 Errno 10053认为是因为我在发送包含大附件的消息时超时。

有没有办法通过指定大小或增加超时限制来解决这个问题? Gmail API 文档中提到了大小,但我很难理解如何在 Python 中使用,或者它是否会有所帮助。

def CreateMessageWithAttachment(sender, to, cc, subject,
                                message_text, file_dir, filename):
  """Create a message for an email.

  Args:
    sender: Email address of the sender.
    to: Email address of the receiver.
    subject: The subject of the email message.
    message_text: The text of the email message.
    file_dir: The directory containing the file to be attached.
    filename: The name of the file to be attached.

  Returns:
    An object containing a base64url encoded email object.
  """
  message = MIMEMultipart()
  message['to'] = to
  if cc != None:
    message['cc'] = cc
  message['from'] = sender
  message['subject'] = subject

  msg = MIMEText(message_text)
  message.attach(msg)

  path = os.path.join(file_dir, filename)
  content_type, encoding = mimetypes.guess_type(path)

  QCoreApplication.processEvents()

  if content_type is None or encoding is not None:
    content_type = 'application/octet-stream'
  main_type, sub_type = content_type.split('/', 1)
  if main_type == 'text':
    fp = open(path, 'rb')
    msg = MIMEText(fp.read(), _subtype=sub_type)
    fp.close()
  elif main_type == 'image':
    fp = open(path, 'rb')
    msg = MIMEImage(fp.read(), _subtype=sub_type)
    fp.close()
  elif main_type == 'audio':
    fp = open(path, 'rb')
    msg = MIMEAudio(fp.read(), _subtype=sub_type)
    fp.close()
  else:
    fp = open(path, 'rb')
    msg = MIMEBase(main_type, sub_type)
    msg.set_payload(fp.read())
    fp.close()
  QCoreApplication.processEvents()

  msg.add_header('Content-Disposition', 'attachment', filename=filename)
  message.attach(msg)
  return 'raw': base64.urlsafe_b64encode(message.as_string())



def SendMessage(service, user_id, message, size):
  """Send an email message.

  Args:
    service: Authorized Gmail API service instance.
    user_id: User's email address. The special value "me"
    can be used to indicate the authenticated user.
    message: Message to be sent.

  Returns:
    Sent Message.
  """

  try:
    message = (service.users().messages().send(userId=user_id, body=message)
               .execute())
    QCoreApplication.processEvents()
    return message
  except errors.HttpError, error:
    pass

【问题讨论】:

查看此链接***.com/questions/17854713/error-errno-10053 【参考方案1】:

我成功插入/发送带有大文件、pythons 代码的消息。 google api 文档对开发者不友好,“/upload”问题完全不清楚,也没有很好的记录,这让很多开发者感到困惑。

最后一行发挥了作用:)

def insert_message(service, message):
        try:
                if message['sizeEstimate'] > 6000000:
                        insert_large_message(service, message)
                else:
                        insert_small_message(service, message)
        except:
                print ('Error: ----type: %s, ----value: %s, ----traceback: %s ************' % (sys.exc_info()[0],sys.exc_info()[1],sys.exc_info()[2]))

def insert_small_message(service, message):
        body = 'raw': message['raw'],'labelIds':message['labelIds'],'internalDateSource':'dateHeader'
        message = service.users().messages().insert(userId='me',body=body).execute()

def insert_large_message(service, message):
        b = io.BytesIO()
        message_bytes = base64.urlsafe_b64decode(str(message['raw']))
        b.write(message_bytes)
        body = 'labelIds':message['labelIds'],'internalDateSource':'dateHeader'
        media_body = googleapiclient.http.MediaIoBaseUpload(b, mimetype='message/rfc822' )
        print('load big data!')
        message = service.users().messages().insert(userId='me',body=body,media_body=media_body).execute()

【讨论】:

【参考方案2】:

'g' 是我授权的 api 上下文。 call 方法将在对象上调用 execute。重要的是媒体调用并同时使用 media_body 和 body 参数。这会导致插入带有标签 INBOX 的消息,并且它将允许至少 24MB 的文件。

由于读取超时时间太短,我最终得到了两个副本:

f fetch 8:9 (flags INTERNALDATE RFC822.SIZE)
* 8 FETCH (RFC822.SIZE 24000720 INTERNALDATE "19-Jul-2007 17:12:26 +0000" FLAGS (\Seen))
* 9 FETCH (RFC822.SIZE 24000720 INTERNALDATE "19-Jul-2007 17:12:26 +0000" FLAGS (\Seen))

示例代码:

import mailbox
import StringIO
import googleapiclient.http

f = 'my-mbox-file.mbox'
params = 
params[ 'internalDateSource' ] = 'dateHeader'
for m in mailbox.mbox( f, create=False ):
    message_string = m.as_string()
    params[ 'body' ] =  'labelIds': [ 'INBOX' ] 

    if len(message_string) > 6000000:
        s = StringIO.StringIO()
        s.write( message_string )
        params[ 'media_body' ] = googleapiclient.http.MediaIoBaseUpload(
                            s, mimetype='message/rfc822' )
    else:
        params['body']['raw'] = (
            base64.urlsafe_b64encode( message_string ) )

    g.call( g.auth.users().messages().insert, params )

    try:
        del params[ 'media_body' ]
    except KeyError:
        pass

【讨论】:

【参考方案3】:

对于这么大的内容,您需要使用 MEDIA /upload 选项。然后,您可以在 Gmail 允许的最大范围内发送电子邮件。如何使用 /upload 的文档: https://developers.google.com/gmail/api/v1/reference/users/messages/send

10MB 的限制没有很好的记录。

【讨论】:

以上是关于使用 Gmail API 发送大型附件时出现错误 10053的主要内容,如果未能解决你的问题,请参考以下文章

发布到 Gmail API 时出现 http 500 后端错误

在 golang 中使用 gmail API 发送带附件的电子邮件

访问 Gmail API 时出现错误请求

尝试通过 API 删除 gmail 邮件时出现 401 错误

使用 Gmail api 时尝试获取电子邮件列表时出现错误 [403]

Python Post 请求 - 通过 Outlook API 发送文件时出现 415 错误