Billionmail/BillionMail · warning

unable to determine domain for noreply email

Error message

unable to determine domain for noreply email

What it means

RetrieveMountpointByUser resolves the mountpoint for a username by looking up the OS user and deriving the mountpoint from the prefix of HomeDir before '/home/'. It throws 'specified user not valid' when the user exists but their home directory does not contain '/home/', meaning the function cannot infer a mountpoint. This is a BillionMail-specific convention, not a standard Unix constraint.

Source

Thrown at core/internal/controller/campaign/campaign_v1_form.go:111

// sendConfirmationEmail sends a confirmation email to the newly subscribed user
func sendConfirmationEmail(ctx context.Context, email, name string) error {
	// Get the base domain to construct noreply email
	baseURL := domains.GetBaseURL()
	if baseURL == "" {
		return fmt.Errorf("base URL not configured")
	}

	// Extract domain from base URL
	domain := ""
	if u, err := url.Parse(baseURL); err == nil && u.Hostname() != "" {
		domain = u.Hostname()
	} else {
		// Fallback: try to get from environment
		if hostname, err := public.DockerEnv("BILLIONMAIL_HOSTNAME"); err == nil && hostname != "" {
			domain = hostname
		} else {
			return fmt.Errorf("unable to determine domain for noreply email")
		}
	}

	// Construct noreply email address
	noreplyEmail := fmt.Sprintf("noreply@%s", domain)

	// Create email sender
	sender, err := mail_service.NewEmailSenderWithLocal(noreplyEmail)
	if err != nil {
		return fmt.Errorf("failed to create email sender: %w", err)
	}
	defer sender.Close()

	// Create confirmation email content
	subject := "Welcome! Your subscription has been confirmed"
	content := fmt.Sprintf(`
<!DOCTYPE html>
<html>

View on GitHub (pinned to fc36c76c05)

Solutions

  1. Pass a regular user whose home directory lives under /home/ (e.g. 'www')
  2. If the user must be supported, create it with usermod -d /home/<name> <name>
  3. Adjust RetrieveMountpointByUser to handle home dirs outside /home/ if your environment requires it
  4. Handle the returned error explicitly and fall back to a default mountpoint ('/')

Example fix

// before
mp, err := public.RetrieveMountpointByUser("root") // HomeDir=/root -> error
// after
mp, err := public.RetrieveMountpointByUser("www") // HomeDir=/home/www -> ok
Defensive patterns

Strategy: validation

Validate before calling

if u, err := user.Lookup(username); err == nil && !strings.Contains(u.HomeDir, "/home/") {
	return fmt.Errorf("user %s has home %q outside /home; pick a regular user", username, u.HomeDir)
}

Try / catch

mp, err := public.RetrieveMountpointByUser(username)
if err != nil {
	if strings.Contains(err.Error(), "specified user not valid") {
		mp = "/" // fall back to root mountpoint or reject the request
	}
	return err
}

Prevention

When it happens

Trigger: Calling RetrieveMountpointByUser with a user whose HomeDir is not under /home (e.g. root with /root, service users with /var/lib/... or /nonexistent, nologin system users).

Common situations: Running the code in minimal/containerized environments where users are system accounts with unusual home dirs; passing 'root'; LDAP/NIS users whose home paths differ.

Related errors


AI-assisted analysis of Billionmail/BillionMail@fc36c76c05 (2026-09-05). Data as JSON: /api/errors/728e3fa434e27d9c. Report an issue: GitHub.