plusforta/heykaution-mail

Shared mail layout components and Laravel mail theme for heykaution applications

Maintainers

Package info

gitlab.com/plusforta/public/heykaution-mail

Issues

pkg:composer/plusforta/heykaution-mail

Transparency log

Statistics

Installs: 6

Dependents: 0

Suggesters: 0

Stars: 0

1.0.5 2026-07-29 09:27 UTC

This package is auto-updated.

Last update: 2026-07-30 12:20:31 UTC


README

Shared mail layout components and Laravel mail theme for heykaution.de and heykaution-dmz.

Notification content stays in each application — this package only provides branding, layout building blocks, and helpers.

Installation

composer require plusforta/heykaution-mail:^1.0

The package is published on Packagist, so no VCS repository entry is needed.

HeykautionMailServiceProvider is auto-discovered by Laravel and registers:

  • anonymous Blade components (<x-mail-*>)
  • the heykaution mail markdown theme (<x-mail::*>)
  • translations for component strings (notifications.mail_closing, …), merged into each app's lang/*/notifications.php group
  • the formatIban() helper
  • configurable footer/legal/social URLs via config/heykaution-mail.php

Configuration

Publish is optional — defaults work in heykaution.de (named routes + settings.links.social_media).

Apps without HK routes (e.g. DMZ) should set config/heykaution-mail.php:

return [
    'app_url' => config('services.hk.app_url'),

    'footer' => [
        'social' => [
            'facebook' => 'https://www.facebook.com/...',
            'instagram' => 'https://www.instagram.com/...',
            'linkedin' => 'https://linkedin.com/...',
        ],
    ],
];

Helpers used by the mail theme:

HelperPurpose
heykaution_mail_app_url()Public HK URL (heykaution-mail.app_urlservices.hk.app_urlapp.url)
heykaution_mail_asset($path)Local asset or absolute HK URL
heykaution_mail_legal_url('terms'\|'privacy'\|'imprint')Config URL, named route, or {app_url}/{locale}/agb fallback
heykaution_mail_social_url('facebook'\|'linkedin'\|'instagram')Config or legacy settings.links.social_media.*

Custom components

These components are registered globally as <x-mail-*>.

<x-mail-highlight-box>

Green highlight box for emphasized content (e.g. changed account data, lock periods).

PropTypeDefaultDescription
alignstring'left'Text alignment inside the box (left, center, right, …)

Slot: Markdown content (rendered via Illuminate\Mail\Markdown::parse, same as <x-mail::panel>).

<x-mail-highlight-box>
Old IBAN: {{ formatIban($oldIban) }}<br />
New IBAN: {{ formatIban($newIban) }}
</x-mail-highlight-box>

<x-mail-highlight-box align="left">
Left-aligned content
</x-mail-highlight-box>

<x-mail-device-info>

Displays device and connection details for a security-relevant change. Accepts both a DTO object (heykaution.de) and an array (heykaution-dmz).

PropTypeDefaultDescription
securityInformationobject\|arrayRequired. Device information (see structure below)

Expected fields in securityInformation:

FieldTypeDescription
ipAddressstringConnection IP address
devicestringDevice name (e.g. smartphone)
browserstringBrowser family
osstringOperating system
timestampCarbonInterface\|string\|nullTime of the change; falls back to when empty
{{-- HK: SecurityInformation DTO --}}
<x-mail-device-info :security-information="$securityInformation" />

{{-- DMZ: array from sync queue --}}
<x-mail-device-info :security-information="[
    'ipAddress' => '203.0.113.1',
    'device' => 'desktop',
    'browser' => 'Chrome',
    'os' => 'macOS',
    'timestamp' => '2026-06-09T10:30:00+02:00',
]" />

Translation key: notifications.device_info.text

<x-mail-closing>

Standard signature with greeting and team line (config('app.name')).

PropTypeDescription
No props

Slot: None.

<x-mail-closing />

Translation keys: notifications.mail_closing.greeting, notifications.mail_closing.team

<x-mail-button-link-hint>

Fallback hint below a button when the button does not work in the mail client.

PropTypeDefaultDescription
urlstringRequired. Target URL rendered as a clickable link
<x-mail::button :url="$url">Confirm email address</x-mail::button>

<x-mail-button-link-hint :url="$url" />

Translation key: notifications.mail_button_link_hint

<x-mail-border>

Visual separator (blue line) between mail sections. Typically placed before the button link hint.

PropTypeDescription
No props

Slot: None.

<x-mail-closing />

<x-mail-border />

<x-mail-button-link-hint :url="$url" />

<x-mail-table-row>

Table row with a label column and a value column. Use inside a <table>.

PropTypeDefaultDescription
labelstringRequired. Left column label
lastRowboolfalseWhen true, no bottom border is rendered

Slot: Right column cell content (HTML allowed).

<table width="100%" cellpadding="0" cellspacing="0">
    <x-mail-table-row label="IBAN">
        {{ formatIban($iban) }}
    </x-mail-table-row>
    <x-mail-table-row label="Amount" :last-row="true">
        {{ $amount }}
    </x-mail-table-row>
</table>

Mail theme components (<x-mail::*>)

This package overrides Laravel's default mail theme. Use these components in markdown notification templates.

<x-mail::message>

Wrapper for a complete mail. Renders layout, header, footer, and markdown body.

PropTypeDescription
No custom props

Slot: Markdown content of the mail.

<x-mail::layout>

HTML shell (used internally by <x-mail::message>, rarely used directly).

PropTypeDefaultDescription
withClosingbooltrueControls optional closing behavior in the layout

<x-mail::button>

Primary call-to-action button (heykaution blue).

PropTypeDefaultDescription
urlstringRequired. Target URL
trackingDisabledboolfalseSets data-pm-no-track on the link (Postmark)

Slot: Button label.

<x-mail::button :url="$url">Confirm now</x-mail::button>

<x-mail::button :url="$url" :tracking-disabled="true">Without tracking</x-mail::button>

<x-mail::panel>, <x-mail::table>, <x-mail::header>, <x-mail::footer>, <x-mail::subcopy>

Standard Laravel mail components with heykaution styling. No additional props — slot content only.

<x-mail::panel>
Important notice with **markdown**.
</x-mail::panel>

Helper

formatIban(string $iban): string

Formats an IBAN with a space every 4 characters.

formatIban('DE89370400440532013000');
// → "DE89 3704 0044 0532 0130 00"

Usable directly in Blade templates:

{{ formatIban($iban) }}

Translations

The package loads the following keys under the notifications namespace (de/en):

KeyUsage
notifications.mail_closing.greetingSignature greeting
notifications.mail_closing.teamTeam line (:app_name)
notifications.mail_button_link_hintButton fallback text (:url)
notifications.device_info.textDevice info (:date, :time, :device, :ip)

App-specific lang/*/notifications.php files can add more keys; Laravel merges the namespaces.

Example: notification template

Blade file in the app, e.g. resources/views/notifications/en/email/example.blade.php:

{{-- @formatter:off --}}
<x-mail::message>
**Hello {{ $notifiable->first_name }},**

Your IBAN was changed successfully.

<x-mail-highlight-box>
Old IBAN: {{ formatIban($oldIban) }}<br />
New IBAN: {{ formatIban($newIban) }}<br />
<br />
Payouts locked until: {{ $unlockAt }}
</x-mail-highlight-box>

If you did not make this change, you can revert it immediately:

<x-mail::button :url="$cancelUrl">
Revert change
</x-mail::button>

**Change details:**
<x-mail-device-info :security-information="$securityInformation" />

<x-mail-closing />

<x-mail-border />

<x-mail-button-link-hint :url="$cancelUrl" />

</x-mail::message>

Matching notification class (simplified):

public function toMail(mixed $notifiable): MailMessage
{
    return (new MailMessage())
        ->subject('Your IBAN was changed')
        ->markdown('notifications.en.email.example', [
            'notifiable' => $notifiable,
            'oldIban' => 'DE89370400440532013000',
            'newIban' => 'DE89370400440532013100',
            'unlockAt' => '14.06.2026 10:30',
            'cancelUrl' => 'https://heykaution.de/en/settings/security-lock/cancel/abc123',
            'securityInformation' => [
                'ipAddress' => '203.0.113.1',
                'device' => 'desktop',
                'browser' => 'Firefox',
                'os' => 'Windows',
                'timestamp' => now()->toIso8601String(),
            ],
        ]);
}

Local development

For parallel work on the package and consuming apps:

{
  "repositories": [
    {
      "type": "path",
      "url": "../heykaution-mail",
      "options": { "symlink": true }
    }
  ]
}

Changes in the package are then immediately visible in HK/DMZ.

Repository

https://gitlab.com/plusforta/public/heykaution-mail