作为头像写入数据存储并附加图像:可能吗?

发布于 2024-10-06 17:09:40 字数 3866 浏览 0 评论 0 原文

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

该文档有发送附件,但我找不到任何文档关于接收附件。 此页面显示

附件

消息的文件附件,作为二值元组的列表,每个附件一个元组。

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

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

我认为这也与发送电子邮件有关。

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

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 问题已解决:

作为记录,对于任何有相同问题的人,请注意 邮件属性附件而不是附件

message.attachment

给出AttributeError

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

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

[('portrait.png', <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)

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

message.attachment[1] 吗?

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

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

谢谢!

Has anyone worked with attachments in received emails? I was thinking, instead of the user uploading an image they can send it as an attachment that I can use to upload to datastore.

The documentation has sending attachments but I could not find any documentation about receiving attachments. This page says:

attachments

The file attachments for the message, as a list of two-value tuples, one tuple for each attachment.

Each tuple contains a filename as the first element, and the file contents as the second element.

An attachment file must be one of the allowed file types, and the filename must end with an extension that corresponds with the type. For a list of allowed types and filename extensions, see Overview: Attachments.

I think this is also about sending email.

I have this code to save the image to datastore:

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('/')

Intuitively, it seems that message.attachment instead of "img" will do the trick.

avatar = images.resize(self.request.get(message.attachment), 50, 50)

What do you think? Thanks.


Update2 (New code as response to Nick Johnson's comment)

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 Problem solved:

For the record, and for anyone who has the same question please note that the attribute of message is attachments not attachment:

message.attachment

gives the AttributeError

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

And the object message.attachment looks like this:

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

so the correct way to pull the <EncodedPayload payload=#8461006914571150170 encoding=base64> part is

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

The original code that I posted has

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

which does not work, obviously.

Thanks again to jesmith and Robert Kluin for answers.


Update0 (regarding the answer by jesmith)

In my case, I am taking an image "img" from a form uploaded by a user and write it to datastore like this:

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

In your code this corresponds to this section, I believe:

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)

assuming that, in my case, there is only 1 attachment; how do I pick up the data part of the attachment?

Is it message.attachment[1] ?

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

is message.attachment[1] data part of the attachment?

Thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

甲如呢乙后呢 2024-10-13 17:09:40

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

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

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

希望这有帮助!

This is a fragment from an incoming mail handler I use:

   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)

Note that goodDecode is a function I wrote because there was a bug in the underlying GAE decode (it lowercased everything, which munged base64-encoded text):

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

This is probably not necessary any more, because I'm pretty sure they fixed that bug.

In my case, I'm stuffing the attachments into the database:

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

When I want to show this email, I'm using this:

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

The attachment handler is:

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

(So, basically, I'm letting the browser figure out what to do with the attachments.)

Hope this helps!

老旧海报 2024-10-13 17:09:40

查看电子邮件文档中的处理传入电子邮件部分,它解释附件属性。

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

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

因此,您将需要类似的内容:

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)

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

Review the Handling Incoming Email section in the email docs, it explains the attachments attribute.

The InboundEmailMessage object
includes attributes to access other
message fields:

  • attachments is a list of file attachments, possibly empty. Each
    value in the list is a tuple of two
    elements: the filename and the file
    contents.

So you are going to want something like:

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)

You will need to decide how you want to handle the case when a user attaches more than one image. This will simply use the last of the attachments.

我的黑色迷你裙 2024-10-13 17:09:40

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

是message.attachment[1]吗?

是的,但是你需要解码它。否则,您只会得到一大堆 ASCII 字符(在电子邮件中,附件始终编码为 7 位、短行、1975 年安全格式,例如 base64)。

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

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

Yes, in response to your follow-up:

Is it message.attachment[1] ?

Yes, but you need to decode it. Otherwise, you'll just get a big blob of ASCII characters (in emails, attachments are always encoded into a 7-bit, short line, 1975-safe format, such as base64).

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

And don't forget to use lots of try-catch logic around it, because the mail stuff in GAE is prone to throwing lots of exceptions.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文