接收App Engine中的电子邮件附件Unicode文本文件中的Python错误 [英] Receiving Email Attachments in App Engine Python errors on Unicode Text File

查看:299
本文介绍了接收App Engine中的电子邮件附件Unicode文本文件中的Python错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



代码基本上保存文件并返回一个转换为字符串的密钥,然后存储在父电子邮件实体中。正如你可以看到我解码文件,然后将其存储为一个blob。我已经发送了很多附件,而这个代码适用于除Unicode之外的文本。有没有更好的方法来做到这一点?我可以如何处理Unicode文本附件?



代码snipit

  my_file = [] 
my_list = []
如果hasattr(mail_message,'附件'):
file_name =
file_blob =
为文件名, mail_message.attachments中的filecontents:
file_name = filename
file_blob = filecontents.decode()
my_file.append(file_name)
my_list.append(str(store_file(self,file_name, file_blob)))

store_file

  def store_file(self,file_name,file_blob):
new_file = myblob(file_name = file_name,
file_blob = file_blob)
return new_file.put()$ b我试过使用 file_blob = str(file_blob)在上面没有用。这只是打破代码,文件永远不会被存储。



日志1的Unicode文本文件

 属性file_blob必须可转换为Blob实例(Blob()参数应为str instance,而不是unicode)
追溯(最近的最后一次调用):
文件/ base / python27_runtime / python27_lib / versions / third_party / webapp2-2.5.1 / webapp2.py,第1530行,__call__
rv = self.router.dispatch(请求,响应)
文件/ base / python27_runtime /python27_lib/versions/third_party/webapp2-2.5.1/webapp2.py,第1278行,default_dispatcher
return route.handler_adapter(request,response)
文件/ base / python27_runtime / python27_lib / versions /third_party/webapp2-2.5.1/webapp2.py,第1102行,__call__
return handler.dispatch()
文件/base/python27_runtime/python27_lib/versions/third_party/webapp2-2.5。 1 / webapp2.py,第572行,在调度
return self.handle_exception(e,self.app.debug)
文件/ base / python2 7_runtime / python27_lib / versions / third_party / webapp2-2.5.1 / webapp2.py,第570行,在调度
返回方法(* args,** kwargs)
文件/ base / python27_runtime / python27_lib /versions/1/google/appengine/ext/webapp/mail_handlers.py,第65行,发布
self.receive(mail.InboundEmailMessage(self.request.body))
文件/ base /data/home/apps/s~ae-baseapp/1.359073377819595139/controllers/InboundHandler.py,第51行接收
file_list.append(str(store_file(self,file_name,file_blob)))
文件/base/data/home/apps/s~ae-baseapp/1.359073377819595139/models/MyModel.py,第63行,store_file
file_blob = file_blob)
文件/ base / python27_runtime /python27_lib/versions/1/google/appengine/ext/db/__init__.py,第974行,__init__
prop .__ set __(self,value)
文件/ base / python27_runtime / python27_lib /版本/ 1 / google / appengine / ext / db / __ init__.py,第614行,__set__
value = self.validate(value)
文件/ base / python27_ru ntime / python27_lib / versions / 1 / google / appengine / ext / db / __ init__.py,第2780行验证
(self.name,self.data_type .__ name__,err))
BadValueError:属性file_blob必须可转换为Blob实例(Blob()参数应为str instance,而不是unicode)

日志2删除filecontents.decode()并用filecontents替换它。

 属性file_blob必须可转换为Blob实例(Blob()参数应该是str instance,而不是EncodedPayload)
Traceback(最近的最后一次调用):
文件/base/python27_runtime/python27_lib/versions/third_party/webapp2-2.5.1/webapp2 .py,第1530行,__call__
rv = self.router.dispatch(请求,响应)
文件/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)
文件/ base / python27_runtime / python27_lib / versions / t hird_party / webapp2-2.5.1 / webapp2.py,第1102行,__call__
return handler.dispatch()
文件/base/python27_runtime/python27_lib/versions/third_party/webapp2-2.5.1 /webapp2.py,第572行,在调度中
return self.handle_exception(e,self.app.debug)
文件/base/python27_runtime/python27_lib/versions/third_party/webapp2-2.5.1
文件/ base / python27_runtime / python27_lib / versions / 1 / google / appengine / ext / webapp / mail_handlers.py,第65行,post
self.receive(mail.InboundEmailMessage(self.request.body))
文件/ base / data / home / apps / s〜ae-baseapp / 1.359097282640216691 / controllers / InboundHandler.py,第57行接收
file_list.append(str(store_file(self,file_name,file_blob)))
文件/ base / data / home / apps / s 〜ae-baseapp / 1.359097282640216691 / models / MyModel.py,第64行,store_file
file_blob = file_blob)
文件/ base / python27_runtime / python27 __init__
prop .__ set __(self,value)
文件/ base / python27_runtime / python27_lib / versions中的第_行_ /1/google/appengine/ext/db/__init__.py,第614行,__set__
value = self.validate(value)
文件/ base / python27_runtime / python27_lib / versions / 1 / google / appengine / ext / db / __ init__.py,第2780行验证
(self.name,self.data_type .__ name__,err))
BadValueError:属性file_blob必须可转换为Blob实例(Blob()参数应该是str instance,而不是EncodedPayload)


解决方案

附件有效内容是 EncodedPayload 类。附件具有编码和可选字符集。前者指的是转移编码,如base64;后者将字符编码如UTF-8(字符集有点过时和误导性的术语)。 EncodedPayload.decode()方法可以解码传输编码和文本编码,如您所注意到的那样,如果您只想获取用户附加的原始字节,则不是很有帮助他们的消息。



有很多方法可以在这里,但我建议复制EncodedPayload的解码传输编码的逻辑,看起来像这样:如果filecontents.encoding和filecontents.encoding.lower()!='7bit':
try:$ b,则

 $ b payload = filecontents.payload.decode(filecontents.encoding)
除了LookupError:
raise UnknownEncodingError('Unknown decoding%s。'%filecontents.encoding)
except(异常,错误) ,e:
raise PayloadEncodingError('无法解码有效载荷:%s'%e)
else:
payload = filecontents.payload
pre>

请注意,如果附件文本,则需要包含字符en当您存储它时的编码,或者当您将其发送回用户时,无法解释它 - 原始文本可能使用任何字符编码进行编码。



同样,如果可以,您还应该保存附件的mimetype,但这并不会在API的任何地方露出。您可能想考虑避免使用IncomingMessage类,而是使用Python的mime消息模块来解码POST请求的正文。


I have some code to parse an email and find the attachments then store them into the Datastore as db.BlobProperties (might change that to Blobstore later). The problem is that when I send a UTF8 encoded text file it generates an error.

The code basically saves the file and returns a key that is converted to a string then stored in the parent email entity. As you can see I decode the file then store it as a blob. I have sent lots of attachments and this code works on everything but Text encoded with Unicode. Is there a better way to do this? What can I do to handle Unicode text attachments?

code snipit

    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)))

store_file

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

I have tried using file_blob = str(file_blob) in the above to no avail. That just breaks the code and the file never gets stored.

log 1 of Unicode Text File

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)

Log 2 of removing the filecontents.decode() and replacing it with just filecontents.

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)

解决方案

Attachment payloads are instances of the EncodedPayload class. Attachments have an encoding and an optional character set. The former refers to transfer encodings such as base64; the latter to character encodings such as UTF-8 (character set's a bit of an outdated and misleading term here). The EncodedPayload.decode() method decodes both transfer encoding and text encoding, which as you've noticed is not very helpful if you just want to get the original bytes the user attached to their message.

There's a number of approaches you can take here, but what I'd recommend is duplicating EncodedPayload's logic for decoding transfer encoding, which looks something like this:

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

Note that if the attachment was text, you need to include the character encoding when you store it, or there'll be no way to interpret it when you send it back to the user - the original text could have been encoded using any character encoding.

Likewise, you should also save the mimetype of the attachment if you can, but this doesn't appear to be exposed anywhere in the API. You might want to consider avoiding using the IncomingMessage class at all, and instead decoding the body of the POST request using Python's mime message module.

这篇关于接收App Engine中的电子邮件附件Unicode文本文件中的Python错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆