Compare commits

...

2 Commits

Author SHA1 Message Date
grandwizard28
b251aa60bf feat: revamp invite email 2026-02-13 18:07:37 +05:30
grandwizard28
b166b20069 feat: revamp invite email 2026-02-13 18:06:40 +05:30
8 changed files with 159 additions and 21 deletions

View File

@@ -14,5 +14,8 @@
},
"[sql]": {
"editor.defaultFormatter": "adpyke.vscode-sql-formatter"
},
"[html]": {
"editor.defaultFormatter": "vscode.html-language-features"
}
}

View File

@@ -193,6 +193,15 @@ emailing:
templates:
# The directory containing the email templates. This directory should contain a list of files defined at pkg/types/emailtypes/template.go.
directory: /opt/signoz/conf/templates/email
format:
header:
enabled: false
logo_url: ""
help:
enabled: false
email: ""
footer:
enabled: false
smtp:
# The SMTP server address.
address: localhost:25

View File

@@ -10,6 +10,27 @@ type Config struct {
type Templates struct {
Directory string `mapstructure:"directory"`
Format Format `mapstructure:"format"`
}
type Format struct {
Header Header `mapstructure:"header" json:"header"`
Help Help `mapstructure:"help" json:"help"`
Footer Footer `mapstructure:"footer" json:"footer"`
}
type Header struct {
Enabled bool `mapstructure:"enabled" json:"enabled"`
LogoURL string `mapstructure:"logo_url" json:"logo_url"`
}
type Help struct {
Enabled bool `mapstructure:"enabled" json:"enabled"`
Email string `mapstructure:"email" json:"email"`
}
type Footer struct {
Enabled bool `mapstructure:"enabled" json:"enabled"`
}
type SMTP struct {
@@ -45,6 +66,19 @@ func newConfig() factory.Config {
Enabled: false,
Templates: Templates{
Directory: "/root/templates",
Format: Format{
Header: Header{
Enabled: false,
LogoURL: "",
},
Help: Help{
Enabled: false,
Email: "",
},
Footer: Footer{
Enabled: false,
},
},
},
SMTP: SMTP{
Address: "localhost:25",

View File

@@ -15,6 +15,7 @@ type provider struct {
settings factory.ScopedProviderSettings
store emailtypes.TemplateStore
client *client.Client
config emailing.Config
}
func NewFactory() factory.ProviderFactory[emailing.Emailing, emailing.Config] {
@@ -55,7 +56,7 @@ func New(ctx context.Context, providerSettings factory.ProviderSettings, config
return nil, err
}
return &provider{settings: settings, store: store, client: client}, nil
return &provider{settings: settings, store: store, client: client, config: config}, nil
}
func (provider *provider) SendHTML(ctx context.Context, to string, subject string, templateName emailtypes.TemplateName, data map[string]any) error {
@@ -69,6 +70,9 @@ func (provider *provider) SendHTML(ctx context.Context, to string, subject strin
return err
}
data["format"] = provider.config.Templates.Format
data["to"] = to
content, err := emailtypes.NewContent(template, data)
if err != nil {
return err

View File

@@ -146,11 +146,9 @@ func (m *Module) CreateBulkInvite(ctx context.Context, orgID valuer.UUID, userID
continue
}
if err := m.emailing.SendHTML(ctx, invites[i].Email.String(), "You are invited to join a team in SigNoz", emailtypes.TemplateNameInvitationEmail, map[string]any{
"CustomerName": invites[i].Name,
"InviterName": creator.DisplayName,
"InviterEmail": creator.Email,
"Link": fmt.Sprintf("%s/signup?token=%s", bulkInvites.Invites[i].FrontendBaseUrl, invites[i].Token),
if err := m.emailing.SendHTML(ctx, invites[i].Email.String(), "You're Invited to Join SigNoz", emailtypes.TemplateNameInvitationEmail, map[string]any{
"inviter_email": creator.Email,
"link": fmt.Sprintf("%s/signup?token=%s", bulkInvites.Invites[i].FrontendBaseUrl, invites[i].Token),
}); err != nil {
m.settings.Logger().ErrorContext(ctx, "failed to send email", "error", err)
}

View File

@@ -16,7 +16,7 @@ var (
)
var (
TemplateNameInvitationEmail = TemplateName{valuer.NewString("invitation_email")}
TemplateNameInvitationEmail = TemplateName{valuer.NewString("invite")}
TemplateNameUpdateRole = TemplateName{valuer.NewString("update_role")}
TemplateNameResetPassword = TemplateName{valuer.NewString("reset_password_email")}
)

View File

@@ -1,14 +0,0 @@
<!DOCTYPE html>
<html>
<body>
<p>Hi {{.CustomerName}},</p>
<p>You have been invited to join SigNoz project by {{.InviterName}} ({{.InviterEmail}}).</p>
<p>Please click on the following button to accept the invitation:</p>
<a href="{{.Link}}" style="background-color: #000000; color: white; padding: 14px 20px; text-align: center; text-decoration: none; display: inline-block;">Accept Invitation</a>
<p>Button not working? Paste the following link into your browser:</p>
<p>{{.Link}}</p>
<p>Follow docs here 👉 to <a href="https://signoz.io/docs/cloud/">Get Started with SigNoz Cloud</a></p>
<p>Thanks,</p>
<p>SigNoz Team</p>
</body>
</html>

View File

@@ -0,0 +1,104 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>You're Invited to Join SigNoz</title>
</head>
<body
style="margin: 0; padding: 0; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif; line-height: 1.6; color: #333333; background-color: #ffffff;">
<table role="presentation" width="100%" cellspacing="0" cellpadding="0" border="0" style="background-color: #ffffff;">
<tr>
<td align="center" style="padding: 0;">
<table role="presentation" width="600" cellspacing="0" cellpadding="0" border="0"
style="background-color: #ffffff; max-width: 600px; width: 100%;">
{{ if .format.header.enabled }}
<tr>
<td align="center" style="padding: 40px 20px 24px 20px;">
<img src="{{.format.header.logo_url}}" alt="SigNoz" width="160" height="40"
style="display: block; border: 0; outline: none; max-width: 100%; height: auto;">
</td>
</tr>
{{ end }}
<tr>
<td style="padding: 24px 20px 32px 20px;">
<p style="margin: 0 0 24px 0; font-size: 16px; color: #1a1a1a;">Hi there,</p>
<p style="margin: 0 0 24px 0; font-size: 16px; color: #333333; line-height: 1.6;">
You've been invited by <strong>{{.inviter_email}}</strong> to join their SigNoz organization.
</p>
<p style="margin: 0 0 16px 0; font-size: 16px; color: #333333; line-height: 1.6;">
A new account has been created for you with the following details:
</p>
<table role="presentation" width="100%" cellspacing="0" cellpadding="0" border="0"
style="margin: 0 0 24px 0;">
<tr>
<td
style="padding: 20px; background-color: #f5f5f5; border-radius: 6px; border-left: 4px solid #4E74F8;">
<p style="margin: 0; font-size: 15px; color: #333333; line-height: 1.6;">
<strong>Email:</strong> {{.to}}
</p>
</td>
</tr>
</table>
<p style="margin: 0 0 24px 0; font-size: 16px; color: #333333; line-height: 1.6;">
Accept the invitation to get started.
</p>
<table role="presentation" width="100%" cellspacing="0" cellpadding="0" border="0"
style="margin: 0 0 16px 0;">
<tr>
<td align="center">
<table role="presentation" cellspacing="0" cellpadding="0" border="0">
<tr>
<td style="border-radius: 4px; background-color: #4E74F8;">
<a href="{{.link}}" target="_blank"
style="display: inline-block; padding: 16px 48px; font-size: 16px; font-weight: 600; color: #ffffff; text-decoration: none; border-radius: 4px;">Accept
Invitation</a>
</td>
</tr>
</table>
</td>
</tr>
</table>
<p style="margin: 0 0 4px 0; font-size: 13px; color: #666666; text-align: center;">Button not working?
Copy and paste this link into your browser:</p>
<p
style="margin: 0 0 32px 0; font-size: 13px; color: #4E74F8; word-break: break-all; text-align: center;">
<a href="{{.link}}" style="color: #4E74F8; text-decoration: none;">{{.link}}</a>
</p>
{{ if .format.help.enabled }}
<p style="margin: 0 0 32px 0; font-size: 16px; color: #333333; line-height: 1.6;">
Need help? Chat with our team in the SigNoz application or email us at <a
href="mailto:{{.format.help.email}}"
style="color: #4E74F8; text-decoration: none;">{{.format.help.email}}</a>.
</p>
{{ end }}
<p style="margin: 0; font-size: 16px; color: #333333; line-height: 1.6;">
Thanks,<br>
<strong>The SigNoz Team</strong>
</p>
</td>
</tr>
{{ if .format.footer.enabled }}
<tr>
<td align="center" style="padding: 32px 20px 40px 20px;">
<p style="margin: 0 0 8px 0; font-size: 12px; color: #999999; line-height: 1.5;">
<a href="https://signoz.io/terms-of-service/" style="color: #4E74F8; text-decoration: none;">Terms of
Service</a> -
<a href="https://signoz.io/privacy/" style="color: #4E74F8; text-decoration: none;">Privacy Policy</a>
</p>
<p style="margin: 0; font-size: 12px; color: #999999; line-height: 1.5;">
©2026 SigNoz Inc.
</p>
</td>
</tr>
{{ end }}
</table>
</td>
</tr>
</table>
</body>
</html>