2

我有一些代码可以解析电子邮件并找到附件,然后将它们作为 db.BlobProperties 存储到数据存储中(稍后可能会将其更改为 Blobstore)。问题是当我发送一个 UTF8 编码的文本文件时,它会产生一个错误。

该代码基本上保存文件并返回一个密钥,该密钥转换为字符串,然后存储在父电子邮件实体中。如您所见,我对文件进行解码,然后将其存储为 blob。我已经发送了很多附件,并且此代码适用于除使用 Unicode 编码的文本之外的所有内容。有一个更好的方法吗?我可以做些什么来处理 Unicode 文本附件?

代码片段

    my_file = []
    my_list = []
    if hasattr(mail_message, 'attachments'):
        file_name = ""
        file_blob = ""
        for filename, filecontents in mail_message.attachments:
            file_name = filename
            file_blob = filecontents.decode()
            my_file.append(file_name)
            my_list.append(str(store_file(self, file_name, file_blob)))

存储文件

def store_file(self, file_name, file_blob):
    new_file = myblob(file_name = file_name, 
                      file_blob = file_blob)
    return new_file.put()

我试过file_blob = str(file_blob)在上面使用无济于事。这只会破坏代码,并且文件永远不会被存储。

Unicode 文本文件的日志 1

Property file_blob must be convertible to a Blob instance (Blob() argument should be str instance, not unicode)
Traceback (most recent call last):
  File "/base/python27_runtime/python27_lib/versions/third_party/webapp2-2.5.1/webapp2.py", line 1530, in __call__
    rv = self.router.dispatch(request, response)
  File "/base/python27_runtime/python27_lib/versions/third_party/webapp2-2.5.1/webapp2.py", line 1278, in default_dispatcher
    return route.handler_adapter(request, response)
  File "/base/python27_runtime/python27_lib/versions/third_party/webapp2-2.5.1/webapp2.py", line 1102, in __call__
    return handler.dispatch()
  File "/base/python27_runtime/python27_lib/versions/third_party/webapp2-2.5.1/webapp2.py", line 572, in dispatch
    return self.handle_exception(e, self.app.debug)
  File "/base/python27_runtime/python27_lib/versions/third_party/webapp2-2.5.1/webapp2.py", line 570, in dispatch
    return method(*args, **kwargs)
  File "/base/python27_runtime/python27_lib/versions/1/google/appengine/ext/webapp/mail_handlers.py", line 65, in post
    self.receive(mail.InboundEmailMessage(self.request.body))
  File "/base/data/home/apps/s~ae-baseapp/1.359073377819595139/controllers/InboundHandler.py", line 51, in receive
    file_list.append(str(store_file(self, file_name, file_blob)))
  File "/base/data/home/apps/s~ae-baseapp/1.359073377819595139/models/MyModel.py", line 63, in store_file
    file_blob = file_blob)
  File "/base/python27_runtime/python27_lib/versions/1/google/appengine/ext/db/__init__.py", line 974, in __init__
    prop.__set__(self, value)
  File "/base/python27_runtime/python27_lib/versions/1/google/appengine/ext/db/__init__.py", line 614, in __set__
    value = self.validate(value)
  File "/base/python27_runtime/python27_lib/versions/1/google/appengine/ext/db/__init__.py", line 2780, in validate
    (self.name, self.data_type.__name__, err))
BadValueError: Property file_blob must be convertible to a Blob instance (Blob() argument should be str instance, not unicode)

删除 filecontents.decode() 并将其替换为仅文件内容的日志 2。

Property file_blob must be convertible to a Blob instance (Blob() argument should be str instance, not EncodedPayload)
Traceback (most recent call last):
  File "/base/python27_runtime/python27_lib/versions/third_party/webapp2-2.5.1/webapp2.py", line 1530, in __call__
    rv = self.router.dispatch(request, response)
  File "/base/python27_runtime/python27_lib/versions/third_party/webapp2-2.5.1/webapp2.py", line 1278, in default_dispatcher
    return route.handler_adapter(request, response)
  File "/base/python27_runtime/python27_lib/versions/third_party/webapp2-2.5.1/webapp2.py", line 1102, in __call__
    return handler.dispatch()
  File "/base/python27_runtime/python27_lib/versions/third_party/webapp2-2.5.1/webapp2.py", line 572, in dispatch
    return self.handle_exception(e, self.app.debug)
  File "/base/python27_runtime/python27_lib/versions/third_party/webapp2-2.5.1/webapp2.py", line 570, in dispatch
    return method(*args, **kwargs)
  File "/base/python27_runtime/python27_lib/versions/1/google/appengine/ext/webapp/mail_handlers.py", line 65, in post
    self.receive(mail.InboundEmailMessage(self.request.body))
  File "/base/data/home/apps/s~ae-baseapp/1.359097282640216691/controllers/InboundHandler.py", line 57, in receive
    file_list.append(str(store_file(self, file_name, file_blob)))
  File "/base/data/home/apps/s~ae-baseapp/1.359097282640216691/models/MyModel.py", line 64, in store_file
    file_blob = file_blob)
  File "/base/python27_runtime/python27_lib/versions/1/google/appengine/ext/db/__init__.py", line 974, in __init__
    prop.__set__(self, value)
  File "/base/python27_runtime/python27_lib/versions/1/google/appengine/ext/db/__init__.py", line 614, in __set__
    value = self.validate(value)
  File "/base/python27_runtime/python27_lib/versions/1/google/appengine/ext/db/__init__.py", line 2780, in validate
    (self.name, self.data_type.__name__, err))
BadValueError: Property file_blob must be convertible to a Blob instance (Blob() argument should be str instance, not EncodedPayload)
4

2 回答 2

2

附件负载是EncodedPayload类的实例。附件有一个编码和一个可选的字符集。前者指的是base64等传输编码;后者适用于 UTF-8 等字符编码(这里的字符集有点过时且具有误导性)。该EncodedPayload.decode()方法同时解码传输编码和文本编码,正如您所注意到的,如果您只想获取用户附加到其消息的原始字节,这并不是很有帮助。

您可以在此处采用多种方法,但我建议您复制 EncodedPayload 用于解码传输编码的逻辑,如下所示:

if filecontents.encoding and filecontents.encoding.lower() != '7bit':
  try:
    payload = filecontents.payload.decode(filecontents.encoding)
  except LookupError:
    raise UnknownEncodingError('Unknown decoding %s.' % filecontents.encoding)
  except (Exception, Error), e:
    raise PayloadEncodingError('Could not decode payload: %s' % e)
else:
  payload = filecontents.payload

请注意,如果附件文本,则在存储时需要包含字符编码,否则在将其发送回用户时将无法解释 - 原始文本可能已使用任何字符编码进行编码.

同样,如果可以,您还应该保存附件的 mimetype,但这似乎不会在 API 的任何地方公开。您可能需要考虑完全避免使用 IncomingMessage 类,而是使用 Python 的 mime 消息模块解码 POST 请求的主体。

于 2012-05-23T01:19:03.847 回答
2

检查此代码是否有帮助:

============================

   my_file = []
    my_list = []
    if hasattr(mail_message, 'attachments'):
        file_name = ""
        for filename, filecontents in mail_message.attachments:
            file_name = filename
            file_blob = filecontents.payload
            file_blob = file_blob.decode(filecontents.encoding)
            my_file.append(file_name)
            my_list.append(str(store_file(self, file_name, file_blob)))
于 2012-10-01T06:38:23.637 回答