@snugdesk/email-widget
v0.3.3
Published
Self-contained email widget for Angular Apps - Powered by Snugdesk
Readme
Snugdesk - Email Widget for Angular
A production-ready Angular library that embeds a complete email client inside your web application. The widget handles authentication, mailbox discovery, conversation threading, rich-text composing, templates with placeholders, signatures, attachments, real-time updates, and light/dark theming out of the box — in one component tag.
To purchase licenses or to get implementation assistance, reach out to:
SNUG Technologies Pvt Ltd
📧 [email protected]
✅ Requirements
- Angular 21.0.0+ (matches the published peer dependency range)
@snugdesk/core0.2.39+- Angular Material 21.0.0+ and CKEditor 5 (
ckeditor543+,@ckeditor/ckeditor5-angular9+) - A licensed Snugdesk tenant with access to the Email channel, with at least one mailbox configured
📦 Installation
Install the core runtime first (all Snugdesk widgets depend on it), then add the email widget and its editor peers.
npm install @snugdesk/core
npm install @snugdesk/email-widget
npm install @angular/material @angular/cdk
npm install ckeditor5 @ckeditor/ckeditor5-angularOther runtime dependencies are bundled (moment-timezone, ngx-skeleton-loader, …).
🛠 Workspace Configuration (required)
The AWS SDK for JavaScript (v3) expects Node-style globals (global, process) to exist. Add the following once in your host application:
Create
src/custom-polyfills.ts// src/custom-polyfills.ts (window as any).global = window; (window as any).process = { env: { DEBUG: undefined } };Keep additional polyfills above if your app already uses this file.
Register the polyfill file in
angular.json{ "projects": { "your-app": { "architect": { "build": { "options": { "polyfills": [ "zone.js", "src/custom-polyfills.ts" ] } }, "test": { "options": { "polyfills": [ "zone.js", "zone.js/testing", "src/custom-polyfills.ts" ] } } } } } }Let TypeScript know about the polyfill file
Add the file to the
filesarray in bothtsconfig.app.jsonandtsconfig.spec.json:{ "files": [ "src/custom-polyfills.ts" ] }Raise the build budgets
The rich-text editor and cloud SDK make the initial bundle larger than the Angular defaults. In the
productionconfiguration ofangular.json:"budgets": [ { "type": "initial", "maximumWarning": "4MB", "maximumError": "8MB" } ]
These changes ensure the widget (and its client libraries) run reliably in both builds and tests.
⚙️ Angular Setup
Standalone-bootstrapped apps
The widget component is not an Angular standalone component — it is exported by EmailWidgetModule. In a standalone-bootstrapped app you make it available by importing the module into whichever component renders the widget (standalone components can import NgModules).
Provide animations and HttpClient at bootstrap (
main.ts)import { bootstrapApplication } from '@angular/platform-browser'; import { provideAnimations } from '@angular/platform-browser/animations'; import { provideHttpClient, withInterceptorsFromDi } from '@angular/common/http'; import { AppComponent } from './app/app.component'; bootstrapApplication(AppComponent, { providers: [ provideAnimations(), provideHttpClient(withInterceptorsFromDi()), ] });Import
EmailWidgetModulein the consuming standalone componentimport { Component } from '@angular/core'; import { EmailWidgetModule } from '@snugdesk/email-widget'; @Component({ selector: 'app-root', standalone: true, imports: [EmailWidgetModule], templateUrl: './app.component.html', }) export class AppComponent {}Without this import the
<snugdesk-email-widget>element will not be recognised.
NgModule-based apps
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { HttpClientModule } from '@angular/common/http';
import { EmailWidgetModule } from '@snugdesk/email-widget';
import { AppComponent } from './app.component';
@NgModule({
declarations: [AppComponent],
imports: [BrowserModule, HttpClientModule, EmailWidgetModule],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule {}🔐 Authentication Workflow
The widget takes a session token, establishes a session with SnugdeskAuthenticationService from @snugdesk/core, and then discovers the tenant, the signed-in user, the mailboxes, and the message templates on its own. token is the only credential you pass.
Step 1 — Create an integration credential (once, as a tenant administrator)
POST /tenants/{tenantId}/api-credentials
Authorization: Bearer <your Snugdesk session token>The response returns the credential exactly once. Store it in your backend's secret store — never in browser code, since anything the page can read, so can its visitors.
Step 2 — Issue a session token from your server, per agent session
POST /auth/library
Authorization: Bearer <keyId>.<secret>
{ "userId": "<agent user id>" }This returns a short-lived sessionToken.
Step 3 — Pass that token to the widget
import { Component } from '@angular/core';
@Component({
selector: 'my-component',
templateUrl: './my-component.html'
})
export class InboxShellComponent {
token = 'session-token-issued-by-your-backend';
}<snugdesk-email-widget [token]="token"></snugdesk-email-widget>Refresh the token from your backend before it expires, the same way you issued it.
Inputs
token(required) – Snugdesk session token fromPOST /auth/library. The widget callsauthenticate(...)with it and derives the tenant and user from the session.mode(optional) –'Standalone'or'Embedded'. Defaults to'Standalone'. See Widget Modes.theme(optional) –'light'or'dark'. Defaults to'light'.entityId(required inEmbeddedmode) – Scopes the inbox to a single contact or record, so only that entity's email threads are listed.entityEmail(optional) – In Embedded mode, pre-fills the To field when the agent composes a new email.tenantId,userId(deprecated) – Still accepted so existing markup keeps compiling, but ignored: both are read from the authenticated session. Safe to remove.
The widget shows a loading state until the session resolves, and an authentication message if it does not. Give its container a real height — the widget fills 100% of the space you allocate.
🧭 Widget Modes
The widget supports two modes: Standalone and Embedded. Use the mode input to choose how the UI behaves.
Standalone mode (default)
- A full-page, two-panel inbox: conversation list on the left, thread or composer on the right.
- Lists every email conversation for the session's tenant.
- Automatically switches to the drill-down layout on phones and narrow screens.
<snugdesk-email-widget [token]="token"></snugdesk-email-widget>Embedded mode
- A single-column, drill-down layout designed for a side panel next to a CRM record, ticket, or contact page.
- Requires
entityId; passentityEmailto pre-fill new emails to that contact.
<snugdesk-email-widget
[token]="token"
mode="Embedded"
theme="dark"
[entityId]="contact.id"
[entityEmail]="contact.email">
</snugdesk-email-widget>🎨 Assets & Styling
The library ships a single theme stylesheet that provides the Angular Material base theme, CKEditor 5 styles, the Open Sans font, Material Icons, the widget layout, and all colour variables. Import it once in your global stylesheet:
/* src/styles.css */
@import "@snugdesk/email-widget/src/lib/styles/email-widget-theme.css";
html, body {
margin: 0;
padding: 0;
height: 100%;
overflow: hidden;
}Brand colours
Override any of the widget's CSS variables in your own :root block after the import to match your product's brand:
:root {
--app-color: #ff6633; /* primary accent */
--app-color-dark: #ff5805; /* hover / active accent */
--app-color-light: #fe8c66;
--background-color: #ffffff;
--border-color: #c9c9c9;
--text-color: #666;
--text-color-dark: #333;
--text-font-family: "Open Sans", "Helvetica Neue", "Helvetica", "Arial", sans-serif;
}Dark mode
Dark mode ships with the theme — set theme="dark" on the component and the entire widget, including the composer and dialogs, repaints to a dark palette. Incoming emails are always rendered in their light styling so third-party marketing mail never renders half-darkened.
✨ Feature Highlights
Inbox
- Two-panel inbox with conversation list, threaded reader, and composer
- Real-time updates — new and updated conversations appear at the top of the list without a refresh
- Infinite-scroll history with skeleton loading states
- Instant search across subject, sender name, and email address — matches in the loaded list appear as you type, and the server is queried for older conversations that have not been loaded yet
- Advanced filters: sender (with address auto-suggestions), subject, and a date range — within the last day, 3 days, week, 2 weeks, month, or on a specific date
- Gmail-style sender avatars, relative timestamps, and message previews
- Contact-scoped mode that shows only one record's email history
Reading
- Full conversation threading, with the latest message expanded and older ones collapsed to a snippet
- Faithful, safely-sanitised rendering of HTML emails, including marketing mail and Office-pasted content
- Plain-text emails rendered with automatic link detection
- Attachment gallery with file-type icons, image thumbnails, and one-click download
- Built-in preview for images and PDFs, without leaving the widget
Composing
- Rich-text editor with bold, italic, underline, strikethrough, lists, indentation, font size, text and highlight colours, alignment, links, images, and tables
- Reply, Reply All, and Forward — inline at the bottom of the thread, with recipients, subject, and quoted history pre-filled
- Chip-based To / Cc / Bcc fields that accept comma, semicolon, Enter, or Tab
- Send-as mailbox picker when the tenant has more than one email address configured
- Per-mailbox signatures, inserted automatically and swapped when the sender changes
- Drag-in images, inline pasting, and image resizing inside the message body
- Email-safe HTML output, so messages render correctly in Outlook, Gmail, and Apple Mail
- Reliable resend: retrying a failed send delivers the same email rather than a duplicate
Templates
- Browse and search the tenant's approved message templates
{{placeholder}}fields filled inline, with defaults and a live preview before insertion- Subject and body applied together, without disturbing the signature
Attachments
- Up to 10 files and 25 MB per email
- Large attachments upload directly to secure cloud storage, so big files send as reliably as small ones
- Clear file size feedback and per-file removal before sending
Presentation
- Standalone and Embedded modes
- Light and dark themes, plus a configurable accent colour
- Fully responsive down to phone widths, with a drill-down list → thread flow
📜 Release Notes
0.2.6 – 0.2.8 — Aug 2026
- Revamped inbox UI across the conversation list, thread header, and composer.
- Advanced search. Search now reaches conversations that have not been loaded into the list yet, with filters for sender, subject, and date range, plus sender auto-suggestions.
- Token-only authentication. The widget derives the tenant and user from the session token; the
tenantIdanduserIdinputs are ignored. - Fixed a scrolling issue in the conversation list.
- Trimmed the published package contents.
0.2.5 — Aug 2026
- Angular 21 support across the widget and its Material and editor peers.
- Reliable resend — if a send fails on a flaky connection, pressing Send again delivers the same email instead of a second copy.
0.2.3 – 0.2.4 — May 2026
- Fully responsive UI. The inbox collapses to a drill-down list → thread flow on tablets and phones, with a Back to list action.
- Dark theme across the list, thread, composer, template picker, and attachment preview.
- Layout and spacing polish throughout the conversation list and thread header.
0.2.1 – 0.2.2 — May 2026
- Embedded mode. Scope the inbox to a single contact or record with
entityId, and pre-fill new emails withentityEmail— ideal for a CRM side panel. - Switching records resets the panel cleanly instead of carrying the previous thread over.
0.2.0 — Mar 2026
- Published as a standalone library, independent of the Snugdesk application.
- CKEditor 5 composer replacing the earlier editor: tables, image resizing, font colours, and paste-from-Office support.
- Large attachments — files beyond the inline limit upload directly to secure cloud storage, lifting the practical ceiling to 25 MB per email.
- Attachment preview dialog for images and PDFs.
0.1.0 – 0.1.3 — Mar 2026
- First public releases of the email client: conversation list, threaded reader, composer, reply/reply-all/forward, and real-time updates.
- Template enhancements — inline placeholder filling with defaults and a live preview.
- Fixed link rendering inside email bodies, plus assorted layout fixes.
🛠 Troubleshooting & Tips
- Nothing renders / the widget is invisible. The widget fills its container — make sure the parent element has an explicit height (the demo uses
height: 100%onhtml, body). <snugdesk-email-widget>is not a known element. ImportEmailWidgetModuleinto the component that renders it, not only intomain.ts.- "Authentication failed" instead of the inbox. The
tokenis missing, expired, or was issued for a different tenant — re-issue it from your backend viaPOST /auth/library. - Unstyled or icon-less UI. Confirm the theme stylesheet import in your global
styles.css— it carries the fonts, Material theme, and editor styles. - Build fails on bundle size. Raise the
initialbudget as shown in Workspace Configuration. - No sender address in the composer. At least one active mailbox must be configured for the tenant's Email channel in Snugdesk.
- Upgrade the widget in lockstep with your Angular major version to stay within the supported peer dependency range (
>=21.0.0).
📬 Support
Need help with deployment, theming, or backend setup?
SNUG Technologies Pvt Ltd
📧 [email protected]
Include your tenant name, Angular version, and a summary of the issue so the support team can assist quickly.
