将数据库作为头像写入和映像附件:是否可能?

时间:2010-12-05 02:22:52

标签: python google-app-engine email google-cloud-datastore

是否有人在收到的电子邮件中处理过附件?我在考虑,而不是用户上传图像,他们可以将其作为附件发送,我可以用来上传到数据存储区。

文档已sending attachments但我找不到任何有关接收附件的文档。 This page says

  

附件

     

邮件的文件附件,作为两值元组的列表,每个附件的一个元组。

     

每个元组包含一个文件名作为第一个元素,文件内容作为第二个元素。

     

附件文件必须是允许的文件类型之一,文件名必须以与该类型对应的扩展名结尾。有关允许的类型和文件扩展名列表,请参阅概述:附件。

我认为这也是关于发送电子邮件。

我有这段代码将图像保存到数据存储区:

class AvatarSave(webapp.RequestHandler):
    def post(self):
        q = User.all()
        q.filter("userEmail =", emailAddress)
        qTable = q.fetch(10)
        if qTable:
            for row in qTable:
                avatar = images.resize(self.request.get("img"), 50, 50)
                row.avatar = db.Blob(avatar)
            db.put(qTable)
        else:
            self.response.out.write("user not found")

        self.redirect('/')

直观地说,message.attachment代替"img"似乎可以解决问题。

avatar = images.resize(self.request.get(message.attachment), 50, 50)
你怎么看?谢谢。


Update2 (新代码作为对Nick Johnson评论的回应)

class Register(InboundMailHandler):
    def receive(self, message):
        senderEmail = message.sender
        emailTuple = parseaddr(senderEmail)
        emailUserName = emailTuple[0]
        emailAddress = emailTuple[1]
        newAvatar = db.Blob(images.resize(goodDecode(message.attachments[0][1]), 50, 50))        
        newUser = User(userEmail=emailAddress,
                       userName=emailUserName,
                       avatar=newAvatar)

        db.put(newUser)

Update1 问题已解决:

对于记录,对于有相同问题的任何人,请注意attribute of messageattachments而不是attachment

message.attachment

给出AttributeError

AttributeError: 'InboundEmailMessage' object has no attribute 'attachment'

对象message.attachment看起来像这样:

[('portrait.png', <EncodedPayload payload=#8461006914571150170 encoding=base64>)]

因此拉出<EncodedPayload payload=#8461006914571150170 encoding=base64>部分的正确方法是

avatar = images.resize(goodDecode(message.attachments[0][1]), 50, 50)

我发布的原始代码

avatar = images.resize(goodDecode(message.attachments[1]), 50, 50)

显然不起作用。

再次感谢jesmithRobert Kluin寻求答案。


Update0 (关于jesmith的答案)

在我的情况下,我从用户上传的表单中获取图片"img"并将其写入数据存储区,如下所示:

       for row in qTable:
            avatar = images.resize(self.request.get("img"), 50, 50)
            row.avatar = db.Blob(avatar)    
        db.put(qTable)
        self.redirect('/')
    else:
        logging.info("else user not found")
        self.redirect('/user-not-found')

在您的代码中,这与本节相对应,我相信:

try:
    if hasattr(message, "attachment"):
        for a in message.attachments:
            msg.attachmentNames.append(a[0])
            msg.attachmentContents.append(append(db.Blob(goodDecode(a[1])))
        msg.put()        
except:
    logging.exception("exception decoding attachments in email from %s" % message.sender)

假设在我的情况下,只有一个附件;如何获取附件的数据部分?

message.attachment[1]吗?

avatar = images.resize(message.attachment[1], 50, 50)

是附件的message.attachment[1]数据部分吗?

谢谢!

3 个答案:

答案 0 :(得分:2)

这是我使用的传入邮件处理程序的片段:

   bodies = message.bodies(content_type='text/html')
    allBodies = u"";
    for body in bodies:
      allBodies = allBodies + u"\n" + unicode(goodDecode(body[1]), errors="ignore")
    if not allBodies:
      bodies = message.bodies(content_type='text/plain')
      for body in bodies:
        allBodies = allBodies + u"\n" + unicode(goodDecode(body[1]), errors="ignore")

    msg = EmailMessageModel()
...fill in various stuff...
    msg.sender = message.sender
    msg.date = datetime.datetime.now()
    msg.message = allBodies
    # Calling put() before dealing with attachments because it seems like that could throw various exceptions
    msg.put()
    event.email = True
    event.put()
    event.project.email = True
    event.project.put()
    # attachments is a list of element pairs containing file names and contents.

    try:
      if hasattr(message, 'attachments'):
        for a in message.attachments:
          msg.attachmentNames.append(a[0])
          msg.attachmentContents.append(db.Blob(goodDecode(a[1])))
        msg.put()
    except:
      logging.exception("Exception decoding attachments in email from %s" % message.sender)

请注意,goodDecode是我编写的一个函数,因为底层GAE解码中存在一个错误(它降低了所有内容,它使用了base64编码的文本):

def goodDecode(encodedPayload):
  if not hasattr(encodedPayload, 'encoding'):
    return encodedPayload
  encoding = encodedPayload.encoding
  payload = encodedPayload.payload
  if encoding and encoding.lower() != '7bit':
    payload = payload.decode(encoding)
  return payload

这可能不再需要了,因为我很确定他们修复了这个错误。

在我的情况下,我将附件填入数据库:

class EmailMessageModel(db.Model):
....various stuff...
  sender = db.StringProperty()
  date = db.DateTimeProperty()
  message = db.TextProperty()
  attachmentNames = db.StringListProperty()
  attachmentContents = db.ListProperty(db.Blob)

当我想要显示此电子邮件时,我正在使用它:

<h2>{{ e.sender }} {{ e.date|date:"M j, Y f A " }} GMT</h2>
<p>From: {{ e.sender }}<br/>Date: {{ e.date|date:"M j, Y f A" }} GMT ({{ e.date|timesince }} ago)<br/>Subject: {{ e.subject }}</p>
{% if e.attachmentNames %}
<p>Attachments: 
  {% for a in e.attachmentNames %}
<a href="/admin/attachment?email={{ e.key }}&index={{ forloop.counter0 }}" target="_blank">{{ a }}</a>
  {% endfor %}
</p>
{% endif %}
<div style='background-color: white'>{{ e.message }}</div>

附件处理程序是:

class AttachmentHandler(webapp.RequestHandler):
  def get(self):
    email = EmailMessageModel.get(self.request.get('email'))
    index = self.request.get('index')
    if index:
      index = int(index)
      filename = email.attachmentNames[index]
      self.response.headers['Content-Type'] = str(mimetypes.guess_type(filename)[0]) or 'application/octet-stream'
      self.response.out.write(email.attachmentContents[index])

(所以,基本上,我让浏览器弄清楚如何处理附件。)

希望这有帮助!

答案 1 :(得分:1)

查看电子邮件文档中的Handling Incoming Email部分,它解释了附件属性。

  

InboundEmailMessage对象   包括访问其他的属性   消息字段:

     
      
  • 附件是文件附件列表,可能为空。每   列表中的值是两个元组   elements:文件名和文件   内容。
  •   

所以你会想要这样的东西:

for file_name, data in message.attachments:
    # add some tests to check that the
    # file-type is correct and that the
    # data-size is "OK".
    avatar = db.Blob(data)

当用户附加多个图像时,您需要决定如何处理该案例。这将只使用最后一个附件。

答案 2 :(得分:1)

是的,回应您的后续行动:

  

是message.attachment [1]吗?

是的,但你需要解码它。否则,你只会得到一大块ASCII字符(在电子邮件中,附件总是被编码成7位短线,1975年安全格式,例如base64)。

avatar = images.resize(goodDecode(message.attachment[1]), 50, 50)

并且不要忘记在它周围使用大量的try-catch逻辑,因为GAE中的邮件容易抛出许多异常。