【问题标题】:Creating Gmail draft after deployment not working部署后创建 Gmail 草稿不起作用
【发布时间】:2016-02-04 04:14:02
【问题描述】:

我正在尝试使用 Gmail API 创建 Gmail 草稿。

在开发时它可以完美运行,但是当我部署它时,我收到一条错误消息。

POST http://myapp.appspot.com/emailDoc 500 (Internal Server Error)

这就是我的 Flask 路由函数的样子:

# Flask Route
@app.route('/emailDoc', methods=["POST"])
def emailDoc():

    # Get Oauth2 Credentials
    credentials = Credentials().get_by_id('tokens')
    if not authcheck(credentials):
        return 'error'

    # Create ReportLab PDF
    buff = StringIO()
    doc = SimpleDocTemplate(buff, pagesize=A4,
                          rightMargin=1.25*cm,leftMargin=1.25*cm,
                          topMargin=1.25*cm,bottomMargin=1.25*cm)
    doc.build(genpdf(data))

    # Create Email Message
    message = MIMEMultipart()
    message['to'] = to@email.com
    message['from'] = 'me'
    message['subject'] = 'Hello'

    messageBody = MIMEText("Hello Wolrd")

    messageFile = MIMEBase('application', 'pdf')
    messageFile.set_payload(str(buff.getvalue()))
    messageFile.add_header('Content-Disposition', 'attachment', filename='document.pdf')

    message.attach(messageBody)
    message.attach(messageFile)

    # Oauth2 Flow
    access_token = credentials.access_token
    flow = AccessTokenCredentials(access_token, 'myapp')
    http = flow.authorize(httplib2.Http())

    # HTTP Request
    obj = http.request(
        uri='https://www.googleapis.com/gmail/v1/users/me/drafts',
        method='POST',
        body={
          'message': {
            'raw':base64.urlsafe_b64encode( message.as_string() )
           }
        },
        headers={'content-type':'application/json'}
    )[1]

    return obj

这是我在 Google Developers Console 日志记录选项卡中收到的错误消息。

Exception on /emailDoc [POST]
Traceback (most recent call last):
  File "/base/data/home/apps/s~admin-app/1.388311669567787470/lib/flask/app.py", line 1817, in wsgi_app
    response = self.full_dispatch_request()
  File "/base/data/home/apps/s~admin-app/1.388311669567787470/lib/flask/app.py", line 1477, in full_dispatch_request
    rv = self.handle_user_exception(e)
  File "/base/data/home/apps/s~admin-app/1.388311669567787470/lib/flask/app.py", line 1381, in handle_user_exception
    reraise(exc_type, exc_value, tb)
  File "/base/data/home/apps/s~admin-app/1.388311669567787470/lib/flask/app.py", line 1475, in full_dispatch_request
    rv = self.dispatch_request()
  File "/base/data/home/apps/s~admin-app/1.388311669567787470/lib/flask/app.py", line 1461, in dispatch_request
    return self.view_functions[rule.endpoint](**req.view_args)
  File "/base/data/home/apps/s~admin-app/1.388311669567787470/main.py", line 471, in emailDoc
    headers={'content-type':'application/json'}
  File "/base/data/home/apps/s~admin-app/1.388311669567787470/lib/oauth2client/client.py", line 589, in new_request
    redirections, connection_type)
  File "/base/data/home/apps/s~admin-app/1.388311669567787470/lib/httplib2/__init__.py", line 1593, in request
    (response, content) = self._request(conn, authority, uri, request_uri, method, body, headers, redirections, cachekey)
  File "/base/data/home/apps/s~admin-app/1.388311669567787470/lib/httplib2/__init__.py", line 1335, in _request
    (response, content) = self._conn_request(conn, request_uri, method, body, headers)
  File "/base/data/home/apps/s~admin-app/1.388311669567787470/lib/httplib2/__init__.py", line 1291, in _conn_request
    response = conn.getresponse()
  File "/base/data/home/runtimes/python27/python27_dist/lib/python2.7/gae_override/httplib.py", line 522, in getresponse
    **extra_kwargs)
  File "/base/data/home/apps/s~admin-app/1.388311669567787470/lib/httplib2/__init__.py", line 1091, in fixed_fetch
    validate_certificate=validate_certificate)
  File "/base/data/home/runtimes/python27/python27_lib/versions/1/google/appengine/api/urlfetch.py", line 270, in fetch
    allow_truncated, follow_redirects, validate_certificate)
  File "/base/data/home/runtimes/python27/python27_lib/versions/1/google/appengine/api/urlfetch.py", line 326, in make_fetch_call
    request.set_payload(payload)
  File "cpp_message.pyx", line 124, in cpp_message.SetScalarAccessors.Setter (third_party/apphosting/python/protobuf/proto1/cpp_message.cc:2229)
TypeError: <type 'dict'> has type <type 'dict'>, but expected one of: str, unicode

【问题讨论】:

    标签: python google-app-engine flask gmail-api


    【解决方案1】:

    您在代码中的某处发送字典而不是字符串。我建议您使用gmail python library,它非常快,并且每次调用都有代码快照。

    """Generates and submits an email as a draft.
    """
    
    import base64
    from email.mime.audio import MIMEAudio
    from email.mime.base import MIMEBase
    from email.mime.image import MIMEImage
    from email.mime.multipart import MIMEMultipart
    from email.mime.text import MIMEText
    import mimetypes
    import os
    
    from apiclient import errors
    
    
    def CreateDraft(service, user_id, message_body):
      """Create and insert a draft email. Print the returned draft's message and id.
    
      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_body: The body of the email message, including headers.
    
      Returns:
        Draft object, including draft id and message meta data.
      """
      try:
        message = {'message': message_body}
        draft = service.users().drafts().create(userId=user_id, body=message).execute()
    
        print 'Draft id: %s\nDraft message: %s' % (draft['id'], draft['message'])
    
        return draft
      except errors.HttpError, error:
        print 'An error occurred: %s' % error
        return None
    
    
    def CreateMessage(sender, to, subject, message_text):
      """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.
    
      Returns:
        An object containing a base64 encoded email object.
      """
      message = MIMEText(message_text)
      message['to'] = to
      message['from'] = sender
      message['subject'] = subject
      return {'raw': base64.b64encode(message.as_string())}
    
    
    def CreateMessageWithAttachment(sender, to, subject, message_text, file_dir,
                                    filename):
      """Create a message for an email.
    
      Args:
        sender: The email address of the sender.
        to: The 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 base64 encoded email object.
      """
      message = MIMEMultipart()
      message['to'] = to
      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)
    
      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()
    
      msg.add_header('Content-Disposition', 'attachment', filename=filename)
      message.attach(msg)
    
      return {'raw': base64.b64encode(message.as_string())}
    

    【讨论】:

    • 谢谢,我最后就是这么做的。
    【解决方案2】:

    http.request 要求 body= 是一个字符串。你必须先json.dumps 你的dict 才能传递它。

    # HTTP Request
    obj = http.request(
        uri='https://www.googleapis.com/gmail/v1/users/me/drafts',
        method='POST',
        # json encoded string
        body=json.dumps({
          'message': {
            'raw':base64.urlsafe_b64encode( message.as_string() )
           }
        }),
        headers={'content-type':'application/json'}
    )[1]
    

    【讨论】:

      猜你喜欢
      • 2018-02-20
      • 2016-01-12
      • 2018-04-19
      • 2014-10-19
      • 1970-01-01
      • 2017-06-17
      • 1970-01-01
      • 1970-01-01
      • 2010-11-15
      相关资源
      最近更新 更多