Написание и прикрепление изображения к хранилищу данных в качестве аватара: возможно ли это? - PullRequest
1 голос
/ 05 декабря 2010

Кто-нибудь работал с вложениями в полученных письмах? Я думал, что вместо того, чтобы загружать изображение, пользователь может отправить его как вложение, которое я могу использовать для загрузки в хранилище данных.

В документации отправка вложений , но я не смог найти никакой документации о получении вложений. На этой странице написано :

1010 * вложений *

Файл вложений для сообщения в виде списка двухзначных кортежей, по одному кортежу для каждого вложения.

Каждый кортеж содержит имя файла в качестве первого элемента и содержимое файла в качестве второго элемента.

Файл вложения должен быть одного из разрешенных типов файлов, а имя файла должно заканчиваться расширением, соответствующим типу. Список разрешенных типов и расширений файлов см. В разделе Обзор: вложения.

Я думаю, это также касается отправки электронной почты.

У меня есть этот код для сохранения изображения в хранилище данных:

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 (Новый код в ответ на комментарий Ника Джонсона)

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 Проблема решена:

Для записи и для тех, у кого есть тот же вопрос, обратите внимание, что атрибут сообщения *1043* равен attachments, а не 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)

который не работает, очевидно.

Еще раз спасибо jesmith и Robert Kluin за ответы.


Обновление0 (относительно ответа 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] частью данных вложения?

Спасибо! * * 1092

Ответы [ 3 ]

2 голосов
/ 05 декабря 2010

Это фрагмент обработчика входящей почты, который я использую:

   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 голос
/ 05 декабря 2010

Да, в ответ на ваше наблюдение:

Это message.attachment [1]?

Да, но вам нужно его расшифровать. В противном случае вы просто получите большой набор символов ASCII (в сообщениях электронной почты вложения всегда кодируются в 7-битный формат с короткими строками, безопасный для 1975 года, например, base64).

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

И не забывайте использовать множество логик try-catch вокруг него, потому что почтовый материал в GAE склонен к созданию множества исключений.

1 голос
/ 05 декабря 2010

Просмотрите раздел Обработка входящей электронной почты в документах электронной почты, в нем объясняется атрибут вложения.

Объект 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)

Вынужно будет решить, как вы хотите обработать случай, когда пользователь присоединяет более одного изображения.Это будет просто использовать последний из вложений.

...