-
Notifications
You must be signed in to change notification settings - Fork 3.4k
[WEB-5917] fix: generate clean plain text from HTML email template. #8535
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: preview
Are you sure you want to change the base?
Conversation
|
Linked to Plane Work Item(s) This comment was auto-generated by Plane |
📝 WalkthroughWalkthroughA new utility function Changes
Estimated code review effort🎯 2 (Simple) | ⏱️ ~10 minutes Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (2)
apps/api/plane/utils/email.py (1)
19-42: Consider handling<script>tags and HTML entities for robustness.The implementation handles
<style>tags well, but a few edge cases could improve robustness:
<script>tags: While unlikely in email templates, any script content would leak into plain text.- HTML entities:
strip_tagsdoesn't decode entities like ,&,<, etc., which may appear in the plain-text output.♻️ Suggested enhancement
# Python imports +import html import re # Django imports from django.utils.html import strip_tags def generate_plain_text_from_html(html_content): """ Generate clean plain text from HTML email template. Removes all HTML tags, CSS styles, and excessive whitespace. Args: html_content (str): The HTML content to convert to plain text Returns: str: Clean plain text without HTML tags, styles, or excessive whitespace """ + if not html_content: + return "" + # Remove style tags and their content html_content = re.sub(r"<style[^>]*>.*?</style>", "", html_content, flags=re.DOTALL | re.IGNORECASE) + # Remove script tags and their content (defensive) + html_content = re.sub(r"<script[^>]*>.*?</script>", "", html_content, flags=re.DOTALL | re.IGNORECASE) + # Strip HTML tags text_content = strip_tags(html_content) + # Decode HTML entities + text_content = html.unescape(text_content) + # Remove excessive empty lines text_content = re.sub(r"\n\s*\n\s*\n+", "\n\n", text_content) - # Ensure there's a leading and trailing whitespace + # Ensure there's a leading and trailing newline text_content = "\n\n" + text_content.lstrip().rstrip() + "\n\n" return text_contentapps/api/plane/bgtasks/forgot_password_task.py (1)
7-8: Duplicate comment block.There's a redundant
# Third party importscomment on line 8. The Django imports section already has its header on line 7, and third-party imports (Celery) are correctly commented on line 4.Suggested fix
# Django imports -# Third party imports from django.core.mail import EmailMultiAlternatives, get_connection
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (12)
apps/api/plane/bgtasks/analytic_plot_export.pyapps/api/plane/bgtasks/email_notification_task.pyapps/api/plane/bgtasks/forgot_password_task.pyapps/api/plane/bgtasks/magic_link_code_task.pyapps/api/plane/bgtasks/project_add_user_email_task.pyapps/api/plane/bgtasks/project_invitation_task.pyapps/api/plane/bgtasks/user_activation_email_task.pyapps/api/plane/bgtasks/user_deactivation_email_task.pyapps/api/plane/bgtasks/user_email_update_task.pyapps/api/plane/bgtasks/webhook_task.pyapps/api/plane/bgtasks/workspace_invitation_task.pyapps/api/plane/utils/email.py
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-12-23T14:18:32.899Z
Learnt from: dheeru0198
Repo: makeplane/plane PR: 8339
File: apps/api/plane/db/models/api.py:35-35
Timestamp: 2025-12-23T14:18:32.899Z
Learning: Django REST Framework rate limit strings are flexible: only the first character of the time unit matters. Acceptable formats include: "60/s", "60/sec", "60/second" (all equivalent), "60/m", "60/min", "60/minute" (all equivalent), "60/h", "60/hr", "60/hour" (all equivalent), and "60/d", "60/day" (all equivalent). Abbreviations like "min" are valid and do not need to be changed to "minute". Apply this guidance to any Python files in the project that configure DRF throttling rules.
Applied to files:
apps/api/plane/utils/email.pyapps/api/plane/bgtasks/webhook_task.pyapps/api/plane/bgtasks/magic_link_code_task.pyapps/api/plane/bgtasks/user_deactivation_email_task.pyapps/api/plane/bgtasks/workspace_invitation_task.pyapps/api/plane/bgtasks/analytic_plot_export.pyapps/api/plane/bgtasks/forgot_password_task.pyapps/api/plane/bgtasks/project_add_user_email_task.pyapps/api/plane/bgtasks/email_notification_task.pyapps/api/plane/bgtasks/user_email_update_task.pyapps/api/plane/bgtasks/project_invitation_task.pyapps/api/plane/bgtasks/user_activation_email_task.py
🧬 Code graph analysis (11)
apps/api/plane/bgtasks/webhook_task.py (1)
apps/api/plane/utils/email.py (1)
generate_plain_text_from_html(19-42)
apps/api/plane/bgtasks/magic_link_code_task.py (1)
apps/api/plane/utils/email.py (1)
generate_plain_text_from_html(19-42)
apps/api/plane/bgtasks/user_deactivation_email_task.py (1)
apps/api/plane/utils/email.py (1)
generate_plain_text_from_html(19-42)
apps/api/plane/bgtasks/workspace_invitation_task.py (1)
apps/api/plane/utils/email.py (1)
generate_plain_text_from_html(19-42)
apps/api/plane/bgtasks/analytic_plot_export.py (1)
apps/api/plane/utils/email.py (1)
generate_plain_text_from_html(19-42)
apps/api/plane/bgtasks/forgot_password_task.py (1)
apps/api/plane/utils/email.py (1)
generate_plain_text_from_html(19-42)
apps/api/plane/bgtasks/project_add_user_email_task.py (1)
apps/api/plane/utils/email.py (1)
generate_plain_text_from_html(19-42)
apps/api/plane/bgtasks/email_notification_task.py (1)
apps/api/plane/utils/email.py (1)
generate_plain_text_from_html(19-42)
apps/api/plane/bgtasks/user_email_update_task.py (1)
apps/api/plane/utils/email.py (1)
generate_plain_text_from_html(19-42)
apps/api/plane/bgtasks/project_invitation_task.py (1)
apps/api/plane/utils/email.py (1)
generate_plain_text_from_html(19-42)
apps/api/plane/bgtasks/user_activation_email_task.py (1)
apps/api/plane/utils/email.py (1)
generate_plain_text_from_html(19-42)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
- GitHub Check: Cursor Bugbot
- GitHub Check: Analyze (javascript)
🔇 Additional comments (13)
apps/api/plane/bgtasks/workspace_invitation_task.py (1)
14-14: LGTM!The import and usage of
generate_plain_text_from_htmlare correct. This improves the plain-text email content by removing style blocks and excessive whitespace, which will also benefit the storedmessagefield.Also applies to: 56-59
apps/api/plane/bgtasks/magic_link_code_task.py (1)
14-14: LGTM!The import and usage of
generate_plain_text_from_htmlare correct and consistent with the other task files.Also applies to: 36-36
apps/api/plane/bgtasks/user_deactivation_email_task.py (1)
14-14: LGTM!The import and usage are correct and follow the same pattern as the other email task files.
Also applies to: 30-30
apps/api/plane/bgtasks/project_add_user_email_task.py (1)
14-14: LGTM!The import and usage of
generate_plain_text_from_htmlare correct and consistent with the refactor across all email task files.Also applies to: 58-58
apps/api/plane/bgtasks/user_email_update_task.py (1)
13-13: LGTM!The import and usage of
generate_plain_text_from_htmlis correctly implemented in bothsend_email_update_magic_codeandsend_email_update_confirmationfunctions. This provides cleaner plain-text email content by properly stripping styles and excessive whitespace.Also applies to: 35-35, 86-86
apps/api/plane/bgtasks/forgot_password_task.py (1)
14-14: LGTM!The import and usage of
generate_plain_text_from_htmlis correctly implemented in theforgot_passwordfunction.Also applies to: 44-44
apps/api/plane/bgtasks/analytic_plot_export.py (1)
20-20: LGTM!The import and usage of
generate_plain_text_from_htmlis correctly implemented in thesend_export_emailhelper function, which serves bothanalytic_export_taskandexport_analytics_to_csv_emailtasks.Also applies to: 51-51
apps/api/plane/bgtasks/email_notification_task.py (1)
19-19: LGTM!The import and usage of
generate_plain_text_from_htmlis correctly implemented in thesend_email_notificationtask. The plain-text conversion now properly handles style tags and excessive whitespace.Also applies to: 259-259
apps/api/plane/bgtasks/user_activation_email_task.py (1)
14-14: LGTM!The import and usage of
generate_plain_text_from_htmlis correctly implemented in theuser_activation_emailtask.Also applies to: 30-30
apps/api/plane/bgtasks/webhook_task.py (2)
49-49: LGTM!Import is correctly placed with other module imports and aligns with the PR objective.
220-221: LGTM!The replacement of
strip_tagswithgenerate_plain_text_from_htmlproperly handles style tag removal and whitespace normalization for cleaner email plain-text output.apps/api/plane/bgtasks/project_invitation_task.py (2)
15-15: LGTM!Import is correctly added alongside other module imports.
38-43: LGTM!The change correctly applies the improved HTML-to-text conversion. Note that
generate_plain_text_from_htmladds leading/trailing newlines to the output, which will now be stored inproject_member_invite.message. This should be fine as it's whitespace normalization for consistent formatting.
Description
Generate clean plain text from HTML email template.
Removes all HTML tags, CSS styles, and excessive whitespace.
Type of Change
Screenshots and Media (if applicable)
Test Scenarios
References
Note
Improves plain-text generation for all outbound emails.
plane/utils/email.pywithgenerate_plain_text_from_htmlto strip<style>blocks, remove HTML, collapse whitespace, and normalize spacingstrip_tagswithgenerate_plain_text_from_htmlin multiple tasks:email_notification_task,forgot_password_task,magic_link_code_task,project_add_user_email_task,project_invitation_task,workspace_invitation_task,user_activation_email_task,user_deactivation_email_task,user_email_update_task,webhook_task, and analytics export (analytic_plot_export)Written by Cursor Bugbot for commit 1c7a98d. This will update automatically on new commits. Configure here.
Summary by CodeRabbit
Release Notes
✏️ Tip: You can customize this high-level summary in your review settings.