mailauth

package
v0.13.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 20, 2026 License: MIT Imports: 17 Imported by: 0

Documentation

Overview

Package mailauth implements the e-mail based account features on top of internal/mail: the effective SMTP configuration (environment/config file, or the panel settings with an AEAD-sealed password), address verification codes, the e-mail second factor (panel login and the RustDesk client /api/login "email_check" step) and password reset links.

Codes are 6 random digits, stored as sha256 bound to user and purpose, valid 10 minutes, invalidated after 5 wrong guesses and by a newer code. Sending is limited by a resend cooldown and hourly caps per user and per client IP (counted in email_codes, so limits survive restarts).

Index

Constants

View Source
const (
	CodeTTL        = 10 * time.Minute
	ResetTTL       = 30 * time.Minute
	MaxAttempts    = 5
	ResendCooldown = time.Minute
	// MaxPerUserHour caps e-mails sent to one user (all purposes) per hour.
	MaxPerUserHour = 10
	// MaxPerIPHour caps e-mails triggered from one client IP per hour.
	MaxPerIPHour = 30
)

Tuning.

View Source
const (
	// SettingSMTP holds the panel-managed SMTP server (storedSMTP); ignored
	// while the configuration (RDPANEL_SMTP_HOST / smtp.host) defines one.
	SettingSMTP = "mail.smtp"
	// SettingDefaultLocale is the e-mail language for users without one.
	SettingDefaultLocale = "mail.default_locale"
	// SettingRequireEmail2FA (bool): users without TOTP but with a verified
	// address must enter an e-mailed code at sign-in.
	SettingRequireEmail2FA = "auth.require_email_2fa"
)

Settings keys (JSON values in the settings table).

View Source
const ResetPath = "/reset-password"

ResetPath is the SPA route of the reset link.

Variables

View Source
var (
	// ErrDisabled: no SMTP server is configured.
	ErrDisabled = errors.New("mailauth: e-mail is not configured")
	// ErrNoAddress: the user has no e-mail address.
	ErrNoAddress = errors.New("mailauth: user has no e-mail address")
	// ErrSend wraps delivery failures.
	ErrSend = errors.New("mailauth: could not send e-mail")
	// ErrInvalidToken: unknown, used or expired reset token.
	ErrInvalidToken = errors.New("mailauth: invalid or expired token")
)

Errors.

Functions

func MaskEmail

func MaskEmail(addr string) string

MaskEmail hides most of the local part for display on a code prompt: "alice@example.com" -> "a***e@example.com".

func ValidateInput

func ValidateInput(in *SMTPInput) map[string]string

ValidateInput normalises in and returns per-field errors.

Types

type Options

type Options struct {
	Store *store.Store
	AEAD  *crypto.AEAD
	// Config supplies smtp.* and admin_url (reset links).
	Config *config.Config
	Log    *slog.Logger
	// NewSender builds the Sender for a configuration (default mail.NewSMTP).
	NewSender func(config.SMTPConfig) rdmail.Sender
}

Options configure a Service.

type RateLimitError

type RateLimitError struct{ Wait time.Duration }

RateLimitError is returned when a send is refused by the cooldown or the hourly caps.

func (*RateLimitError) Error

func (e *RateLimitError) Error() string

func (*RateLimitError) RetryAfter

func (e *RateLimitError) RetryAfter() time.Duration

RetryAfter returns how long to wait before the next send.

type SMTPInput

type SMTPInput struct {
	Host     string
	Port     int
	Username string
	// Password: nil keeps the stored one, "" clears it.
	Password           *string
	From               string
	Encryption         string
	InsecureSkipVerify bool
}

SMTPInput is an update of the panel-managed SMTP configuration.

type SMTPView

type SMTPView struct {
	Source             Source
	Host               string
	Port               int
	Username           string
	PasswordSet        bool
	From               string
	Encryption         string
	InsecureSkipVerify bool
}

SMTPView is the SMTP configuration without the password (admin UI).

type Service

type Service struct {
	// contains filtered or unexported fields
}

Service implements the e-mail features. Safe for concurrent use.

func New

func New(o Options) *Service

New returns a Service.

func (*Service) CheckResetToken

func (s *Service) CheckResetToken(ctx context.Context, token string) (*store.User, error)

CheckResetToken returns the user a reset token belongs to (ErrInvalidToken when it is unknown, used or expired).

func (*Service) ConfirmVerification

func (s *Service) ConfirmVerification(ctx context.Context, u *store.User, code string) (bool, error)

ConfirmVerification marks the address verified when code matches and the address did not change since the code was sent.

func (*Service) DefaultLocale

func (s *Service) DefaultLocale(ctx context.Context) string

DefaultLocale returns the panel's e-mail language.

func (*Service) Email2FARequiredByPolicy

func (s *Service) Email2FARequiredByPolicy(ctx context.Context) (bool, error)

Email2FARequiredByPolicy reports the auth.require_email_2fa setting.

func (*Service) Enabled

func (s *Service) Enabled(ctx context.Context) bool

Enabled reports whether e-mail can be sent (an SMTP host is configured).

func (*Service) LoginFactorRequired

func (s *Service) LoginFactorRequired(ctx context.Context, u *store.User) (bool, error)

LoginFactorRequired reports whether u must enter an e-mailed code at sign-in. Callers check TOTP first (TOTP wins). The factor needs a verified address and a configured SMTP server: when e-mail is not configured it is not enforced (an administrator removed the server).

func (*Service) PasswordResetAvailable

func (s *Service) PasswordResetAvailable(ctx context.Context) bool

PasswordResetAvailable reports whether "Forgot password?" works: SMTP is configured and the panel URL (for the link) is known.

func (*Service) RequestPasswordReset

func (s *Service) RequestPasswordReset(ctx context.Context, login, ip string)

RequestPasswordReset e-mails a reset link to the account named by login (username, or e-mail address of up to 5 accounts) when it is active, has a password, may use password sign-in and has a verified address. The lookup and delivery run in the background so the caller's response does not depend on whether the account exists.

func (*Service) ResendLoginCode

func (s *Service) ResendLoginCode(ctx context.Context, u *store.User, ip string) error

ResendLoginCode e-mails a fresh sign-in code (subject to the cooldown).

func (*Service) ResetPassword

func (s *Service) ResetPassword(ctx context.Context, token, hash, algo string) (*store.User, int64, error)

ResetPassword consumes token, stores the new password hash and revokes every session and client token of the user. It returns the user and the number of revoked tokens.

func (*Service) SMTP

func (s *Service) SMTP(ctx context.Context) (config.SMTPConfig, Source, error)

SMTP returns the effective SMTP configuration and its source. The configuration file / environment wins over the panel settings.

func (*Service) SaveStored

func (s *Service) SaveStored(ctx context.Context, in SMTPInput, actor *int64) error

SaveStored stores the panel-managed SMTP configuration (an empty Host removes it). It refuses while the configuration file / environment defines the server.

func (*Service) SendLoginCode

func (s *Service) SendLoginCode(ctx context.Context, u *store.User, ip string) error

SendLoginCode e-mails a sign-in code. A code sent less than a minute ago that is still valid is reused (no new e-mail).

func (*Service) SendTest

func (s *Service) SendTest(ctx context.Context, addr, locale string) error

SendTest delivers the test message to addr (admin "Send test e-mail").

func (*Service) SendVerification

func (s *Service) SendVerification(ctx context.Context, u *store.User, ip string) error

SendVerification e-mails a verification code to the user's address.

func (*Service) VerifyLoginCode

func (s *Service) VerifyLoginCode(ctx context.Context, userID int64, code string) (bool, error)

VerifyLoginCode checks and consumes a sign-in code.

func (*Service) View

func (s *Service) View(ctx context.Context) (SMTPView, error)

View returns the effective configuration for display.

func (*Service) Wait

func (s *Service) Wait()

Wait blocks until background deliveries (password reset) finished (tests).

type Source

type Source string

Source tells where the effective SMTP configuration comes from.

const (
	SourceNone     Source = "none"
	SourceConfig   Source = "config"
	SourceSettings Source = "settings"
)

Sources.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL