Repository navigation
Conversation
EmailService.SendEmail derives a text/plain alternative from the final HTML when the caller gives none, and every provider sends it: SMTP and Amazon SES as a multipart/alternative part, SendGrid, Mailgun, Postmark, Mailjet and SparkPost through their text field. An email whose HTML holds nothing to read is still sent as HTML only.
The preview endpoint now returns the text/plain version an email would be sent with, derived from the tracked HTML exactly as a send does. Send-time compiles do not compute it, so a broadcast still converts each email once. A link followed by punctuation keeps it attached in the text.
The visual editor gets a Text version mode next to Edit and Preview, the MJML editor a Text version tab, and the template preview drawer a Text version tab, all showing the text the email is sent with. The editor toolbar labels are now translated.
Transactional and broadcast emails are read back raw from Mailpit: each is multipart/alternative with the text first, the text links to exactly the URLs the HTML links to, tracked or direct as the recipient consented, and templates.compile returns the same text.
Bump the version, rebuild the web analytics SDK bundle that embeds it, add the changelog entry and the implementation plan.
List items stored as paragraphs, as the visual editor stores them, keep their marker on the same line, honour an ordered list's start and indent their following lines. A social element's icon is left out when its row then links with a label, including with click tracking. Two line breaks leave an empty line, and punctuation after a URL is separated from a word that follows it. The code editor's text tab waits for the first compile.
A social element's icon and its labelled link are both written when click tracking gives them different URLs: nothing in the HTML says they lead to the same place, and leaving out an unlabelled link next to a labelled one could drop a link written nowhere else. Punctuation followed by a closing quote stays attached to the link before it.
…rsion Autolinkers take a closing quote right after a URL into the link, which broke it, a tracked link answering 400. Only ASCII punctuation stays attached.
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## dev #504 +/- ##
==========================================
+ Coverage 88.73% 88.77% +0.03%
==========================================
Files 365 366 +1
Lines 71231 71512 +281
==========================================
+ Hits 63210 63484 +274
+ Misses 5397 5396 -1
- Partials 2624 2632 +8
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
43.1 is released, so the plain-text version moves to 43.2: version bumped, SDK bundle rebuilt, catalogs re-extracted from dev with the new strings translated.
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #443.
What it does
Every email now goes out with a
text/plainalternative next to its HTML, generated at send time from the final HTML (after link tracking), so the text links are tracked or direct exactly as decided for the recipient. No schema change, no new environment variable, nothing stored in the queue payload.pkg/plaintext(FromHTML, ongolang.org/x/net/html, no new dependency): paragraphs, headings, lists (including the<li><p>markup of the visual editor and<ol start>), blockquotes,pre,hr; links aslabel (url),mailto:/tel:targets, linked images by theiralt; head, scripts, styles, form controls, hidden elements and the inbox preheader are skipped; invisible padding characters removed; a space always separates a URL from the next word, and only ASCII punctuation stays attached after a URL. Returns""when the HTML holds nothing to read, and the email is then sent as HTML only.SendEmailProviderRequest.TextContent, filled inEmailService.SendEmailwhen the caller gives none. Providers: SMTP (multipart/alternative, text first), Amazon SES simple (Body.Text) and raw MIME (mixed > alternative { text, related { html, inline } } + attachments), SendGrid (text/plainfirst, as required), Mailgun form and multipart (text), Postmark (TextBody), Mailjet (TextPart), SparkPost (content.text). Each field is absent when there is no text.templates.compilereturnstext(only when called by the preview endpoint:IncludeTextisjson:"-", so send-time compiles do not convert twice). Console: a Text version mode next to Edit and Preview in the visual editor, a Text version tab in the MJML editor and in the template preview drawer. The editor toolbar labels are now translated; new strings translated in the 8 catalogs.plans/feat-plain-text-alternative-plan.md. Docs: Document the plain-text version of emails docs#27.Tests
FuzzFromHTML, script never leaks, at most one blank line, valid UTF-8), benchmark; MIME tree of every SMTP and SES shape; exact body of each HTTP provider with and without text;SendEmailgeneration; compile (IncludeText, web channel, errors, URL-set equality with the HTML hrefs with tracking on and off, golden template); handler.tests/integration/plain_text_alternative_e2e_test.go, Mailpit raw MIME): transactional and broadcast emails aremultipart/alternativewith text first, the text links to exactly the URLs of the HTML, tracked for a consenting contact and direct for one who refused click tracking,List-Unsubscribekept,templates.compilereturns the text.go test -race ./internal/... ./pkg/..., fullmake test-integration(on11faeff), then after the dev merge the plain-text, List-Unsubscribe and inline-CID e2e tests,cd console && npx vitest run(173 files),tsc -b, eslint on touched files.Review status — in progress
Plan reviewed before implementation; code reviewed three times (whole PR, then each correction). The last blocking finding (typographic closing quotes
”,’,»read by autolinkers as part of a URL) is fixed in4133bc2with a test for a bare URL followed by each closer. The fix and the dev merge (3baffee) are under review.Known, not handled
Facebook (…)): the two links get different tokens, and nothing in the HTML says they lead to the same place. An earlier attempt to drop the icon lost destinations in other layouts and was removed.<pre>or a nested list misplaces its marker;start="3px"numbers from 1; URLs inside<pre>are not separated from the following text.mailto:with only a query (mailto:?subject=…) gives an empty target.pkg/mailersystem emails put their text part last; the API fieldemail.textof a template is still unused (custom text is a later PR).