Logotipo Hedhog

Get Hedhog updates in your inbox

New releases, fresh recipes, and breaking changes — no spam.

Email

Hedhog sends transactional email through @hed-hog/core's MailService. Pick a provider once, and all system emails — password resets, invitations, OAuth sign-up confirmations, 2FA codes — use it automatically.

Status: ✅ Fully implemented — SMTP, Gmail, and Amazon SES all work, with an automatic self-test on save.

SMTP, Gmail, and Amazon SES providers feeding into MailService, with the automatic validation email flag

Quick Setup

  1. Create an Integration Profile (type Email, pick SMTP/Gmail/SES) at Settings → Integration Profiles
  2. Fill in the provider's config fields (tables below)
  3. Go to Settings → Configurations → General → Mail Configuration and set Mail Profile to it
  4. Check that Email Configured (configured-mail) flips to true — Hedhog emails itself automatically to confirm

How It Works

Like OAuth and storage, email credentials live in a generic Integration Profile (type email, provider smtp, gmail, or ses), not in flat settings. A single setting, mail-integration-profile-id, points at the active profile.

  1. Go to Settings → Integration ProfilesNew → Type Email, pick a provider, and fill in its config fields (table below)
  2. Go to Settings → Configurations → General, find the Mail Configuration section, and set Mail Profile to that profile
  3. The moment you save, Hedhog automatically sends a validation email to the configured "from" address and flips an internal configured-mail flag to true — if delivery fails, the flag stays false and the error is logged, so you'll know immediately if credentials are wrong
  4. From then on, every call to MailService.sendTemplatedMail() across the app uses this provider

Switching providers later is just selecting a different profile — no code or redeploy needed, and Hedhog re-sends the validation email automatically.

Common Config Fields (all providers)

These three fields exist in the config JSON of every email profile, regardless of provider, and control the From/Reply-To headers:

Config fieldDescription
from_emailSender address — also the address that receives the automatic validation email
from_nameOptional display name shown before the address ("Name" <[email protected]>)
reply_to_email / reply_to_nameOptional — set only if replies should go to a different address than from_email

SMTP

Works with any SMTP server: Postfix, Mailgun, SendGrid, Mailchimp Transactional, Brevo, etc.

Config fieldDescription
hostSMTP server hostname (e.g. smtp.mailgun.org)
portPort — typically 587 (STARTTLS) or 465 (SSL)
securetrue for port 465, false for 587
usernameSMTP login username
passwordSMTP login password

Gmail

Uses OAuth 2.0 with a refresh token — not a Gmail App Password. This requires creating a Google Cloud OAuth client and going through a one-time consent flow to obtain a refresh token, which is more setup than SMTP but doesn't depend on 2-Step Verification or app passwords being enabled on the account.

  1. In console.cloud.google.com, create an OAuth 2.0 Client ID of type Web application (or Desktop, if you'll generate the token with a local script) and enable the Gmail API
  2. Request the https://mail.google.com/ scope and complete the consent flow once (e.g. via Google's OAuth Playground, using your own client ID/secret under its settings gear icon) to obtain a refresh token — this is the part teams most often get stuck on, since it's a manual one-time step outside the Hedhog admin
  3. Enter the values below in the Integration Profile
Config fieldDescription
client_idOAuth client ID from Google Cloud Console
client_secretOAuth client secret
refresh_tokenLong-lived refresh token obtained via the consent flow above
from_emailThe Gmail address the refresh token was issued for

The refresh token does not expire from inactivity the way access tokens do, but it can be revoked if the Google account's security settings change (password reset, app removed from account access, etc.) — if mail suddenly stops sending, regenerating the refresh token is the first thing to check.


Amazon SES

Suitable for high-volume production email. Requires an AWS account with SES access — note this uses the SES API directly (access_key_id/secret_access_key), not SES's SMTP interface, so the credentials are IAM keys, not SMTP credentials.

  1. Verify your domain (or sender address) in SES → Verified identities
  2. Create an IAM user (or role) with the ses:SendEmail and ses:SendRawEmail permissions, and generate an access key pair for it
  3. Note your SES region (e.g. us-east-1) — it must match the region where the identity was verified
Config fieldDescription
regionAWS region where the identity is verified (e.g. us-east-1)
access_key_idIAM access key ID
secret_access_keyIAM secret access key
from_emailMust be a verified identity in that SES region

Sandbox mode: new SES accounts can only send to addresses/domains that are also verified. Request production access in the SES console before going live, or every test send to a real user's inbox will fail silently from their perspective (bounced or rejected).


Verify It Worked

  • After saving the profile, confirm Email Configured (configured-mail) is true in Settings → Configurations → General
  • Trigger a real flow that sends mail — a password reset is the easiest — and confirm the message actually arrives, not just the automatic validation email Hedhog already sent itself

Troubleshooting

SymptomLikely cause
configured-mail setting stays false after saving the profileCredentials are wrong, or the SES/Gmail account isn't verified — check the API logs for the validation email's error
No mail profile configured errorsmail-integration-profile-id isn't set, or points at a deleted profile
Integration profile X is not an email profileThe selected profile's type isn't email (picked the wrong entity in the picker)
Gmail sends stop working out of nowhereRefresh token was revoked — regenerate it through the consent flow
SES test emails never arriveAccount is still in sandbox mode and the recipient isn't a verified identity