Python 作为化身写入数据存储并将图像附加到数据存储:可能吗?

Python 作为化身写入数据存储并将图像附加到数据存储:可能吗?,python,google-app-engine,email,google-cloud-datastore,Python,Google App Engine,Email,Google Cloud Datastore,是否有人在收到的电子邮件中使用附件?我在想,用户不用上传图像,而是可以将其作为附件发送,我可以用它上传到数据存储 文档已被删除,但我找不到任何关于接收附件的文档: 附件 邮件的文件附件,作为两个值元组的列表,每个附件一个元组 每个元组包含一个文件名作为第一个元素,文件内容作为第二个元素 附件文件必须是允许的文件类型之一,并且文件名必须以与该类型对应的扩展名结尾。有关允许的类型和文件扩展名的列表,请参阅概述:附件 我认为这也是关于发送电子邮件 我有以下代码将图像保存到数据存储: class Ava

是否有人在收到的电子邮件中使用附件?我在想,用户不用上传图像,而是可以将其作为附件发送,我可以用它上传到数据存储

文档已被删除,但我找不到任何关于接收附件的文档:

附件

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

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

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

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

我有以下代码将图像保存到数据存储:

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)
你觉得怎么样?谢谢


更新2(回应尼克·约翰逊评论的新代码)


更新1问题已解决:

为了记录在案,对于任何有相同问题的人,请注意,是
附件
而不是
附件

message.attachment
给出
属性错误

AttributeError: 'InboundEmailMessage' object has no attribute 'attachment'
对象
message.attachment
如下所示:

[('portrait.png', <EncodedPayload payload=#8461006914571150170 encoding=base64>)]
       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')
        
我发布的原始代码

avatar = images.resize(goodDecode(message.attachments[1]), 50, 50)
这显然是行不通的

再次感谢
jesmith
Robert Kluin
的回答


更新0(关于jesmith的回答)

在我的例子中,我从用户上传的表单中获取图像
“img”
,并将其写入数据存储,如下所示:

[('portrait.png', <EncodedPayload payload=#8461006914571150170 encoding=base64>)]
       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)
假设,在我的情况下,只有1个附件;如何提取附件的数据部分

是否是
消息。附件[1]

avatar = images.resize(message.attachment[1], 50, 50)
            
message.attachment[1]
数据是附件的一部分吗

谢谢

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

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

  • 附件是文件附件的列表,可能为空。每个 列表中的值是两个元组 元素:文件名和文件名 内容
因此,您将需要以下内容:

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)
当用户附加多个图像时,您需要决定如何处理该情况。这将只使用最后一个附件。

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

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

  • 附件是文件附件的列表,可能为空。每个 列表中的值是两个元组 元素:文件名和文件名 内容
因此,您将需要以下内容:

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)

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

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

   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 decode中有一个bug(它将所有内容都小写,其中包含base64编码的文本):

这可能不再需要了,因为我很确定他们已经修复了这个bug

在我的例子中,我正在将附件填充到数据库中:

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>
(因此,基本上,我让浏览器决定如何处理附件。)


希望这有帮助

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

   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 decode中有一个bug(它将所有内容都小写,其中包含base64编码的文本):

这可能不再需要了,因为我很确定他们已经修复了这个bug

在我的例子中,我正在将附件填充到数据库中:

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>
(因此,基本上,我让浏览器决定如何处理附件。)


希望这有帮助

是的,针对您的后续行动:

是邮件吗?附件[1]

是的,但你需要解码。否则,您只会得到大量ASCII字符(在电子邮件中,附件总是编码为7位、短线、1975安全格式,如base64)


别忘了使用大量的try-catch逻辑,因为GAE中的邮件很容易抛出大量异常。

是的,作为对后续操作的响应:

是邮件吗?附件[1]

是的,但你需要解码。否则,您只会得到大量ASCII字符(在电子邮件中,附件总是编码为7位、短线、1975安全格式,如base64)


不要忘记使用大量的try-catch逻辑,因为GAE中的邮件内容容易抛出大量异常。

非常感谢您的回复。这很有帮助。我添加了一个更新,其中有一个问题是关于如何使您的代码适应我的情况。我感谢你的帮助。再次感谢。非常感谢您的回复。这很有帮助。我添加了一个更新,其中有一个问题是关于如何使您的代码适应我的情况。我感谢你的帮助。再次感谢。为什么不使用电子邮件作为用户实体的密钥名?您的模型允许复制用户,您可以获取其中10个,并使用虚拟形象更新所有用户(?!)-这似乎很奇怪。@尼克,谢谢您指出这一点。我删除了那个密码;因为我意识到用户只是在注册;我不需要注册新用户的电子邮件;保存到数据库中;然后再次拉它来更新化身。所以现在我在一个p里做了所有的事情