add support for sending emails to peers without linked user accounts if their user-identifier is a valid email address

This commit is contained in:
Christoph Haas
2025-10-12 14:31:01 +02:00
parent c7724b620a
commit 298c9405f6
3 changed files with 52 additions and 20 deletions

View File

@@ -5,6 +5,7 @@ import (
"fmt"
"io"
"log/slog"
"net/mail"
"github.com/h44z/wg-portal/internal/config"
"github.com/h44z/wg-portal/internal/domain"
@@ -101,29 +102,15 @@ func (m Manager) SendPeerEmail(ctx context.Context, linkOnly bool, style string,
}
if peer.UserIdentifier == "" {
slog.Debug("skipping peer email",
"peer", peerId,
"reason", "no user linked")
continue
return fmt.Errorf("peer %s has no user linked, no email is sent", peerId)
}
user, err := m.users.GetUser(ctx, peer.UserIdentifier)
if err != nil {
slog.Debug("skipping peer email",
"peer", peerId,
"reason", "unable to fetch user",
"error", err)
continue
email, user := m.resolveEmail(ctx, peer)
if email == "" {
return fmt.Errorf("peer %s has no valid email address, no email is sent", peerId)
}
if user.Email == "" {
slog.Debug("skipping peer email",
"peer", peerId,
"reason", "user has no mail address")
continue
}
err = m.sendPeerEmail(ctx, linkOnly, style, user, peer)
err = m.sendPeerEmail(ctx, linkOnly, style, &user, peer)
if err != nil {
return fmt.Errorf("failed to send peer email for %s: %w", peerId, err)
}
@@ -194,3 +181,37 @@ func (m Manager) sendPeerEmail(
return nil
}
func (m Manager) resolveEmail(ctx context.Context, peer *domain.Peer) (string, domain.User) {
user, err := m.users.GetUser(ctx, peer.UserIdentifier)
if err != nil {
if m.cfg.Mail.AllowPeerEmail {
_, err := mail.ParseAddress(string(peer.UserIdentifier)) // test if the user identifier is a valid email address
if err == nil {
slog.Debug("peer email: using user-identifier as email",
"peer", peer.Identifier, "email", peer.UserIdentifier)
return string(peer.UserIdentifier), domain.User{}
} else {
slog.Debug("peer email: skipping peer email",
"peer", peer.Identifier,
"reason", "peer has no user linked and user-identifier is not a valid email address")
return "", domain.User{}
}
} else {
slog.Debug("peer email: skipping peer email",
"peer", peer.Identifier,
"reason", "user has no user linked")
return "", domain.User{}
}
}
if user.Email == "" {
slog.Debug("peer email: skipping peer email",
"peer", peer.Identifier,
"reason", "user has no mail address")
return "", domain.User{}
}
slog.Debug("peer email: using user email", "peer", peer.Identifier, "email", user.Email)
return user.Email, *user
}

View File

@@ -41,4 +41,6 @@ type MailConfig struct {
From string `yaml:"from"`
// LinkOnly specifies whether emails should only contain a link to WireGuard Portal or attach the full configuration
LinkOnly bool `yaml:"link_only"`
// AllowPeerEmail specifies whether emails should be sent to peers which have no valid user account linked, but an email address is set as "user".
AllowPeerEmail bool `yaml:"allow_peer_email"`
}