@@ -10,6 +10,8 @@ class Resend extends EmailAdapter
1010{
1111 protected const NAME = 'Resend ' ;
1212
13+ protected const MAX_ATTACHMENT_BYTES = 40 * 1024 * 1024 ;
14+
1315 /**
1416 * @param string $apiKey Your Resend API key to authenticate with the API.
1517 */
@@ -29,9 +31,8 @@ public function getMaxMessagesPerRequest(): int
2931 }
3032
3133 /**
32- * Uses Resend's batch sending API to send multiple emails at once.
33- *
3434 * @link https://resend.com/docs/api-reference/emails/send-batch-emails
35+ * @link https://resend.com/docs/api-reference/emails/send-email
3536 */
3637 protected function process (EmailMessage $ message ): array
3738 {
@@ -77,7 +78,7 @@ protected function process(EmailMessage $message): array
7778
7879 $ emails = [];
7980 foreach ($ message ->getTo () as $ to ) {
80- $ toFormatted = !empty ($ to ['name ' ])
81+ $ toFormatted = ! empty ($ to ['name ' ])
8182 ? "{$ to ['name ' ]} < {$ to ['email ' ]}> "
8283 : $ to ['email ' ];
8384
@@ -133,19 +134,33 @@ protected function process(EmailMessage $message): array
133134 'Content-Type: application/json ' ,
134135 ];
135136
137+ if (! empty ($ attachments )) {
138+ return $ this ->sendIndividually ($ message , $ emails , $ headers , $ response );
139+ }
140+
141+ return $ this ->sendBatch ($ message , $ emails , $ headers , $ response );
142+ }
143+
144+ /**
145+ * @param array<array<string, mixed>> $emails
146+ * @param array<string> $headers
147+ * @return array{deliveredTo: int, type: string, results: array<array<string, mixed>>}
148+ */
149+ private function sendBatch (EmailMessage $ message , array $ emails , array $ headers , Response $ response ): array
150+ {
136151 $ result = $ this ->request (
137152 method: 'POST ' ,
138153 url: 'https://api.resend.com/emails/batch ' ,
139154 headers: $ headers ,
140- body: $ emails , // @phpstan-ignore-line
155+ body: $ emails ,
141156 );
142157
143158 $ statusCode = $ result ['statusCode ' ];
144159
145160 if ($ statusCode === 200 ) {
146161 $ responseData = $ result ['response ' ];
147162
148- if (isset ($ responseData ['errors ' ]) && ! empty ($ responseData ['errors ' ])) {
163+ if (\is_array ( $ responseData ) && isset ($ responseData ['errors ' ]) && ! empty ($ responseData ['errors ' ])) {
149164 $ failedIndices = [];
150165 foreach ($ responseData ['errors ' ] as $ error ) {
151166 $ failedIndices [$ error ['index ' ]] = $ error ['message ' ];
@@ -168,33 +183,80 @@ protected function process(EmailMessage $message): array
168183 }
169184 }
170185 } elseif ($ statusCode >= 400 && $ statusCode < 500 ) {
171- $ errorMessage = 'Unknown error ' ;
172-
173- if (\is_string ($ result ['response ' ])) {
174- $ errorMessage = $ result ['response ' ];
175- } elseif (isset ($ result ['response ' ]['message ' ])) {
176- $ errorMessage = $ result ['response ' ]['message ' ];
177- } elseif (isset ($ result ['response ' ]['error ' ])) {
178- $ errorMessage = $ result ['response ' ]['error ' ];
179- }
186+ $ errorMessage = $ this ->extractErrorMessage ($ result ['response ' ], 'Unknown error ' );
180187
181188 foreach ($ message ->getTo () as $ to ) {
182189 $ response ->addResult ($ to ['email ' ], $ errorMessage );
183190 }
184191 } elseif ($ statusCode >= 500 ) {
185- $ errorMessage = ' Server error ' ;
192+ $ errorMessage = $ this -> extractErrorMessage ( $ result [ ' response ' ], ' Server error ') ;
186193
187- if (\is_string ($ result ['response ' ])) {
188- $ errorMessage = $ result ['response ' ];
189- } elseif (isset ($ result ['response ' ]['message ' ])) {
190- $ errorMessage = $ result ['response ' ]['message ' ];
194+ foreach ($ message ->getTo () as $ to ) {
195+ $ response ->addResult ($ to ['email ' ], $ errorMessage );
191196 }
197+ }
192198
193- foreach ($ message ->getTo () as $ to ) {
199+ return $ response ->toArray ();
200+ }
201+
202+ /**
203+ * @param array<array<string, mixed>> $emails
204+ * @param array<string> $headers
205+ * @return array{deliveredTo: int, type: string, results: array<array<string, mixed>>}
206+ */
207+ private function sendIndividually (EmailMessage $ message , array $ emails , array $ headers , Response $ response ): array
208+ {
209+ $ recipients = $ message ->getTo ();
210+ $ deliveredTo = 0 ;
211+
212+ foreach ($ emails as $ index => $ email ) {
213+ $ to = $ recipients [$ index ];
214+
215+ $ result = $ this ->request (
216+ method: 'POST ' ,
217+ url: 'https://api.resend.com/emails ' ,
218+ headers: $ headers ,
219+ body: $ email ,
220+ );
221+
222+ $ statusCode = $ result ['statusCode ' ];
223+
224+ if ($ statusCode >= 200 && $ statusCode < 300 ) {
225+ $ response ->addResult ($ to ['email ' ]);
226+ $ deliveredTo ++;
227+ } elseif ($ statusCode >= 400 && $ statusCode < 500 ) {
228+ $ errorMessage = $ this ->extractErrorMessage ($ result ['response ' ], 'Unknown error ' );
229+ $ response ->addResult ($ to ['email ' ], $ errorMessage );
230+ } else {
231+ $ errorMessage = $ this ->extractErrorMessage ($ result ['response ' ], 'Server error ' );
194232 $ response ->addResult ($ to ['email ' ], $ errorMessage );
195233 }
196234 }
197235
236+ $ response ->setDeliveredTo ($ deliveredTo );
237+
198238 return $ response ->toArray ();
199239 }
240+
241+ /**
242+ * @param array<string, mixed>|string|null $body
243+ */
244+ private function extractErrorMessage (array |string |null $ body , string $ default ): string
245+ {
246+ if (\is_string ($ body )) {
247+ return $ body ;
248+ }
249+
250+ if (\is_array ($ body )) {
251+ if (isset ($ body ['message ' ]) && \is_string ($ body ['message ' ])) {
252+ return $ body ['message ' ];
253+ }
254+
255+ if (isset ($ body ['error ' ]) && \is_string ($ body ['error ' ])) {
256+ return $ body ['error ' ];
257+ }
258+ }
259+
260+ return $ default ;
261+ }
200262}
0 commit comments