Codex commited on
Commit
10e9ccd
·
1 Parent(s): 6b2fff3

Add Brevo API send as primary email path with SMTP fallback

Browse files
Files changed (1) hide show
  1. server.js +75 -14
server.js CHANGED
@@ -29,6 +29,7 @@ const SMTP_HOST = process.env.SMTP_HOST || 'smtp-relay.brevo.com';
29
  const SMTP_PORT = parseInt(process.env.SMTP_PORT || '587', 10);
30
  const SMTP_SECURE = process.env.SMTP_SECURE === 'true' || SMTP_PORT === 465;
31
  const SMTP_TIMEOUT = parseInt(process.env.SMTP_TIMEOUT_MS || '10000', 10);
 
32
  let emailTransport = null;
33
  let emailConfigChecked = false;
34
 
@@ -39,6 +40,46 @@ async function sendMailWithTimeout(transport, mailOptions, timeoutMs = SMTP_TIME
39
  ]);
40
  }
41
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
42
  function getEmailTransport() {
43
  if (emailTransport || emailConfigChecked) return emailTransport;
44
 
@@ -111,15 +152,43 @@ function buildAlertEmail(statusEntry) {
111
  return { subject, text, html };
112
  }
113
 
114
- async function sendAlertEmail(statusEntry) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
115
  const transport = getEmailTransport();
116
- if (!transport) return;
 
 
117
 
 
 
 
 
 
 
 
 
 
 
118
  const { subject, text, html } = buildAlertEmail(statusEntry);
119
  const emailFrom = process.env.EMAIL_FROM;
120
  const emailTo = process.env.EMAIL_TO;
121
 
122
- await sendMailWithTimeout(transport, {
123
  from: emailFrom,
124
  to: emailTo,
125
  subject,
@@ -226,22 +295,14 @@ function buildStatusReportEmail() {
226
  async function sendStatusReportEmail() {
227
  const emailFrom = process.env.EMAIL_FROM;
228
  const emailTo = process.env.EMAIL_TO;
229
- const smtpUser = process.env.SMTP_USER || emailFrom;
230
- const smtpPass = process.env.SMTP_PASS || process.env.BREVO_SMTP_PASS || process.env.BREVO_API_KEY;
231
 
232
- if (!emailFrom || !emailTo || !smtpUser || !smtpPass) {
233
- throw new Error('Brak konfiguracji e-mail: ustaw EMAIL_FROM, EMAIL_TO, SMTP_USER, SMTP_PASS (lub BREVO_SMTP_PASS / BREVO_API_KEY).');
234
- }
235
-
236
- const transport = getEmailTransport();
237
- if (!transport) {
238
- throw new Error('Transport e-mail nie jest dostępny.');
239
  }
240
 
241
  const { subject, text, html } = buildStatusReportEmail();
242
- console.log(`Sending status report email via ${SMTP_HOST}:${SMTP_PORT} secure=${SMTP_SECURE} as ${smtpUser} to ${emailTo}, timeout ${SMTP_TIMEOUT}ms`);
243
 
244
- await sendMailWithTimeout(transport, {
245
  from: emailFrom,
246
  to: emailTo,
247
  subject,
 
29
  const SMTP_PORT = parseInt(process.env.SMTP_PORT || '587', 10);
30
  const SMTP_SECURE = process.env.SMTP_SECURE === 'true' || SMTP_PORT === 465;
31
  const SMTP_TIMEOUT = parseInt(process.env.SMTP_TIMEOUT_MS || '10000', 10);
32
+ const BREVO_API_TIMEOUT = parseInt(process.env.BREVO_API_TIMEOUT_MS || '10000', 10);
33
  let emailTransport = null;
34
  let emailConfigChecked = false;
35
 
 
40
  ]);
41
  }
42
 
43
+ async function sendViaBrevoApi(message) {
44
+ const apiKey = process.env.BREVO_API_KEY;
45
+ if (!apiKey) {
46
+ throw new Error('Brak BREVO_API_KEY do wysyłki przez API.');
47
+ }
48
+
49
+ const recipients = (message.to || '')
50
+ .split(',')
51
+ .map(s => s.trim())
52
+ .filter(Boolean)
53
+ .map(email => ({ email }));
54
+
55
+ if (recipients.length === 0) {
56
+ throw new Error('Brak odbiorców e-mail (EMAIL_TO).');
57
+ }
58
+
59
+ const payload = {
60
+ sender: { email: message.from },
61
+ to: recipients,
62
+ subject: message.subject,
63
+ textContent: message.text,
64
+ htmlContent: message.html
65
+ };
66
+
67
+ await axios.post(
68
+ 'https://api.brevo.com/v3/smtp/email',
69
+ payload,
70
+ {
71
+ headers: {
72
+ 'api-key': apiKey,
73
+ accept: 'application/json',
74
+ 'content-type': 'application/json'
75
+ },
76
+ timeout: BREVO_API_TIMEOUT
77
+ }
78
+ );
79
+
80
+ console.log('Email sent via Brevo API');
81
+ }
82
+
83
  function getEmailTransport() {
84
  if (emailTransport || emailConfigChecked) return emailTransport;
85
 
 
152
  return { subject, text, html };
153
  }
154
 
155
+ async function sendEmail(message) {
156
+ const emailFrom = process.env.EMAIL_FROM;
157
+ const emailTo = process.env.EMAIL_TO;
158
+ if (!emailFrom || !emailTo) {
159
+ throw new Error('Brak EMAIL_FROM/EMAIL_TO do wysyłki e-mail.');
160
+ }
161
+
162
+ // Prefer Brevo API if key is available
163
+ if (process.env.BREVO_API_KEY) {
164
+ try {
165
+ await sendViaBrevoApi(message);
166
+ return;
167
+ } catch (err) {
168
+ console.error('Brevo API send failed, falling back to SMTP if available:', err && err.message ? err.message : err);
169
+ }
170
+ }
171
+
172
  const transport = getEmailTransport();
173
+ if (!transport) {
174
+ throw new Error('Brak transportu e-mail (SMTP/API).');
175
+ }
176
 
177
+ await sendMailWithTimeout(transport, {
178
+ from: message.from,
179
+ to: message.to,
180
+ subject: message.subject,
181
+ text: message.text,
182
+ html: message.html
183
+ });
184
+ }
185
+
186
+ async function sendAlertEmail(statusEntry) {
187
  const { subject, text, html } = buildAlertEmail(statusEntry);
188
  const emailFrom = process.env.EMAIL_FROM;
189
  const emailTo = process.env.EMAIL_TO;
190
 
191
+ await sendEmail({
192
  from: emailFrom,
193
  to: emailTo,
194
  subject,
 
295
  async function sendStatusReportEmail() {
296
  const emailFrom = process.env.EMAIL_FROM;
297
  const emailTo = process.env.EMAIL_TO;
 
 
298
 
299
+ if (!emailFrom || !emailTo) {
300
+ throw new Error('Brak konfiguracji e-mail: ustaw EMAIL_FROM i EMAIL_TO.');
 
 
 
 
 
301
  }
302
 
303
  const { subject, text, html } = buildStatusReportEmail();
 
304
 
305
+ await sendEmail({
306
  from: emailFrom,
307
  to: emailTo,
308
  subject,