@@ -150,6 +150,43 @@ describe('render on node environments', () => {
150150 *
151151 * @see https://github.com/resend/react-email/issues/2353
152152 */
153+ // Regression test for https://github.com/resend/react-email/issues/1667
154+ // and https://github.com/resend/react-email/issues/1932
155+ //
156+ // React's streaming renderer can produce chunks that split multi-byte UTF-8
157+ // characters at chunk boundaries, resulting in NULL bytes (U+0000) in the
158+ // rendered output. Email clients treat NULL as a string terminator, causing
159+ // emails to be truncated mid-content.
160+ it ( 'rendered output contains no NULL bytes with multi-byte characters' , async ( ) => {
161+ const MultiByteTemplate = ( ) => {
162+ const paragraphs = Array ( 30 )
163+ . fill ( null )
164+ . map ( ( _ , i ) => (
165+ < p key = { i } >
166+ 段落{ i } :日本語のテキストを含むメールテンプレートのテストです。
167+ Ärzte und Ünternehmen für Lösung und Grüße aus München.
168+ Тестовая компания приветствует вас в нашем сервисе.
169+ 이메일 템플릿 테스트를 위한 한국어 텍스트입니다.
170+ </ p >
171+ ) ) ;
172+
173+ return (
174+ < div >
175+ < h1 > テスト会社ABCははハハtestあ</ h1 >
176+ { paragraphs }
177+ </ div >
178+ ) ;
179+ } ;
180+
181+ const html = await render ( < MultiByteTemplate /> ) ;
182+
183+ expect ( html ) . not . toContain ( '\0' ) ;
184+ expect ( html ) . toContain ( 'テスト会社ABCははハハtestあ' ) ;
185+ expect ( html ) . toContain ( '日本語のテキスト' ) ;
186+ expect ( html ) . toContain ( 'Ünternehmen' ) ;
187+ expect ( html ) . toContain ( 'Тестовая' ) ;
188+ } ) ;
189+
153190 it ( 'renders large emails without hydration markers' , async ( ) => {
154191 const LargeEmailTemplate = ( ) => {
155192 const largeContent = Array ( 100 )
0 commit comments