# 7. Email Notifications

## 7.1 Module and exports

`lib/sendEmail.js` uses **nodemailer** and exports two functions:

- **`sendNascoEmail(data, pdfAttachmentPath, mailConfig, clientName)`** — sends a report email with the generated PDF attached. Used by `generateNascoPDF`, `generateFullPdf`, and `generateSanuxPDF` in `index.js` (i.e. shared across the wellbeing, extended-wellbeing, and SanusX flows, despite the "Nasco" name).
- **`sendEmailNotification(data)`** — a generic notification email, no PDF pipeline attached. Wired to `index.js`'s exported `sendEmail(json)`.

## 7.2 SMTP transport configuration — entirely caller-supplied

There are **no environment variables and no hardcoded SMTP credentials** anywhere in this module. The transport is built directly from a `mailConfig` object that the caller constructs and passes in:

```js
// index.js — constructed identically in generateNascoPDF, generateFullPdf, generateSanuxPDF
let mailConfig = {
    host: reportData.host,
    port: reportData.port,
    authUser: reportData.authUser,
    authPass: reportData.authPass,
    sendFromEmail: reportData.sendFromEmail,
    secure: reportData.secure
}
```

```js
// lib/sendEmail.js
var transporter = nodemailer.createTransport({
    host: mailConfig.host,
    port: mailConfig.port,
    secure: false,          // NOTE: hardcoded, see below
    pool: true,
    requireTLS: true,
    maxConnections: 20,
    maxMessages: 1,
    auth: { user: mailConfig.authUser, pass: mailConfig.authPass }
});
```

**Known bug:** `mailConfig.secure` is collected from the caller in all three call sites but **never actually read** by `sendMail` — the transporter hardcodes `secure: false` and instead forces a STARTTLS upgrade via `requireTLS: true`. So the connection isn't unencrypted (an unsupportable-TLS server will fail closed), but a caller who explicitly sets `secure: true` expecting implicit TLS (port-465 style) gets no such thing — the flag is dead code. If you ever need genuinely implicit-TLS support, this is where to add it.

`maxMessages: 1` combined with `pool: true` means a new SMTP connection/handshake is opened per message despite pooling being enabled — a minor inefficiency, not a security issue.

`sendEmailNotification` builds its own, differently-shaped `mailConfig` inline from the same style of caller-supplied fields.

## 7.3 Email content

- **Attachment:** yes — the generated PDF, attached by **file path** (nodemailer reads it from disk, not from an in-memory buffer): `attachments: [{ path: pdfAttach, filename: data.name + " WellbeingReport.pdf", contentType: "application/pdf" }]`. In the `generateFullPdf` flow, this path is a per-call, UUID-suffixed temp file that gets unlinked after send (see [doc 1.7](01-architecture-overview.md#17-filetemp-file-handling--an-evolving-pattern-worth-knowing)); in the older `generateNascoPDF`/`generateSanuxPDF` flows it's a fixed shared filename under `output/`.
- **Subject/body (`sendNascoEmail`):** subject is a fixed, localized string (`localeService.t('wellbeingReport')`); the body is a hardcoded, i18n-translated multi-paragraph template — genuinely translated, but not caller-customizable beyond the patient's name.
- **Subject/body (`sendEmailNotification`):** fully caller-driven — `data.emailSubject`, plus `customHeaderHTML`/`customBodyHTML`/`customFooterHTML` override fields.
- **Branding:** `sendNascoEmail` pulls `logo`, `signature`, and a color from `config/{clientName}.json` (falling back to `config/default.json`) — using the client string **as-is, with no case-normalization and no `pha`→`Pha` mapping** (a third, different resolution rule from the ones in [doc 2.2](02-configuration-and-whitelabelling.md#22-how-clientclientname-resolves-to-a-config-file--and-why-its-inconsistent) — the caller must pass the exact on-disk filename casing here).
- **RTL:** email HTML uses a `lang === "ar"` check to flip `float`/`text-align`/`direction` in its hand-built inline styles — a simpler mechanism than the report templates', and using a different placeholder syntax: single-brace `{token}` (e.g. `{logo}`, `{header_text}`), not the `{{double-brace}}` convention used in the PDF templates. Don't apply PDF-template assumptions when editing email strings.

## 7.4 Security considerations

- **SMTP credentials travel in plaintext inside the request payload.** `authUser`/`authPass` are plain JSON fields on the same object that's only base64-*encoded* (not encrypted) end to end — see [doc 1.3](01-architecture-overview.md#13-entry-points-indexjs). Anyone who can observe the call to this library (or a log of it) can trivially recover the SMTP password. If `isDebugging` logging is ever extended to dump the full `reportData`/`mailConfig` object, credentials would land in `output/LOGS-*.txt` in plaintext.
- **No enforcement of the caller's `secure` intent** — see 7.2. This is a config-drift risk more than an active vulnerability (the connection still requires TLS via `requireTLS`), but it means the `secure` field is misleading and should either be honored or removed from the API surface.
- **No hardcoded credentials found** in this module. The only hardcoded value is the fallback sender address `noreply@medicus.ai`, which is not a secret.
- **Recommendation for anyone hardening this:** if the host application controls both ends, consider moving SMTP credentials to a per-deployment secret/environment variable inside the *host* app rather than passing them through this library's payload on every call — this library has no mechanism for that today, so it would be a host-application-level change, not a change to this package's public API shape necessarily, but worth raising with whoever owns the calling system.
