Skip to content

fix(gmail): add HTML draft creation guidance to generated skill#568

Open
kleinq wants to merge 1 commit intogoogleworkspace:mainfrom
kleinq:fix/gmail-draft-html-formatting
Open

fix(gmail): add HTML draft creation guidance to generated skill#568
kleinq wants to merge 1 commit intogoogleworkspace:mainfrom
kleinq:fix/gmail-draft-html-formatting

Conversation

@kleinq
Copy link

@kleinq kleinq commented Mar 19, 2026

Problem

When creating Gmail drafts via gws gmail users drafts create, users naturally
pass plain-text bodies in the raw RFC 2822 message. Plain-text emails are
line-wrapped by email clients (typically at 72–76 chars), breaking paragraph
flow and making the draft look unprofessional.

Fix

Add a ## Creating Drafts section to the generated gws-gmail skill that:

  • Explains the wrapping problem and why HTML is required
  • Shows the exact paragraph/newline → <div>/<br> conversion pattern
    (matching how Gmail's native compose formats messages)
  • Provides a copy-paste Python snippet to build and base64url-encode the
    RFC 2822 message with Content-Type: text/html

This is a gmail-specific section (guarded by alias == "gmail") so it only
appears in the gws-gmail skill, not in other service skills.

Testing

Run gws generate-skills after this change; the generated
skills/gws-gmail/SKILL.md should contain the new ## Creating Drafts
section before ## Discovering Commands.

@changeset-bot
Copy link

changeset-bot bot commented Mar 19, 2026

⚠️ No Changeset found

Latest commit: 2eec4f7

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@google-cla
Copy link

google-cla bot commented Mar 19, 2026

Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA).

View this failed invocation of the CLA check for more information.

For the most up to date status, view the checks section at the bottom of the pull request.

@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request enhances the gws-gmail skill documentation by integrating comprehensive guidance on how to create well-formatted Gmail drafts using HTML. It addresses the common issue of plain-text emails being improperly line-wrapped, ensuring that generated drafts maintain their intended paragraph flow and professional appearance.

Highlights

  • Problem with plain-text Gmail drafts: Plain-text emails created via gws gmail users drafts create often suffer from line wrapping by email clients, leading to unprofessional formatting.
  • Solution: HTML draft creation guidance: New documentation has been added to the gws-gmail skill to guide users on creating properly formatted HTML drafts.
  • HTML conversion pattern: The guidance details the conversion pattern: double newlines become paragraph breaks (<div>...</div> separated by <div><br></div>), single newlines become <br>, and the entire body is wrapped in <div dir="ltr">...</div>.
  • Python snippet for RFC 2822 message: A copy-paste Python snippet is provided to construct and base64url-encode the RFC 2822 message with Content-Type: text/html, demonstrating the conversion.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.

Footnotes

  1. Review the Generative AI Prohibited Use Policy, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

The pull request introduces valuable guidance for creating HTML-formatted Gmail drafts, addressing the common issue of line wrapping in plain-text emails. The addition of a Python snippet to demonstrate the conversion process is very helpful. However, the Python snippet has a potential Cross-Site Scripting (XSS) vulnerability due to unsanitized user input being directly inserted into HTML. This should be addressed to prevent malicious content from being rendered.

out.push_str("subject = \"Your Subject\"\n");
out.push_str("body = \"\"\"Paragraph one line one.\\nStill paragraph one.\\n\\nParagraph two.\"\"\"\n\n");
out.push_str("paragraphs = body.split('\\n\\n')\n");
out.push_str("html_parts = ['<div>' + p.replace('\\n', '<br>').strip() + '</div>' for p in paragraphs]\n");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

security-high high

The Python snippet constructs HTML by directly inserting the body content without proper HTML escaping. If the body variable contains malicious HTML or script tags (e.g., <script>alert('XSS')</script>), this could lead to a Cross-Site Scripting (XSS) vulnerability when the email is viewed by a recipient. It's crucial to HTML-escape any user-provided text that will be rendered as HTML to prevent such attacks.

To fix this, you should escape the p variable before concatenating it into the div tag. Python's html module (specifically html.escape) can be used for this purpose. Alternatively, if using a templating engine, it would handle escaping automatically.

For example, you could modify the line to include html.escape(p):

import html
# ... other code ...
html_parts = ['<div>' + html.escape(p.replace('\n', '<br>').strip()) + '</div>' for p in paragraphs]
Suggested change
out.push_str("html_parts = ['<div>' + p.replace('\\n', '<br>').strip() + '</div>' for p in paragraphs]\n");
html_parts = ['<div>' + html.escape(p.replace('\n', '<br>').strip()) + '</div>' for p in paragraphs]
References
  1. Sanitize error strings printed to the terminal to prevent escape sequence injection.

out.push_str("- Wrap in `<div dir=\"ltr\">...</div>`\n\n");
out.push_str("```bash\n");
out.push_str("python3 - <<'PYEOF'\n");
out.push_str("import base64\n\n");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

To support the suggested fix for XSS in the html_parts generation, the html module needs to be imported. Please add import html at the beginning of the Python snippet.

Suggested change
out.push_str("import base64\n\n");
import base64
import html

@malob
Copy link
Contributor

malob commented Mar 19, 2026

FWIW, I've got adding draft support for the +send, +reply, +reply-all, and +forward helpers (which all support sending sending HTML emails using the --html flag) ready to go: malob@93997d9

(Just waiting on another PR to land which touches at lot of the same code.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants