Esempio n. 1
0
    def notify_reset_password(self, user: User,
                              reset_password_token: str) -> None:
        """
        Reset password link for user
        :param user: user to notify
        :param reset_password_token: token for resetting password
        """
        logger.debug(self, "user: {}".format(user.user_id))
        logger.info(self,
                    "Generating reset password email to {}".format(user.email))
        translator = Translator(self.config, default_lang=user.lang)
        email_sender = EmailSender(self.config, self._smtp_config,
                                   self.config.EMAIL__NOTIFICATION__ACTIVATED)
        translated_subject = translator.get_translation(
            self.config.EMAIL__NOTIFICATION__RESET_PASSWORD_REQUEST__SUBJECT)
        subject = translated_subject.replace(EST.WEBSITE_TITLE,
                                             str(self.config.WEBSITE__TITLE))
        from_header = self._get_sender()
        to_header = EmailAddress(user.get_display_name(), user.email)

        html_template_file_path = (
            self.config.
            EMAIL__NOTIFICATION__RESET_PASSWORD_REQUEST__TEMPLATE__HTML)
        # TODO - G.M - 2018-08-17 - Generate token
        context = {
            "user":
            user,
            "logo_url":
            get_email_logo_frontend_url(self.config),
            "reset_password_url":
            get_reset_password_frontend_url(self.config,
                                            token=reset_password_token,
                                            email=user.email),
        }

        body_html = self._render_template(
            mako_template_filepath=html_template_file_path,
            context=context,
            translator=translator)
        message = EmailNotificationMessage(
            subject=subject,
            from_header=from_header,
            to_header=to_header,
            body_html=body_html,
            lang=translator.default_lang,
        )
        send_email_through(config=self.config,
                           sendmail_callable=email_sender.send_mail,
                           message=message)
Esempio n. 2
0
    def notify_created_account(
            self,
            user: User,
            password: str,
            origin_user: typing.Optional[User] = None) -> None:
        """
        Send created account email to given user.

        :param password: choosed password
        :param user: user to notify
        """
        logger.info(self,
                    "Generating created account mail to {}".format(user.email))

        email_sender = EmailSender(self.config, self._smtp_config,
                                   self.config.EMAIL__NOTIFICATION__ACTIVATED)
        translator = Translator(self.config, default_lang=user.lang)
        translated_subject = translator.get_translation(
            self.config.EMAIL__NOTIFICATION__CREATED_ACCOUNT__SUBJECT)
        subject = translated_subject.replace(EST.WEBSITE_TITLE,
                                             str(self.config.WEBSITE__TITLE))
        from_header = self._get_sender(origin_user)
        to_header = EmailAddress(user.get_display_name(), user.email)
        html_template_file_path = self.config.EMAIL__NOTIFICATION__CREATED_ACCOUNT__TEMPLATE__HTML

        context = {
            "origin_user": origin_user,
            "user": user,
            "password": password,
            "logo_url": get_email_logo_frontend_url(self.config),
            "login_url": get_login_frontend_url(self.config),
        }
        translator = Translator(self.config, default_lang=user.lang)
        body_html = self._render_template(
            mako_template_filepath=html_template_file_path,
            context=context,
            translator=translator)
        message = EmailNotificationMessage(
            subject=subject,
            from_header=from_header,
            to_header=to_header,
            body_html=body_html,
            lang=translator.default_lang,
        )

        send_email_through(config=self.config,
                           sendmail_callable=email_sender.send_mail,
                           message=message)
Esempio n. 3
0
    def notify_reset_password(self, user: User, reset_password_token: str) -> None:
        """
        Reset password link for user
        :param user: user to notify
        :param reset_password_token: token for resetting password
        """
        logger.debug(self, "user: {}".format(user.user_id))
        logger.info(self, "Generating reset password email to {}".format(user.email))
        translator = Translator(self.config, default_lang=user.lang)
        email_sender = EmailSender(
            self.config, self._smtp_config, self.config.EMAIL__NOTIFICATION__ACTIVATED
        )
        translated_subject = translator.get_translation(
            self.config.EMAIL__NOTIFICATION__RESET_PASSWORD_REQUEST__SUBJECT
        )
        subject = translated_subject.replace(EST.WEBSITE_TITLE, str(self.config.WEBSITE__TITLE))
        message = MIMEMultipart("alternative")
        message["Subject"] = subject
        message["From"] = self._get_sender()
        message["To"] = formataddr((user.get_display_name(), user.email))

        html_template_file_path = (
            self.config.EMAIL__NOTIFICATION__RESET_PASSWORD_REQUEST__TEMPLATE__HTML
        )
        # TODO - G.M - 2018-08-17 - Generate token
        context = {
            "user": user,
            "logo_url": get_email_logo_frontend_url(self.config),
            "reset_password_url": get_reset_password_frontend_url(
                self.config, token=reset_password_token, email=user.email
            ),
        }

        body_html = self._render_template(
            mako_template_filepath=html_template_file_path, context=context, translator=translator
        )

        part2 = MIMEText(body_html, "html", "utf-8")

        # Attach parts into message container.
        # According to RFC 2046, the last part of a multipart message,
        # in this case the HTML message, is best and preferred.
        message.attach(part2)

        send_email_through(
            config=self.config, sendmail_callable=email_sender.send_mail, message=message
        )
Esempio n. 4
0
    def notify_created_account(self, user: User, password: str) -> None:
        """
        Send created account email to given user.

        :param password: choosed password
        :param user: user to notify
        """
        logger.info(self, "Generating created account mail to {}".format(user.email))

        email_sender = EmailSender(
            self.config, self._smtp_config, self.config.EMAIL__NOTIFICATION__ACTIVATED
        )
        translator = Translator(self.config, default_lang=user.lang)
        translated_subject = translator.get_translation(
            self.config.EMAIL__NOTIFICATION__CREATED_ACCOUNT__SUBJECT
        )
        subject = translated_subject.replace(EST.WEBSITE_TITLE, str(self.config.WEBSITE__TITLE))
        message = MIMEMultipart("alternative")
        message["Subject"] = subject
        message["From"] = self._get_sender()
        message["To"] = formataddr((user.get_display_name(), user.email))

        html_template_file_path = self.config.EMAIL__NOTIFICATION__CREATED_ACCOUNT__TEMPLATE__HTML

        context = {
            "user": user,
            "password": password,
            "logo_url": get_email_logo_frontend_url(self.config),
            "login_url": get_login_frontend_url(self.config),
        }
        translator = Translator(self.config, default_lang=user.lang)
        body_html = self._render_template(
            mako_template_filepath=html_template_file_path, context=context, translator=translator
        )

        part2 = MIMEText(body_html, "html", "utf-8")

        # Attach parts into message container.
        # According to RFC 2046, the last part of a multipart message,
        # in this case the HTML message, is best and preferred.
        message.attach(part2)

        send_email_through(
            config=self.config, sendmail_callable=email_sender.send_mail, message=message
        )
Esempio n. 5
0
    def _build_context_for_content_update(
        self,
        role: UserRoleInWorkspace,
        content_in_context: ContentInContext,
        parent_in_context: typing.Optional[ContentInContext],
        workspace_in_context: WorkspaceInContext,
        actor: User,
        translator: Translator,
    ):

        _ = translator.get_translation
        content = content_in_context.content
        action = content.get_last_action().id
        previous_revision = content.get_previous_revision()
        new_status = _(content.get_status().label)
        workspace_url = workspace_in_context.frontend_url
        role_label = role.role_as_label()
        logo_url = get_email_logo_frontend_url(self.config)

        # FIXME: remove/readapt assert to debug easily broken case
        # assert user
        # assert workspace
        # assert main_title
        # assert status_label
        # # assert status_icon_url
        # assert role_label
        # # assert content_intro
        # assert content_text or content_text == content.description
        # assert logo_url

        return {
            "user": role.user,
            "actor": actor,
            "action": action,
            "workspace": role.workspace,
            "ActionDescription": ActionDescription,
            "parent_in_context": parent_in_context,
            "content_in_context": content_in_context,
            "workspace_url": workspace_url,
            "previous_revision": previous_revision,
            "new_status": new_status,
            "role_label": role_label,
            "logo_url": logo_url,
        }
Esempio n. 6
0
    def _build_context_for_content_update(
            self,
            role: UserRoleInWorkspace,
            content_in_context: ContentInContext,
            parent_in_context: typing.Optional[ContentInContext],
            workspace_in_context: WorkspaceInContext,
            actor: User,
            translator: Translator
    ):

        _ = translator.get_translation
        content = content_in_context.content
        action = content.get_last_action().id

        # default values
        user = role.user
        workspace = role.workspace
        workspace_url = workspace_in_context.frontend_url
        main_title = content.label
        status_label = content.get_status().label
        # TODO - G.M - 11-06-2018 - [emailTemplateURL] correct value for status_icon_url  # nopep8
        status_icon_url = ''
        role_label = role.role_as_label()
        content_intro = '<span id="content-intro-username">{}</span> did something.'.format(actor.display_name)  # nopep8
        content_text = content.description
        call_to_action_url = content_in_context.frontend_url
        logo_url = get_email_logo_frontend_url(self.config)

        if ActionDescription.COMMENT == action:
            main_title = parent_in_context.label
            content_intro = ''
            call_to_action_url = parent_in_context.frontend_url
        elif ActionDescription.STATUS_UPDATE == action:
            new_status = translator.get_translation(content.get_status().label)
            main_title = content_in_context.label
            content_intro = _('I modified the status of <i>{content}</i>. The new status is <i>{new_status}</i>').format(
                content=content.get_label(),
                new_status=new_status
            )
            content_text = ''
            call_to_action_url = content_in_context.frontend_url
        elif ActionDescription.CREATION == action:
            main_title = content_in_context.label
            content_intro = _('I added an item entitled <i>{content}</i>.').format(content=content.get_label())  # nopep8
            content_text = ''
        elif action in (ActionDescription.REVISION, ActionDescription.EDITION):
            main_title = content_in_context.label
            content_intro = _('I updated <i>{content}</i>.').format(content=content.get_label())  # nopep8

            previous_revision = content.get_previous_revision()
            title_diff = htmldiff(previous_revision.label, content.label)
            content_diff = htmldiff(previous_revision.description, content.description)
            if title_diff or content_diff:
                content_text = str('<p>{diff_intro_text}</p>\n{title_diff}\n{content_diff}').format(  # nopep8
                    diff_intro_text=_('Here is an overview of the changes:'),
                    title_diff=title_diff,
                    content_diff=content_diff
                )
        # if not content_intro and not content_text:
        #     # Skip notification, but it's not normal
        #     logger.error(
        #         self,
        #         'A notification is being sent but no content. '
        #         'Here are some debug informations: [content_id: {cid}]'
        #         '[action: {act}][author: {actor}]'.format(
        #             cid=content.content_id,
        #             act=action,
        #             actor=actor
        #         )
        #     )
        #     raise EmptyNotificationError('Unexpected empty notification')

        # FIXME: remove/readapt assert to debug easily broken case
        assert user
        assert workspace
        assert main_title
        assert status_label
        # assert status_icon_url
        assert role_label
        # assert content_intro
        assert content_text or content_text == content.description
        assert call_to_action_url
        assert logo_url

        return {
            'user': role.user,
            'workspace': role.workspace,
            'workspace_url': workspace_url,
            'main_title': main_title,
            'status_label': status_label,
            'status_icon_url': status_icon_url,
            'role_label': role_label,
            'content_intro': content_intro,
            'content_text': content_text,
            'call_to_action_url': call_to_action_url,
            'logo_url': logo_url,
        }
Esempio n. 7
0
    def _build_context_for_content_update(
            self,
            role: UserRoleInWorkspace,
            content_in_context: ContentInContext,
            parent_in_context: typing.Optional[ContentInContext],
            workspace_in_context: WorkspaceInContext,
            actor: User,
            translator: Translator
    ):

        _ = translator.get_translation
        content = content_in_context.content
        action = content.get_last_action().id

        # default values
        user = role.user
        workspace = role.workspace
        workspace_url = workspace_in_context.frontend_url
        main_title = content.label
        status_label = content.get_status().label
        # TODO - G.M - 11-06-2018 - [emailTemplateURL] correct value for status_icon_url  # nopep8
        status_icon_url = ''
        role_label = role.role_as_label()
        content_intro = '<span id="content-intro-username">{}</span> did something.'.format(actor.display_name)  # nopep8
        content_text = content.description
        call_to_action_text = 'See more'
        call_to_action_url = content_in_context.frontend_url
        logo_url = get_email_logo_frontend_url(self.config)

        if ActionDescription.CREATION == action:
            call_to_action_text = _('View online')
            content_intro = _('<span id="content-intro-username">{}</span> create a content:').format(actor.display_name)  # nopep8

            if content_type_list.Thread.slug == content.type:
                if content.get_last_comment_from(actor):
                    content_text = content.get_last_comment_from(actor).description  # nopep8

                call_to_action_text = _('Answer')
                content_intro = _('<span id="content-intro-username">{}</span> started a thread entitled:').format(actor.display_name)
                content_text = '<p id="content-body-intro">{}</p>'.format(content.label) + content_text  # nopep8

            elif content_type_list.File.slug == content.type:
                content_intro = _('<span id="content-intro-username">{}</span> added a file entitled:').format(actor.display_name)
                if content.description:
                    content_text = content.description
                else:
                    content_text = '<span id="content-body-only-title">{}</span>'.format(content.label)

            elif content_type_list.Page.slug == content.type:
                content_intro = _('<span id="content-intro-username">{}</span> added a page entitled:').format(actor.display_name)
                content_text = '<span id="content-body-only-title">{}</span>'.format(content.label)

        elif ActionDescription.REVISION == action:
            content_text = content.description
            call_to_action_text = _('View online')

            if content_type_list.File.slug == content.type:
                content_intro = _('<span id="content-intro-username">{}</span> uploaded a new revision.').format(actor.display_name)
                content_text = content.description

        elif ActionDescription.EDITION == action:
            call_to_action_text = _('View online')

            if content_type_list.File.slug == content.type:
                content_intro = _('<span id="content-intro-username">{}</span> updated the file description.').format(actor.display_name)
                content_text = '<p id="content-body-intro">{}</p>'.format(content.get_label()) + content.description  # nopep8

            elif content_type_list.Thread.slug == content.type:
                content_intro = _('<span id="content-intro-username">{}</span> updated the thread description.').format(actor.display_name)
                previous_revision = content.get_previous_revision()
                title_diff = ''
                if previous_revision.label != content.label:
                    title_diff = htmldiff(previous_revision.label, content.label)
                content_text = str('<p id="content-body-intro">{}</p> {text} {title_diff} {content_diff}').format(
                    text=_('Here is an overview of the changes:'),
                    title_diff=title_diff,
                    content_diff=htmldiff(previous_revision.description, content.description)
                )
            elif content_type_list.Page.slug == content.type:
                content_intro = _('<span id="content-intro-username">{}</span> updated this page.').format(actor.display_name)
                previous_revision = content.get_previous_revision()
                title_diff = ''
                if previous_revision.label != content.label:
                    title_diff = htmldiff(previous_revision.label, content.label)  # nopep8
                content_text = str('<p id="content-body-intro">{}</p> {text}</p> {title_diff} {content_diff}').format(  # nopep8
                    actor.display_name,
                    text=_('Here is an overview of the changes:'),
                    title_diff=title_diff,
                    content_diff=htmldiff(previous_revision.description, content.description)
                )

        elif ActionDescription.STATUS_UPDATE == action:
            intro_user_msg = _(
                '<span id="content-intro-username">{}</span> '
                'updated the following status:'
            )
            intro_body_msg = '<p id="content-body-intro">{}: {}</p>'

            call_to_action_text = _('View online')
            content_intro = intro_user_msg.format(actor.display_name)
            content_text = intro_body_msg.format(
                content.get_label(),
                content.get_status().label,
            )

        elif ActionDescription.COMMENT == action:
            call_to_action_text = _('Answer')
            main_title = parent_in_context.label
            content_intro = _('<span id="content-intro-username">{}</span> added a comment:').format(actor.display_name)  # nopep8
            call_to_action_url = parent_in_context.frontend_url

        if not content_intro and not content_text:
            # Skip notification, but it's not normal
            logger.error(
                self,
                'A notification is being sent but no content. '
                'Here are some debug informations: [content_id: {cid}]'
                '[action: {act}][author: {actor}]'.format(
                    cid=content.content_id,
                    act=action,
                    actor=actor
                )
            )
            raise EmptyNotificationError('Unexpected empty notification')

        # FIXME: remove/readapt assert to debug easily broken case
        assert user
        assert workspace
        assert main_title
        assert status_label
        # assert status_icon_url
        assert role_label
        assert content_intro
        assert content_text or content_text == content.description
        assert call_to_action_text
        assert call_to_action_url
        assert logo_url

        return {
            'user': role.user,
            'workspace': role.workspace,
            'workspace_url': workspace_url,
            'main_title': main_title,
            'status_label': status_label,
            'status_icon_url': status_icon_url,
            'role_label': role_label,
            'content_intro': content_intro,
            'content_text': content_text,
            'call_to_action_text': call_to_action_text,
            'call_to_action_url': call_to_action_url,
            'logo_url': logo_url,
        }
Esempio n. 8
0
    def notify_reset_password(
            self,
            user: User,
            reset_password_token: str,
    ) -> None:
        """
        Reset password link for user
        :param user: user to notify
        :param reset_password_token: token for resetting password
        """
        logger.debug(self, 'user: {}'.format(user.user_id))
        logger.info(self, 'Sending asynchronous email to 1 user ({0})'.format(
            user.email,
        ))
        translator = Translator(self.config, default_lang=user.lang)
        async_email_sender = EmailSender(
            self.config,
            self._smtp_config,
            self.config.EMAIL_NOTIFICATION_ACTIVATED
        )
        subject = self.config.EMAIL_NOTIFICATION_RESET_PASSWORD_SUBJECT.replace(
            EST.WEBSITE_TITLE,
            str(self.config.WEBSITE_TITLE)
        )
        message = MIMEMultipart('alternative')
        message['Subject'] = subject
        message['From'] = self._get_sender()
        message['To'] = formataddr((user.get_display_name(), user.email))

        text_template_file_path = self.config.EMAIL_NOTIFICATION_RESET_PASSWORD_TEMPLATE_TEXT  # nopep8
        html_template_file_path = self.config.EMAIL_NOTIFICATION_RESET_PASSWORD_TEMPLATE_HTML  # nopep8
        # TODO - G.M - 2018-08-17 - Generate token
        context = {
            'user': user,
            'logo_url': get_email_logo_frontend_url(self.config),
            'reset_password_url': get_reset_password_frontend_url(
                self.config,
                token=reset_password_token,
                email=user.email,
            ),
        }
        body_text = self._render_template(
            mako_template_filepath=text_template_file_path,
            context=context,
            translator=translator,
        )

        body_html = self._render_template(
            mako_template_filepath=html_template_file_path,
            context=context,
            translator=translator,
        )

        part1 = MIMEText(body_text, 'plain', 'utf-8')
        part2 = MIMEText(body_html, 'html', 'utf-8')

        # Attach parts into message container.
        # According to RFC 2046, the last part of a multipart message,
        # in this case the HTML message, is best and preferred.
        message.attach(part1)
        message.attach(part2)

        send_email_through(
            config=self.config,
            sendmail_callable=async_email_sender.send_mail,
            message=message
        )
Esempio n. 9
0
    def notify_created_account(
            self,
            user: User,
            password: str,
    ) -> None:
        """
        Send created account email to given user.

        :param password: choosed password
        :param user: user to notify
        """
        # TODO BS 20160712: Cyclic import
        logger.debug(self, 'user: {}'.format(user.user_id))
        logger.info(self, 'Sending asynchronous email to 1 user ({0})'.format(
            user.email,
        ))

        async_email_sender = EmailSender(
            self.config,
            self._smtp_config,
            self.config.EMAIL_NOTIFICATION_ACTIVATED
        )

        subject = \
            self.config.EMAIL_NOTIFICATION_CREATED_ACCOUNT_SUBJECT \
            .replace(
                EST.WEBSITE_TITLE,
                str(self.config.WEBSITE_TITLE)
            )
        message = MIMEMultipart('alternative')
        message['Subject'] = subject
        message['From'] = self._get_sender()
        message['To'] = formataddr((user.get_display_name(), user.email))

        text_template_file_path = self.config.EMAIL_NOTIFICATION_CREATED_ACCOUNT_TEMPLATE_TEXT  # nopep8
        html_template_file_path = self.config.EMAIL_NOTIFICATION_CREATED_ACCOUNT_TEMPLATE_HTML  # nopep8

        context = {
            'user': user,
            'password': password,
            'logo_url': get_email_logo_frontend_url(self.config),
            'login_url': get_login_frontend_url(self.config),
        }
        translator = Translator(self.config, default_lang=user.lang)
        body_text = self._render_template(
            mako_template_filepath=text_template_file_path,
            context=context,
            translator=translator
        )

        body_html = self._render_template(
            mako_template_filepath=html_template_file_path,
            context=context,
            translator=translator
        )

        part1 = MIMEText(body_text, 'plain', 'utf-8')
        part2 = MIMEText(body_html, 'html', 'utf-8')

        # Attach parts into message container.
        # According to RFC 2046, the last part of a multipart message,
        # in this case the HTML message, is best and preferred.
        message.attach(part1)
        message.attach(part2)

        send_email_through(
            config=self.config,
            sendmail_callable=async_email_sender.send_mail,
            message=message
        )