Billionmail/BillionMail · error

password not found for %s

Error message

password not found for %s

What it means

PasswordPlainByEmail found no mailbox row (or an empty password_encode) for the requested username, so val.IsEmpty() triggers 'password not found for %s'. This means the sender address has no corresponding local mailbox with stored credentials.

Source

Thrown at core/internal/service/mail_service/sending.go:160

		return
	}

	if !es.IsConfigured() {
		err = errors.New("Email Sender not configured")
		return
	}

	return
}

// PasswordPlainByEmail
func PasswordPlainByEmail(ctx context.Context, email string) (string, error) {
	val, err := g.DB().Model("mailbox").Where("username", email).Value("password_encode")
	if err != nil {
		return "", fmt.Errorf("query password failed: %w", err)
	}
	if val.IsEmpty() {
		return "", fmt.Errorf("password not found for %s", email)
	}
	rawHex, err := hex.DecodeString(val.String())
	if err != nil {
		return "", fmt.Errorf("hex decode failed: %w", err)
	}
	plainBytes, err := base64.StdEncoding.DecodeString(string(rawHex))
	if err != nil {
		return "", fmt.Errorf("base64 decode failed: %w", err)
	}
	return string(plainBytes), nil
}

// Close closes the SMTP connection
func (e *EmailSender) Close() {
	_ = e.Disconnect()
}

// Connect establishes an SMTP connection

View on GitHub (pinned to fc36c76c05)

Solutions

  1. Confirm the sender address exists: SELECT username FROM mailbox WHERE username='<email>'.
  2. Create the mailbox or set its password if the row is missing/empty.
  3. Fix the From address in your send call to a configured mailbox.
  4. Check password_encode is populated (hex-encoded value), not NULL after provisioning.

Example fix

// before
from := "noreply@mydomain.com"
// after
from := "noreply@mydomain.com" // must exist in mailbox table
// create it if absent:
// INSERT INTO mailbox (username, password_encode, ...) VALUES ('noreply@mydomain.com', <encoded>, ...)
Defensive patterns

Strategy: validation

Validate before calling

n, err := g.DB().Model("mailbox").Where("username", fromAddress).Count()
if err != nil || n == 0 {
    return fmt.Errorf("sender %s has no mailbox; create it or choose a configured sender", fromAddress)
}

Try / catch

sender, err := NewEmailSenderWithLocal(ctx, fromAddress)
if err != nil {
    if strings.Contains(err.Error(), "password not found for") {
        return fmt.Errorf("no mailbox for %s — provision it or use an existing sender", fromAddress)
    }
    return err
}

Prevention

When it happens

Trigger: NewEmailSenderWithLocal is given an email address that doesn't exist in the mailbox table, or the row's password_encode is NULL/empty — e.g. sending from an alias or an externally-hosted address with no local account.

Common situations: Typo in the From address; mailbox deleted but still referenced as sender; mailbox created without a password; using an address managed by an external provider.

Related errors


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