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)
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)
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 )
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 )
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, }
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, }
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, }
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 )
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 )