From 338498cef1cd4f2b9ae49bc54bd496de0e5472a0 Mon Sep 17 00:00:00 2001 From: mnandri Date: Wed, 16 Dec 2015 16:35:33 +0100 Subject: WIP: rename me later --- service/pixelated/adapter/services/mail_service.py | 36 +++++++++++++++++----- .../pixelated/resources/attachments_resource.py | 15 +++++++-- .../test/integration/test_retrieve_attachment.py | 17 ++++++++++ .../test/support/integration/app_test_client.py | 11 +++++-- service/test/support/test_helper.py | 4 +-- 5 files changed, 69 insertions(+), 14 deletions(-) (limited to 'service') diff --git a/service/pixelated/adapter/services/mail_service.py b/service/pixelated/adapter/services/mail_service.py index 964e4354..2f63a2bc 100644 --- a/service/pixelated/adapter/services/mail_service.py +++ b/service/pixelated/adapter/services/mail_service.py @@ -13,13 +13,17 @@ # # You should have received a copy of the GNU Affero General Public License # along with Pixelated. If not, see . +from email import encoders +from email.mime.nonmultipart import MIMENonMultipart +from email.mime.multipart import MIMEMultipart +from leap.mail.mail import Message + from twisted.internet import defer + from pixelated.adapter.model.mail import InputMail from pixelated.adapter.model.status import Status from pixelated.adapter.services.tag_service import extract_reserved_tags -from email import message_from_file -import os - +from leap.mail.adaptors.soledad import SoledadMailAdaptor class MailService(object): @@ -34,10 +38,28 @@ class MailService(object): mails = yield self.mail_store.all_mails() defer.returnValue(mails) - @defer.inlineCallbacks - def attachment_id(self, _file): - _attachment_id = yield 'mocked_for_now' - defer.returnValue(_attachment_id) + def _attachment_to_cdoc(self, content, content_type, encoder=encoders.encode_base64): + major, sub = content_type.split('/') + attachment = MIMENonMultipart(major, sub) + attachment.set_payload(content) + encoder(attachment) + attachment.add_header('Content-Disposition', 'attachment', filename='does_not_matter.txt') + + pseudo_mail = MIMEMultipart() + pseudo_mail.attach(attachment) + + tmp_mail = SoledadMailAdaptor().get_msg_from_string(MessageClass=Message, raw_msg=pseudo_mail.as_string()) + + cdoc = tmp_mail.get_wrapper().cdocs[1] + return cdoc + + def _calc_attachment_id_(self, content, content_type, encoder=encoders.encode_base64): + cdoc = self._attachment_to_cdoc(content, content_type, encoder) + + return cdoc.phash + + def attachment_id(self, content, content_type): + return self._calc_attachment_id_(content, content_type) @defer.inlineCallbacks def mails(self, query, window_size, page): diff --git a/service/pixelated/resources/attachments_resource.py b/service/pixelated/resources/attachments_resource.py index 667d030e..2b5a6912 100644 --- a/service/pixelated/resources/attachments_resource.py +++ b/service/pixelated/resources/attachments_resource.py @@ -13,6 +13,7 @@ # # You should have received a copy of the GNU Affero General Public License # along with Pixelated. If not, see . +import cgi import io import re @@ -78,16 +79,24 @@ class AttachmentsResource(Resource): def getChild(self, attachment_id, request): return AttachmentResource(self.mail_service, attachment_id) - def render_POST(self, request): - _file = request.args['attachment'][0] + def render_GET(self, request): + return '

' \ + '
' \ + '

' \ + '

' \ + '' - deferred = self.mail_service.attachment_id(_file) + def render_POST(self, request): + fields = cgi.FieldStorage(fp=request.content, headers=request.headers, environ={'REQUEST_METHOD':'POST'}) + _file = fields['attachment'] + deferred = defer.maybeDeferred(self.mail_service.attachment_id, _file.value, _file.type) def send_location(attachment_id): request.headers['Location'] = '/%s/%s'% (self.BASE_URL, attachment_id) respond_json_deferred({"attachment_id": attachment_id}, request, status_code=201) def error_handler(error): + print error respond_json_deferred({"message": "Something went wrong. Attachement not saved."}, request, status_code=500) deferred.addCallback(send_location) diff --git a/service/test/integration/test_retrieve_attachment.py b/service/test/integration/test_retrieve_attachment.py index bc7f8a0d..ca11a14d 100644 --- a/service/test/integration/test_retrieve_attachment.py +++ b/service/test/integration/test_retrieve_attachment.py @@ -13,10 +13,13 @@ # # You should have received a copy of the GNU Affero General Public License # along with Pixelated. If not, see . +import base64 +from email import encoders from email.mime.application import MIMEApplication from email.mime.multipart import MIMEMultipart from email.mime.text import MIMEText +from poster.encode import multipart_encode, MultipartParam from twisted.internet import defer from test.support.integration.soledad_test_base import SoledadTestBase @@ -49,3 +52,17 @@ class RetrieveAttachmentTest(SoledadTestBase): self.assertEqual(404, req.code) self.assertIsNone(attachment) + + @defer.inlineCallbacks + def test_post_new_attachment(self): + content_type = 'text/plain' + filename = 'filename.txt' + data = 'pretend to be binary attachment data' + file = MultipartParam('attachment', value=data, filename=filename, filetype=content_type) + datagen, headers = multipart_encode([file]) + post_data = "".join(datagen) + + _, req = yield self.post_attachment(post_data, headers) + + self.assertEqual(201, req.code) + self.assertEqual('/attachment/B5B4ED80AC3B894523D72E375DACAA2FC6606C18EDF680FE95903086C8B5E14A', req.headers['Location']) diff --git a/service/test/support/integration/app_test_client.py b/service/test/support/integration/app_test_client.py index 484bea6e..5f7eb90a 100644 --- a/service/test/support/integration/app_test_client.py +++ b/service/test/support/integration/app_test_client.py @@ -123,8 +123,9 @@ class AppTestClient(object): request.args = get_args return self._render(request, as_json) - def post(self, path, body=''): - request = request_mock(path=path, method="POST", body=body, headers={'Content-Type': ['application/json']}) + def post(self, path, body='', headers=None): + headers = headers or {'Content-Type': 'application/json'} + request = request_mock(path=path, method="POST", body=body, headers=headers) return self._render(request) def put(self, path, body): @@ -198,6 +199,12 @@ class AppTestClient(object): res = yield deferred_result defer.returnValue((res, req)) + @defer.inlineCallbacks + def post_attachment(self, data, headers): + deferred_result, req = self.post('/attachment', body=data, headers=headers) + res = yield deferred_result + defer.returnValue((res, req)) + def put_mail(self, data): res, req = self.put('/mails', data) return res, req diff --git a/service/test/support/test_helper.py b/service/test/support/test_helper.py index 21f59d8f..703b62fa 100644 --- a/service/test/support/test_helper.py +++ b/service/test/support/test_helper.py @@ -96,8 +96,8 @@ class PixRequestMock(DummyRequest): def request_mock(path='', method='GET', body='', headers={}): dummy = PixRequestMock(path.split('/')) - for name, value in headers.iteritems(): - dummy.setHeader(name, value) + for name, val in headers.iteritems(): + dummy.headers[name.lower()] = val dummy.method = method dummy.content = io.BytesIO(body) return dummy -- cgit v1.2.3