feat: added smtp support to email#342
feat: added smtp support to email#342arianpotter wants to merge 2 commits intoOpenpanel-dev:mainfrom
Conversation
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
📝 WalkthroughWalkthroughAdds SMTP as an alternative email delivery backend alongside Resend, updates environment templates/examples, adds SMTP and render dependencies, and implements conditional routing in Changes
Sequence Diagram(s)sequenceDiagram
participant App as Application
participant Email as sendEmail
participant Renderer as `@react-email/render`
participant SMTP as Nodemailer
participant Resend as Resend API
App->>Email: sendEmail(template, data)
Email->>Email: build subject
Email->>Email: generate unsubscribe headers
alt SMTP_HOST configured
Email->>Renderer: render template -> HTML
Renderer-->>Email: HTML
Email->>SMTP: transport.sendMail({from,to,subject,html,headers})
SMTP-->>Email: send result
else RESEND_API_KEY configured
Email->>Resend: resend.emails.send({to,from,subject,html or template,...})
Resend-->>Email: send result
else No provider
Email-->>App: return null + log error
end
Email-->>App: return send result
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~22 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🧪 Generate unit tests (beta)
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.
Actionable comments posted: 1
🧹 Nitpick comments (1)
packages/email/src/index.tsx (1)
76-85: Add a plain-text body for SMTP emails.The SMTP path currently sends only HTML.
@react-email/renderexportstoPlainTextto derive plain text from rendered HTML, which improves compatibility for clients that prefer or require text bodies.✉️ Proposed plain-text fallback
-import { render } from '@react-email/render'; +import { render, toPlainText } from '@react-email/render';const html = await render( <template.Component {...(props.data as any)} />, ); + const text = toPlainText(html); const transport = createSmtpTransport(); const res = await transport.sendMail({ from: FROM, to, subject, html, + text, headers, });🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/email/src/index.tsx` around lines 76 - 85, The SMTP send currently only sets html; derive a plain-text body and include it in the sendMail call by importing and using toPlainText from `@react-email/render` to convert the rendered html into text, then pass that text as the text property to transport.sendMail (locate where render(...) produces html for template.Component and where createSmtpTransport() and transport.sendMail({...}) are called and add the text field).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@packages/email/src/index.tsx`:
- Around line 18-27: The createSmtpTransport function can mis-handle an empty
SMTP_PORT (Number('') === 0) and lacks explicit timeouts; update
createSmtpTransport (where createTransport is called) to use a safe port parse
like: if process.env.SMTP_PORT is set use Number(process.env.SMTP_PORT)
otherwise default to 587, and add nodemailer timeout options (connectionTimeout,
greetingTimeout, socketTimeout) with sensible values to avoid long stalls; also
keep the existing auth logic and secure parsing as-is.
---
Nitpick comments:
In `@packages/email/src/index.tsx`:
- Around line 76-85: The SMTP send currently only sets html; derive a plain-text
body and include it in the sendMail call by importing and using toPlainText from
`@react-email/render` to convert the rendered html into text, then pass that text
as the text property to transport.sendMail (locate where render(...) produces
html for template.Component and where createSmtpTransport() and
transport.sendMail({...}) are called and add the text field).
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 0d780cc6-00cd-4d05-bb13-2c9ceaba19aa
⛔ Files ignored due to path filters (1)
pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (4)
.env.examplepackages/email/package.jsonpackages/email/src/index.tsxself-hosting/.env.template
Add SMTP support as alternative to Resend (issue #320)
Overview
Email sending now supports two transports: SMTP (via nodemailer) and Resend. If
SMTP_HOSTis set, SMTP is used. Otherwise it falls back to Resend. If neither is configured, the email payload is logged to console (existing dev behavior).How it works
SMTP_HOST set? → render template to HTML → send via nodemailer
↓ no
RESEND_API_KEY set? → send via Resend (unchanged behavior)
↓ no
Log to console (dev fallback)
Implementation details
packages/email/src/index.tsx@react-email/renderto convert React Email JSX templates to plain HTML strings — required for SMTP since nodemailer doesn't understand JSXnodemailerfor SMTP transportcreateSmtpTransport()readsSMTP_HOST/PORT/SECURE/USER/PASSfrom envList-Unsubscribe) are preserved for both transportsNew dependencies
nodemailer+@types/nodemailer— SMTP client@react-email/render— HTML renderer for React Email templatesConfiguration
SMTP_HOSTSMTP_PORT587SMTP_SECUREfalse"true"for TLS (port 465)SMTP_USERSMTP_PASSEMAIL_SENDERhello@openpanel.devBoth
.env.exampleandself-hosting/.env.templatehave been updated with the new variables and comments explaining the two options.Summary by CodeRabbit
New Features
Configuration