Billionmail/BillionMail · warning

failed to create email sender: %w

Error message

failed to create email sender: %w

What it means

After deriving the mountpoint from the user's home directory, RetrieveMountpointByUser verifies it exists with FileExists and throws 'mountpoint not exists' when the directory is missing on disk. The inferred prefix path (or '/' if empty) is not a real mounted directory.

Source

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

	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>
<head>
    <meta charset="utf-8">
    <title>Subscription Confirmed</title>
    <style>
        body { font-family: Arial, sans-serif; line-height: 1.6; color: #333; }
        .container { max-width: 600px; margin: 0 auto; padding: 20px; }
        .header { background-color: #20a53a; color: white; padding: 20px; text-align: center; }
        .content { padding: 20px; background-color: #f9f9f9; }
        .footer { text-align: center; padding: 20px; color: #666; font-size: 12px; }
    </style>

View on GitHub (pinned to fc36c76c05)

Solutions

  1. Mount the storage volume that should contain the mountpoint before calling the function
  2. Verify the path exists: ls the mountpoint and correct the user's home directory if it points at a stale path (usermod -d)
  3. Add an existence check for the mountpoint in calling code and wait/retry until the volume is mounted
  4. Recreate the missing directory if it was deleted and re-mount data

Example fix

// before
mp, _ := public.RetrieveMountpointByUser("www") // uses stale /mnt/old
// after
if _, err := os.Stat("/mnt/data"); err != nil {
	return fmt.Errorf("mount volume /mnt/data first: %w", err)
}
mp, err := public.RetrieveMountpointByUser("www")
Defensive patterns

Strategy: validation

Validate before calling

if mp, err := public.RetrieveMountpointByUser(username); err == nil {
	if _, serr := os.Stat(mp); serr != nil {
		return fmt.Errorf("mountpoint %s missing: mount the volume first", mp)
	}
}

Try / catch

mp, err := public.RetrieveMountpointByUser(username)
if err != nil {
	if strings.Contains(err.Error(), "mountpoint not exists") {
		// wait for/retry volume mount, then retry once
	}
	return err
}

Prevention

When it happens

Trigger: The path before '/home/' in the user's HomeDir (e.g. '/mnt/data' in '/mnt/data/home/user') does not exist on the filesystem at call time — unmounted volume, typo in home dir config, or removed directory.

Common situations: Data volume not yet mounted when the service starts (common in container orchestration), stale /etc/passwd entries after storage was detached, or home directories pointing at removed paths.

Related errors


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