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 connectionView on GitHub (pinned to fc36c76c05)
Solutions
- Confirm the sender address exists: SELECT username FROM mailbox WHERE username='<email>'.
- Create the mailbox or set its password if the row is missing/empty.
- Fix the From address in your send call to a configured mailbox.
- 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
- Only allow From addresses that exist in the mailbox table (dropdown instead of free text).
- Provision the mailbox and its password before using the address as a sender.
- Audit for deleted mailboxes still referenced in campaign settings.
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
- query password failed: %w
- Generate password md5-crypt failed: %w
- Email Sender not configured
- password length must be at least 4 characters
- SMTP server is required
AI-assisted analysis of Billionmail/BillionMail@fc36c76c05 (2026-09-05).
Data as JSON: /api/errors/b15f05fbadbde423.
Report an issue: GitHub.