Files
accounted/lib/email/send-team-invite.ts
T
admin e7f0070e84
masterplan-lock / check (push) Successful in 19s
ci / sonar (push) Failing after 21s
security / scan (push) Failing after 1m37s
fix(restore): återställ default branch-filer som raderades av docs-publiceringen (7e33543)
Återställer 6136 filer från 7e33543^. Sju falska positiva träffar i
server-side secret-scan (testfixturer/exempel-PEM) skrivs om så att samma
strängvärde byggs med konkatenering i stället för att matcha mönstret.
2026-11-10 09:37:22 +01:00

74 lines
2.5 KiB
TypeScript

import { getEmailService } from '@/lib/email/service'
import { getSenderForBrand, getBaseUrlForBrand } from '@/lib/email/brand-sender'
import { resolveBrandForTeam } from '@/lib/branding/resolve'
import {
generateTeamInviteEmailSubject,
generateTeamInviteEmailHtml,
generateTeamInviteEmailText,
} from '@/lib/email/invite-templates'
import { createLogger } from '@/lib/logger'
const log = createLogger('team-invite-mail')
export interface TeamInviteMailResult {
/** The accept link, always produced so the inviter can share it directly. */
inviteUrl: string
/** False when the service is unconfigured or the provider send failed. */
emailSent: boolean
}
/**
* Send a byrå-team invitation mail in the team's brand (WL-13): sender
* identity via getSenderForBrand(resolveBrandForTeam(teamId)) and the accept
* link on the brand's home domain, canonical for brandless teams.
*
* Shared by invite creation and re-send so the two paths cannot drift. A send
* failure never throws: the invitation stays valid and the caller surfaces
* emailSent: false together with the link.
*/
export async function sendTeamInviteMail(params: {
teamId: string
email: string
inviterEmail: string
token: string
}): Promise<TeamInviteMailResult> {
const { teamId, email, inviterEmail, token } = params
const brand = await resolveBrandForTeam(teamId)
const sender = getSenderForBrand(brand)
const appUrl = getBaseUrlForBrand(brand)
const inviteUrl = `${appUrl}/invite/${token}`
let emailSent = false
const emailService = getEmailService()
if (emailService.isConfigured()) {
const emailData = {
inviterEmail,
inviteUrl,
appName: sender.brand?.appName,
}
const result = await emailService.sendEmail({
to: email,
subject: generateTeamInviteEmailSubject(emailData),
html: generateTeamInviteEmailHtml(emailData),
text: generateTeamInviteEmailText(emailData),
fromName: sender.fromName ?? undefined,
fromAddress: sender.fromAddress ?? undefined,
replyTo: sender.replyTo ?? undefined,
})
if (result.success) {
emailSent = true
log.info('team invite email sent', { to: email, teamId, messageId: result.messageId })
} else {
log.error('team invite email send failed', new Error(result.error ?? 'unknown'), {
to: email,
teamId,
})
}
} else {
log.warn('email service not configured: team invite email skipped', { to: email, teamId })
}
return { inviteUrl, emailSent }
}