コード例 #1
0
def add_attachments_to_email(email, email_message, inline_headers):
    """ Retrieves all the attachments and adds them to the email. """
    from ..utils import get_attachment_filename_from_url
    for attachment in email.attachments.all():
        if attachment.inline:
            continue

        try:
            storage_file = default_storage._open(attachment.attachment.name)
        except IOError:
            logger.exception(
                'Couldn\'t get attachment, not sending {}:{}'.format(
                    email._meta.db_table, email.id))
            raise

        filename = get_attachment_filename_from_url(attachment.attachment.name)

        storage_file.open()
        content = storage_file.read()
        storage_file.close()

        content_type, encoding = mimetypes.guess_type(filename)
        if content_type is None or encoding is not None:
            content_type = 'application/octet-stream'
        main_type, sub_type = content_type.split('/', 1)

        if main_type == 'text':
            msg = MIMEText(content, _subtype=sub_type)
        elif main_type == 'image':
            msg = MIMEImage(content, _subtype=sub_type)
        elif main_type == 'audio':
            msg = MIMEAudio(content, _subtype=sub_type)
        else:
            msg = MIMEBase(main_type, sub_type)
            msg.set_payload(content)
            Encoders.encode_base64(msg)

        msg.add_header('Content-Disposition',
                       'attachment',
                       filename=os.path.basename(filename))

        email_message.attach(msg)

    # Add the inline attachments to email message header
    for inline_header in inline_headers:
        main_type, sub_type = inline_header['content-type'].split('/', 1)
        if main_type == 'image':
            msg = MIMEImage(inline_header['content'],
                            _subtype=sub_type,
                            name=os.path.basename(
                                inline_header['content-filename']))
            msg.add_header('Content-Disposition',
                           inline_header['content-disposition'],
                           filename=os.path.basename(
                               inline_header['content-filename']))
            msg.add_header('Content-ID', inline_header['content-id'])

            email_message.attach(msg)

    return True
コード例 #2
0
    def get(self, request, *args, **kwargs):
        try:
            attachment = EmailAttachment.objects.get(
                pk=self.kwargs['pk'],
                message__account__tenant_id=self.request.user.tenant.id
            )
        except:
            raise Http404()

        s3_file = default_storage._open(attachment.attachment.name)

        wrapper = FileWrapper(s3_file)
        if hasattr(s3_file, 'key'):
            content_type = s3_file.key.content_type
        else:
            content_type = mimetypes.guess_type(s3_file.file.name)[0]

        response = HttpResponse(wrapper, content_type=content_type)

        inline = 'attachment'
        if attachment.inline:
            inline = 'inline'

        response['Content-Disposition'] = '%s; filename=%s' % (inline, get_attachment_filename_from_url(s3_file.name))
        response['Content-Length'] = attachment.size
        return response
コード例 #3
0
ファイル: views.py プロジェクト: kxion/hellolily
    def get(self, request, *args, **kwargs):
        try:
            attachment = EmailAttachment.objects.get(
                pk=self.kwargs['pk'],
                message__account__tenant_id=self.request.user.tenant.id)
        except:
            raise Http404()

        s3_file = default_storage._open(attachment.attachment.name)

        wrapper = FileWrapper(s3_file)
        if hasattr(s3_file, 'key'):
            content_type = s3_file.key.content_type
        else:
            content_type = mimetypes.guess_type(s3_file.file.name)[0]

        response = HttpResponse(wrapper, content_type=content_type)

        inline = 'attachment'
        if attachment.inline:
            inline = 'inline'

        response['Content-Disposition'] = '%s; filename=%s' % (
            inline, get_attachment_filename_from_url(s3_file.name))
        response['Content-Length'] = attachment.size
        return response
コード例 #4
0
ファイル: tasks.py プロジェクト: noordzij/hellolily
def send_message(email_outbox_message_id, original_message_id=None):
    """
    Send EmailOutboxMessage.

    Args:
        email_outbox_message_id (int): id of the EmailOutboxMessage
        original_message_id (int, optional): ID of the original EmailMessage
    """
    send_logger = logging.getLogger('email_errors_temp_logger')
    send_logger.info('Start sending email_outbox_message: %d' % (email_outbox_message_id,))

    sent_success = False
    try:
        email_outbox_message = EmailOutboxMessage.objects.get(pk=email_outbox_message_id)
    except EmailOutboxMessage.DoesNotExist:
        raise

    email_account = email_outbox_message.send_from

    # If we reply or forward, we want to add the thread_id
    original_message_thread_id = None
    if original_message_id:
        try:
            original_message = EmailMessage.objects.get(pk=original_message_id)
            if original_message.account.id is email_account.id:
                original_message_thread_id = original_message.thread_id
        except EmailMessage.DoesNotExist:
            raise

    # Add template attachments
    if email_outbox_message.template_attachment_ids:
        template_attachment_id_list = email_outbox_message.template_attachment_ids.split(',')
        for template_attachment_id in template_attachment_id_list:
            try:
                template_attachment = EmailTemplateAttachment.objects.get(pk=template_attachment_id)
            except EmailTemplateAttachment.DoesNotExist:
                pass
            else:
                attachment = EmailOutboxAttachment()
                attachment.content_type = template_attachment.content_type
                attachment.size = template_attachment.size
                attachment.email_outbox_message = email_outbox_message
                attachment.attachment = template_attachment.attachment
                attachment.save()

    #  Add attachment from original message (if mail is being forwarded)
    if email_outbox_message.original_attachment_ids:
        original_attachment_id_list = email_outbox_message.original_attachment_ids.split(',')
        for attachment_id in original_attachment_id_list:
            try:
                original_attachment = EmailAttachment.objects.get(pk=attachment_id)
            except EmailAttachment.DoesNotExist:
                pass
            else:
                outbox_attachment = EmailOutboxAttachment()
                outbox_attachment.email_outbox_message = email_outbox_message
                outbox_attachment.tenant_id = original_attachment.message.tenant_id

                file = default_storage._open(original_attachment.attachment.name)
                file.open()
                content = file.read()
                file.close()

                file = ContentFile(content)
                file.name = original_attachment.attachment.name

                outbox_attachment.attachment = file
                outbox_attachment.inline = original_attachment.inline
                outbox_attachment.size = file.size
                outbox_attachment.save()

    if not email_account.is_authorized:
        logger.error('EmailAccount not authorized: %s', email_account)
    else:
        manager = GmailManager(email_account)
        try:
            manager.send_email_message(email_outbox_message.message(), original_message_thread_id)
            logger.debug('Message sent from: %s', email_account)
            # Seems like everything went right, so the EmailOutboxMessage object isn't needed any more
            email_outbox_message.delete()
            sent_success = True
        except ManagerError, e:
            logger.error(traceback.format_exc(e))
            raise
        except Exception, e:
            logger.error(traceback.format_exc(e))
            raise
コード例 #5
0
def send_message(email_outbox_message_id, original_message_id=None):
    """
    Send EmailOutboxMessage.

    Args:
        email_outbox_message_id (int): id of the EmailOutboxMessage
        original_message_id (int, optional): ID of the original EmailMessage
    """
    send_logger = logging.getLogger('email_errors_temp_logger')
    send_logger.info('Start sending email_outbox_message: %d' %
                     (email_outbox_message_id, ))

    sent_success = False
    try:
        email_outbox_message = EmailOutboxMessage.objects.get(
            pk=email_outbox_message_id)
    except EmailOutboxMessage.DoesNotExist:
        raise

    email_account = email_outbox_message.send_from
    if not email_account.is_authorized:
        logger.error('EmailAccount not authorized: %s', email_account)
        return sent_success

    # If we reply or forward, we want to add the thread_id.
    original_message_thread_id = None
    if original_message_id:
        try:
            original_message = EmailMessage.objects.get(pk=original_message_id)
            if original_message.account.id is email_account.id:
                original_message_thread_id = original_message.thread_id
        except EmailMessage.DoesNotExist:
            raise

    # Add template attachments.
    if email_outbox_message.template_attachment_ids:
        template_attachment_id_list = email_outbox_message.template_attachment_ids.split(
            ',')
        for template_attachment_id in template_attachment_id_list:
            try:
                template_attachment = EmailTemplateAttachment.objects.get(
                    pk=template_attachment_id)
            except EmailTemplateAttachment.DoesNotExist:
                pass
            else:
                attachment = EmailOutboxAttachment()
                attachment.content_type = template_attachment.content_type
                attachment.size = template_attachment.size
                attachment.email_outbox_message = email_outbox_message
                attachment.attachment = template_attachment.attachment
                attachment.tenant_id = template_attachment.tenant_id
                attachment.save()

    # Add attachment from original message (if mail is being forwarded).
    if email_outbox_message.original_attachment_ids:
        original_attachment_id_list = email_outbox_message.original_attachment_ids.split(
            ',')
        for attachment_id in original_attachment_id_list:
            try:
                original_attachment = EmailAttachment.objects.get(
                    pk=attachment_id)
            except EmailAttachment.DoesNotExist:
                pass
            else:
                outbox_attachment = EmailOutboxAttachment()
                outbox_attachment.email_outbox_message = email_outbox_message
                outbox_attachment.tenant_id = original_attachment.message.tenant_id

                file = default_storage._open(
                    original_attachment.attachment.name)
                file.open()
                content = file.read()
                file.close()

                file = ContentFile(content)
                file.name = original_attachment.attachment.name

                outbox_attachment.attachment = file
                outbox_attachment.inline = original_attachment.inline
                outbox_attachment.size = file.size
                outbox_attachment.save()

    manager = None
    try:
        manager = GmailManager(email_account)
        manager.send_email_message(email_outbox_message.message(),
                                   original_message_thread_id)
        logger.debug('Message sent from: %s', email_account)
        # Seems like everything went right, so the EmailOutboxMessage object isn't needed any more.
        email_outbox_message.delete()
        sent_success = True
        # TODO: This should probably be moved to the front end once
        # we can notify users about sent mails.
        post_intercom_event(event_name='email-sent',
                            user_id=email_account.owner.id)
    except HttpAccessTokenRefreshError:
        logger.warning('EmailAccount not authorized: %s', email_account)
        pass
    except Exception as e:
        logger.error(traceback.format_exc(e))
        raise
    finally:
        if manager:
            manager.cleanup()

    send_logger.info(
        'Done sending email_outbox_message: %d And sent_succes value: %s' %
        (email_outbox_message_id, sent_success))
    return sent_success
コード例 #6
0
def replace_cid_and_change_headers(html, pk):
    """
    Check in the html source if there is an image tag with the attribute cid. Loop through the attachemnts that are
    linked with the email. If there is a match replace the source of the image with the cid information.
    After read the image information form the disk and put the data in a dummy header.
    At least create a plain text version of the html email.

    Args:
        html (string): HTML string of the email body to be sent.
        mapped_attachments (list): List of linked attachments to the email
        request (instance): The django request

    Returns:
        body_html (string),
        body_text (string),
        dummy_headers (dict)
    """
    if html is None:
        return None

    dummy_headers = []
    inline_images = []
    soup = create_a_beautiful_soup_object(html)
    attachments = EmailAttachment.objects.filter(message_id=pk)

    if soup and attachments:
        inline_images = soup.findAll('img', {'cid': lambda cid: cid})

    if (not soup or soup.get_text() == '') and not inline_images:
        body_html = html
    else:
        cid_done = []

        for image in inline_images:
            image_cid = image['cid']

            for attachment in attachments:
                if (attachment.cid[1:-1] == image_cid or attachment.cid == image_cid) and attachment.cid not in cid_done:
                    image['src'] = "cid:%s" % image_cid

                    storage_file = default_storage._open(attachment.attachment.name)
                    filename = get_attachment_filename_from_url(attachment.attachment.name)

                    if hasattr(storage_file, 'key'):
                        content_type = storage_file.key.content_type
                    else:
                        content_type = mimetypes.guess_type(storage_file.file.name)[0]

                    storage_file.open()
                    content = storage_file.read()
                    storage_file.close()

                    response = {
                        'content-type': content_type,
                        'content-disposition': 'inline',
                        'content-filename': filename,
                        'content-id': attachment.cid,
                        'x-attachment-id': image_cid,
                        'content-transfer-encoding': 'base64',
                        'content': content
                    }

                    dummy_headers.append(response)
                    cid_done.append(attachment.cid)
                    del image['cid']

        body_html = soup.encode_contents()

    body_text_handler = html2text.HTML2Text()
    body_text_handler.ignore_links = True
    body_text_handler.body_width = 0
    body_text = body_text_handler.handle(html)

    return body_html, body_text, dummy_headers
コード例 #7
0
 def _open(self, name, mode='rb'):
     return default_storage._open(name, mode=mode)  # pylint: disable=protected-access
コード例 #8
0
ファイル: models.py プロジェクト: HelloLily/hellolily
    def message(self):
        from ..utils import get_attachment_filename_from_url, replace_cid_and_change_headers

        to = anyjson.loads(self.to)
        cc = anyjson.loads(self.cc)
        bcc = anyjson.loads(self.bcc)

        if self.send_from.from_name:
            # Add account name to From header if one is available
            from_email = '"%s" <%s>' % (Header(u"%s" % self.send_from.from_name, "utf-8"), self.send_from.email_address)
        else:
            # Otherwise only add the email address
            from_email = self.send_from.email_address

        html, text, inline_headers = replace_cid_and_change_headers(self.body, self.original_message_id)

        email_message = SafeMIMEMultipart("related")
        email_message["Subject"] = self.subject
        email_message["From"] = from_email

        if to:
            email_message["To"] = ",".join(list(to))
        if cc:
            email_message["cc"] = ",".join(list(cc))
        if bcc:
            email_message["bcc"] = ",".join(list(bcc))

        email_message_alternative = SafeMIMEMultipart("alternative")
        email_message.attach(email_message_alternative)

        email_message_text = SafeMIMEText(text, "plain", "utf-8")
        email_message_alternative.attach(email_message_text)

        email_message_html = SafeMIMEText(html, "html", "utf-8")
        email_message_alternative.attach(email_message_html)

        for attachment in self.attachments.all():
            if attachment.inline:
                continue

            try:
                storage_file = default_storage._open(attachment.attachment.name)
            except IOError:
                logger.exception("Couldn't get attachment, not sending %s" % self.id)
                return False

            filename = get_attachment_filename_from_url(attachment.attachment.name)

            storage_file.open()
            content = storage_file.read()
            storage_file.close()

            content_type, encoding = mimetypes.guess_type(filename)
            if content_type is None or encoding is not None:
                content_type = "application/octet-stream"
            main_type, sub_type = content_type.split("/", 1)

            if main_type == "text":
                msg = MIMEText(content, _subtype=sub_type)
            elif main_type == "image":
                msg = MIMEImage(content, _subtype=sub_type)
            elif main_type == "audio":
                msg = MIMEAudio(content, _subtype=sub_type)
            else:
                msg = MIMEBase(main_type, sub_type)
                msg.set_payload(content)
                Encoders.encode_base64(msg)

            msg.add_header("Content-Disposition", "attachment", filename=os.path.basename(filename))

            email_message.attach(msg)

        # Add the inline attachments to email message header
        for inline_header in inline_headers:
            main_type, sub_type = inline_header["content-type"].split("/", 1)
            if main_type == "image":
                msg = MIMEImage(
                    inline_header["content"],
                    _subtype=sub_type,
                    name=os.path.basename(inline_header["content-filename"]),
                )
                msg.add_header(
                    "Content-Disposition",
                    inline_header["content-disposition"],
                    filename=os.path.basename(inline_header["content-filename"]),
                )
                msg.add_header("Content-ID", inline_header["content-id"])

                email_message.attach(msg)

        return email_message
コード例 #9
0
    def message(self):
        from ..utils import get_attachment_filename_from_url, replace_cid_and_change_headers

        to = anyjson.loads(self.to)
        cc = anyjson.loads(self.cc)
        bcc = anyjson.loads(self.bcc)

        if self.send_from.from_name:
            # Add account name to From header if one is available
            from_email = '"%s" <%s>' % (Header(
                u'%s' % self.send_from.from_name,
                'utf-8'), self.send_from.email_address)
        else:
            # Otherwise only add the email address
            from_email = self.send_from.email_address

        html, text, inline_headers = replace_cid_and_change_headers(
            self.body, self.original_message_id)

        email_message = SafeMIMEMultipart('related')
        email_message['Subject'] = self.subject
        email_message['From'] = from_email

        if to:
            email_message['To'] = ','.join(list(to))
        if cc:
            email_message['cc'] = ','.join(list(cc))
        if bcc:
            email_message['bcc'] = ','.join(list(bcc))

        email_message_alternative = SafeMIMEMultipart('alternative')
        email_message.attach(email_message_alternative)

        email_message_text = SafeMIMEText(text, 'plain', 'utf-8')
        email_message_alternative.attach(email_message_text)

        email_message_html = SafeMIMEText(html, 'html', 'utf-8')
        email_message_alternative.attach(email_message_html)

        for attachment in self.attachments.all():
            if attachment.inline:
                continue

            try:
                storage_file = default_storage._open(
                    attachment.attachment.name)
            except IOError:
                logger.exception('Couldn\'t get attachment, not sending %s' %
                                 self.id)
                return False

            filename = get_attachment_filename_from_url(
                attachment.attachment.name)

            storage_file.open()
            content = storage_file.read()
            storage_file.close()

            content_type, encoding = mimetypes.guess_type(filename)
            if content_type is None or encoding is not None:
                content_type = 'application/octet-stream'
            main_type, sub_type = content_type.split('/', 1)

            if main_type == 'text':
                msg = MIMEText(content, _subtype=sub_type)
            elif main_type == 'image':
                msg = MIMEImage(content, _subtype=sub_type)
            elif main_type == 'audio':
                msg = MIMEAudio(content, _subtype=sub_type)
            else:
                msg = MIMEBase(main_type, sub_type)
                msg.set_payload(content)
                Encoders.encode_base64(msg)

            msg.add_header('Content-Disposition',
                           'attachment',
                           filename=os.path.basename(filename))

            email_message.attach(msg)

        # Add the inline attachments to email message header
        for inline_header in inline_headers:
            main_type, sub_type = inline_header['content-type'].split('/', 1)
            if main_type == 'image':
                msg = MIMEImage(inline_header['content'],
                                _subtype=sub_type,
                                name=os.path.basename(
                                    inline_header['content-filename']))
                msg.add_header('Content-Disposition',
                               inline_header['content-disposition'],
                               filename=os.path.basename(
                                   inline_header['content-filename']))
                msg.add_header('Content-ID', inline_header['content-id'])

                email_message.attach(msg)

        return email_message
コード例 #10
0
def send_message(email_outbox_message_id, original_message_id=None):
    """
    Send EmailOutboxMessage.

    Args:
        email_outbox_message_id (int): id of the EmailOutboxMessage
        original_message_id (int, optional): ID of the original EmailMessage
    """
    send_logger = logging.getLogger('email_errors_temp_logger')
    send_logger.info('Start sending email_outbox_message: %d' %
                     (email_outbox_message_id, ))

    sent_success = False
    try:
        email_outbox_message = EmailOutboxMessage.objects.get(
            pk=email_outbox_message_id)
    except EmailOutboxMessage.DoesNotExist:
        raise

    email_account = email_outbox_message.send_from

    # If we reply or forward, we want to add the thread_id
    original_message_thread_id = None
    if original_message_id:
        try:
            original_message = EmailMessage.objects.get(pk=original_message_id)
            if original_message.account.id is email_account.id:
                original_message_thread_id = original_message.thread_id
        except EmailMessage.DoesNotExist:
            raise

    # Add template attachments
    if email_outbox_message.template_attachment_ids:
        template_attachment_id_list = email_outbox_message.template_attachment_ids.split(
            ',')
        for template_attachment_id in template_attachment_id_list:
            try:
                template_attachment = EmailTemplateAttachment.objects.get(
                    pk=template_attachment_id)
            except EmailTemplateAttachment.DoesNotExist:
                pass
            else:
                attachment = EmailOutboxAttachment()
                attachment.content_type = template_attachment.content_type
                attachment.size = template_attachment.size
                attachment.email_outbox_message = email_outbox_message
                attachment.attachment = template_attachment.attachment
                attachment.save()

    #  Add attachment from original message (if mail is being forwarded)
    if email_outbox_message.original_attachment_ids:
        original_attachment_id_list = email_outbox_message.original_attachment_ids.split(
            ',')
        for attachment_id in original_attachment_id_list:
            try:
                original_attachment = EmailAttachment.objects.get(
                    pk=attachment_id)
            except EmailAttachment.DoesNotExist:
                pass
            else:
                outbox_attachment = EmailOutboxAttachment()
                outbox_attachment.email_outbox_message = email_outbox_message
                outbox_attachment.tenant_id = original_attachment.message.tenant_id

                file = default_storage._open(
                    original_attachment.attachment.name)
                file.open()
                content = file.read()
                file.close()

                file = ContentFile(content)
                file.name = original_attachment.attachment.name

                outbox_attachment.attachment = file
                outbox_attachment.inline = original_attachment.inline
                outbox_attachment.size = file.size
                outbox_attachment.save()

    if not email_account.is_authorized:
        logger.error('EmailAccount not authorized: %s', email_account)
    else:
        manager = GmailManager(email_account)
        try:
            manager.send_email_message(email_outbox_message.message(),
                                       original_message_thread_id)
            logger.debug('Message sent from: %s', email_account)
            # Seems like everything went right, so the EmailOutboxMessage object isn't needed any more
            email_outbox_message.delete()
            sent_success = True
        except ManagerError, e:
            logger.error(traceback.format_exc(e))
            raise
        except Exception, e:
            logger.error(traceback.format_exc(e))
            raise
コード例 #11
0
ファイル: models.py プロジェクト: noordzij/hellolily
    def message(self):
        from ..utils import get_attachment_filename_from_url, replace_cid_and_change_headers

        to = anyjson.loads(self.to)
        cc = anyjson.loads(self.cc)
        bcc = anyjson.loads(self.bcc)

        if self.send_from.from_name:
            # Add account name to From header if one is available
            from_email = '"%s" <%s>' % (
                Header(u'%s' % self.send_from.from_name, 'utf-8'),
                self.send_from.email_address
            )
        else:
            # Otherwise only add the email address
            from_email = self.send_from.email_address

        html, text, inline_headers = replace_cid_and_change_headers(self.body, self.original_message_id)

        email_message = SafeMIMEMultipart('related')
        email_message['Subject'] = self.subject
        email_message['From'] = from_email

        if to:
            email_message['To'] = ','.join(list(to))
        if cc:
            email_message['cc'] = ','.join(list(cc))
        if bcc:
            email_message['bcc'] = ','.join(list(bcc))

        email_message_alternative = SafeMIMEMultipart('alternative')
        email_message.attach(email_message_alternative)

        email_message_text = SafeMIMEText(text, 'plain', 'utf-8')
        email_message_alternative.attach(email_message_text)

        email_message_html = SafeMIMEText(html, 'html', 'utf-8')
        email_message_alternative.attach(email_message_html)

        for attachment in self.attachments.all():
            if attachment.inline:
                continue

            try:
                storage_file = default_storage._open(attachment.attachment.name)
            except IOError:
                logger.exception('Couldn\'t get attachment, not sending %s' % self.id)
                return False

            filename = get_attachment_filename_from_url(attachment.attachment.name)

            storage_file.open()
            content = storage_file.read()
            storage_file.close()

            content_type, encoding = mimetypes.guess_type(filename)
            if content_type is None or encoding is not None:
                content_type = 'application/octet-stream'
            main_type, sub_type = content_type.split('/', 1)

            if main_type == 'text':
                msg = MIMEText(content, _subtype=sub_type)
            elif main_type == 'image':
                msg = MIMEImage(content, _subtype=sub_type)
            elif main_type == 'audio':
                msg = MIMEAudio(content, _subtype=sub_type)
            else:
                msg = MIMEBase(main_type, sub_type)
                msg.set_payload(content)
                Encoders.encode_base64(msg)

            msg.add_header('Content-Disposition', 'attachment', filename=os.path.basename(filename))

            email_message.attach(msg)

        # Add the inline attachments to email message header
        for inline_header in inline_headers:
            main_type, sub_type = inline_header['content-type'].split('/', 1)
            if main_type == 'image':
                msg = MIMEImage(
                    inline_header['content'],
                    _subtype=sub_type,
                    name=os.path.basename(inline_header['content-filename'])
                )
                msg.add_header(
                    'Content-Disposition',
                    inline_header['content-disposition'],
                    filename=os.path.basename(inline_header['content-filename'])
                )
                msg.add_header('Content-ID', inline_header['content-id'])

                email_message.attach(msg)

        return email_message
コード例 #12
0
ファイル: models.py プロジェクト: HelloLily/hellolily
def add_attachments_to_email(email, email_message, inline_headers):
    """ Retrieves all the attachments and adds them to the email. """
    from ..utils import get_attachment_filename_from_url
    for attachment in email.attachments.all():
        if attachment.inline:
            continue

        try:
            storage_file = default_storage._open(attachment.attachment.name)
        except IOError:
            logger.exception(
                'Couldn\'t get attachment, not sending {}:{}'.format(
                    email._meta.db_table,
                    email.id
                )
            )
            raise

        filename = get_attachment_filename_from_url(attachment.attachment.name)

        storage_file.open()
        content = storage_file.read()
        storage_file.close()

        content_type, encoding = mimetypes.guess_type(filename)
        if content_type is None or encoding is not None:
            content_type = 'application/octet-stream'
        main_type, sub_type = content_type.split('/', 1)

        if main_type == 'text':
            msg = MIMEText(content, _subtype=sub_type)
        elif main_type == 'image':
            msg = MIMEImage(content, _subtype=sub_type)
        elif main_type == 'audio':
            msg = MIMEAudio(content, _subtype=sub_type)
        else:
            msg = MIMEBase(main_type, sub_type)
            msg.set_payload(content)
            Encoders.encode_base64(msg)

        msg.add_header('Content-Disposition', 'attachment', filename=os.path.basename(filename))

        email_message.attach(msg)

    # Add the inline attachments to email message header
    for inline_header in inline_headers:
        main_type, sub_type = inline_header['content-type'].split('/', 1)
        if main_type == 'image':
            msg = MIMEImage(
                inline_header['content'],
                _subtype=sub_type,
                name=os.path.basename(inline_header['content-filename'])
            )
            msg.add_header(
                'Content-Disposition',
                inline_header['content-disposition'],
                filename=os.path.basename(inline_header['content-filename'])
            )
            msg.add_header('Content-ID', inline_header['content-id'])

            email_message.attach(msg)

    return True
コード例 #13
0
ファイル: tasks.py プロジェクト: ernsyn/hellolily
def send_message(email_id, original_message_id=None, draft=False):
    """
    Send EmailOutboxMessage or EmailDraft.

    Args:
        email_outbox_message_id (int): id of the EmailOutboxMessage
        original_message_id (int, optional): ID of the original EmailMessage
        draft (bool, optional): whether the newer EmailDraft should be queried
    """
    send_logger = logging.getLogger('email_errors_temp_logger')
    send_logger.info('Start sending email_outbox_message: %d' % (email_id,))

    # Below describes the differences between EmailOutboxMessage and EmailDraft.
    # As soon as EmailDraft is proven to work, this class can be refactored to only work for EmailDraft.
    email_class = EmailOutboxMessage
    email_attachment_class = EmailOutboxAttachment
    email_attachment_to_email_class_field_name = 'email_outbox_message'
    email_message_function_name = 'message'
    if draft:
        email_class = EmailDraft
        email_attachment_class = EmailDraftAttachment
        email_attachment_to_email_class_field_name = 'email_draft'
        email_message_function_name = 'mime_message'

    sent_success = False
    try:
        email = email_class.objects.get(pk=email_id)
    except email_class.DoesNotExist:
        raise

    email_account = email.send_from
    if not email_account.is_authorized:
        logger.error('EmailAccount not authorized: %s', email_account)
        return sent_success

    # If we reply or forward, we want to add the thread_id.
    original_message_thread_id = None
    if original_message_id:
        try:
            original_message = EmailMessage.objects.get(pk=original_message_id)
            if original_message.account.id is email_account.id:
                original_message_thread_id = original_message.thread_id
        except EmailMessage.DoesNotExist:
            raise

    # Add template attachments.
    if email.template_attachment_ids:
        template_attachment_id_list = email.template_attachment_ids.split(',')
        for template_attachment_id in template_attachment_id_list:
            try:
                template_attachment = EmailTemplateAttachment.objects.get(pk=template_attachment_id)
            except EmailTemplateAttachment.DoesNotExist:
                pass
            else:
                attachment = email_attachment_class()
                attachment.content_type = template_attachment.content_type
                attachment.size = template_attachment.size
                setattr(attachment, email_attachment_to_email_class_field_name, email)
                attachment.attachment = template_attachment.attachment
                attachment.tenant_id = template_attachment.tenant_id
                attachment.save()

    # Add attachment from original message (if mail is being forwarded).
    if email.original_attachment_ids:
        original_attachment_id_list = email.original_attachment_ids.split(',')
        for attachment_id in original_attachment_id_list:
            try:
                original_attachment = EmailAttachment.objects.get(pk=attachment_id)
            except EmailAttachment.DoesNotExist:
                pass
            else:
                outbox_attachment = email_attachment_class()
                setattr(outbox_attachment, email_attachment_to_email_class_field_name, email)
                outbox_attachment.tenant_id = original_attachment.message.tenant_id

                file = default_storage._open(original_attachment.attachment.name)
                file.open()
                content = file.read()
                file.close()

                file = ContentFile(content)
                file.name = original_attachment.attachment.name

                outbox_attachment.attachment = file
                outbox_attachment.inline = original_attachment.inline
                outbox_attachment.size = file.size
                outbox_attachment.save()

    manager = None
    try:
        manager = GmailManager(email_account)
        manager.send_email_message(getattr(email, email_message_function_name)(), original_message_thread_id)
        logger.debug('Message sent from: %s', email_account)
        # Seems like everything went right, so the EmailOutboxMessage object isn't needed any more.
        email.delete()
        sent_success = True
        # TODO: This should probably be moved to the front end once
        # we can notify users about sent mails.
        post_intercom_event(event_name='email-sent', user_id=email_account.owner.id)
    except HttpAccessTokenRefreshError:
        logger.warning('EmailAccount not authorized: %s', email_account)
        pass
    except Exception as e:
        logger.error(traceback.format_exc(e))
        raise
    finally:
        if manager:
            manager.cleanup()

    send_logger.info('Done sending {}: {} And sent_succes value: {}'.format(
        email_attachment_to_email_class_field_name,
        email_id,
        sent_success
    ))

    return sent_success
コード例 #14
0
def send_message(email_outbox_message_id, original_message_id=None):
    """
    Send EmailOutboxMessage.

    Args:
        email_outbox_message_id (int): id of the EmailOutboxMessage
        original_message_id (int, optional): ID of the original EmailMessage
    """
    send_logger = logging.getLogger('email_errors_temp_logger')
    send_logger.info('Start sending email_outbox_message: %d' % (email_outbox_message_id,))

    sent_success = False
    try:
        email_outbox_message = EmailOutboxMessage.objects.get(pk=email_outbox_message_id)
    except EmailOutboxMessage.DoesNotExist:
        raise

    email_account = email_outbox_message.send_from
    if not email_account.is_authorized:
        logger.error('EmailAccount not authorized: %s', email_account)
        return sent_success

    # If we reply or forward, we want to add the thread_id.
    original_message_thread_id = None
    if original_message_id:
        try:
            original_message = EmailMessage.objects.get(pk=original_message_id)
            if original_message.account.id is email_account.id:
                original_message_thread_id = original_message.thread_id
        except EmailMessage.DoesNotExist:
            raise

    # Add template attachments.
    if email_outbox_message.template_attachment_ids:
        template_attachment_id_list = email_outbox_message.template_attachment_ids.split(',')
        for template_attachment_id in template_attachment_id_list:
            try:
                template_attachment = EmailTemplateAttachment.objects.get(pk=template_attachment_id)
            except EmailTemplateAttachment.DoesNotExist:
                pass
            else:
                attachment = EmailOutboxAttachment()
                attachment.content_type = template_attachment.content_type
                attachment.size = template_attachment.size
                attachment.email_outbox_message = email_outbox_message
                attachment.attachment = template_attachment.attachment
                attachment.tenant_id = template_attachment.tenant_id
                attachment.save()

    # Add attachment from original message (if mail is being forwarded).
    if email_outbox_message.original_attachment_ids:
        original_attachment_id_list = email_outbox_message.original_attachment_ids.split(',')
        for attachment_id in original_attachment_id_list:
            try:
                original_attachment = EmailAttachment.objects.get(pk=attachment_id)
            except EmailAttachment.DoesNotExist:
                pass
            else:
                outbox_attachment = EmailOutboxAttachment()
                outbox_attachment.email_outbox_message = email_outbox_message
                outbox_attachment.tenant_id = original_attachment.message.tenant_id

                file = default_storage._open(original_attachment.attachment.name)
                file.open()
                content = file.read()
                file.close()

                file = ContentFile(content)
                file.name = original_attachment.attachment.name

                outbox_attachment.attachment = file
                outbox_attachment.inline = original_attachment.inline
                outbox_attachment.size = file.size
                outbox_attachment.save()

    manager = None
    try:
        manager = GmailManager(email_account)
        manager.send_email_message(email_outbox_message.message(), original_message_thread_id)
        logger.debug('Message sent from: %s', email_account)
        # Seems like everything went right, so the EmailOutboxMessage object isn't needed any more.
        email_outbox_message.delete()
        sent_success = True
        # TODO: This should probably be moved to the front end once
        # we can notify users about sent mails.
        post_intercom_event(event_name='email-sent', user_id=email_account.owner.id)
    except HttpAccessTokenRefreshError:
        logger.warning('EmailAccount not authorized: %s', email_account.email_address)
        pass
    except Exception as e:
        logger.error(traceback.format_exc(e))
        raise
    finally:
        if manager:
            manager.cleanup()

    send_logger.info(
        'Done sending email_outbox_message: %d And sent_succes value: %s' % (email_outbox_message_id, sent_success)
    )
    return sent_success