Email workspaceUtility token received
Source: App\Mail\TokenRecievedMail (retain spelling), app/Mail/TokenRecievedMail.php; resources/views/emails/TokenRecieved.blade.php. Caller: WalletRepository::completePurchase, app/Http/Repository/WalletRepository.php:245.
Subject: {{network}} token received (unchanged).
Suggested preheader: {{network}} token receipt from {{business_name}}. The PIN is deliberately omitted from the new preheader.
Required portable values
| Token | Existing source / derivation | Handling |
|---|---|---|
| {{network}} | emailData.network = WalletService.network | Escaped display and native subject. |
| {{business_name}} | emailData.business_name = wallet.business_name | Escaped From display/body/Thanks sign-off identity. |
| {{token_amount}} | 'KES' . number_format(emailData.amount, 2) | Original fixed email currency, preserving zero/sign. Do not replace with wallet.currency silently. |
| {{token_pin}} | GetTokenValue('pin', response.resultParameters) | Keep complete string, spaces and leading zeros; never coerce to number, truncate or replace with a link. Treat real values as sensitive in consumers. |
| {{token_units}} | GetTokenValue('units', response.resultParameters) | Original string/display, including zero. |
| {{token_reference}} | GetTokenValue('transactionRef', response.resultParameters) | Original complete escaped provider reference, not service/ledger UUID. |
| {{preheader}} | Suggested network/business summary above | Escaped text; do not expose PIN in mailbox snippet. |
Default Built logo/optional {{logo_url}} and shared CID/HTTPS assets: [shared-footer](../shared-footer.md). No optional body section, legacy duplicate link, transactional action or PDF exists. Null/missing values require an explicit consuming-project decision, not invented tokens/units or a delivery guarantee.
Trigger and channel distinctions
completePurchase is the Kenya purchase-completion path. It resolves wallet, debits through WalletKE and records existing ledger/commit entries. Email is inside debit truthiness, sendToken && response, and isset(response.resultParameters). It extracts pin, transactionRef and units, sends a separate SMS, then sends Mail::to(wallet.email)->send(new TokenRecievedMail(emailData)). There is no new email validation/pin validity guard established there; preserve existing flow and handle any changes separately.
From is config(mail.from.address) with emailData.business_name; subject uses network; no Reply-To override. Preserve send(), source headers and underlying transport/outbox policy. API owns the body even though provider data supplies the token. No provider calls, wallet debits or real messages are made by this library.
The source SMS uses wallet.currency and includes a marketing signup link; the email hardcodes KES and does not include that link. Preserve and document the difference rather than copying an SMS action or changing currency through HTML. There are no extra token-use/meter instructions in the email source to invent.
Integration and safety
Use the existing Mailable with a complete HTML Blade view and proposed plain-text alternative. Portable {{placeholder_name}} tokens are not automatically Blade expressions. Escape all text/attributes; use one pass for replacements. Validate image HTTPS/CID destinations separately. Keep PIN/units/reference in both email formats. Never obtain real provider tokens or recipient records for previews, logs or screenshots.
Four fictional states cover received, leading zeros, supplied zero values and long contiguous tokens/references. Files: public/ready/utility-token.html/.txt and previews/utility-token-*.html/.txt. No separate project-owned plain-text source found. Browser checks do not establish actual token validity, payment/provider success, CID delivery, Gmail/Outlook/iOS Mail or current production delivery.