Troubleshooting Ory Kratos Email Verification Failures
Diagnose and fix email verification failures in Ory Kratos. Learn how to troubleshoot SMTP misconfigurations, schema errors, and network blocks to ensure users receive registration emails.
24 Mar 2026, 20:29 UTC

The Symptom: Registration Success, No Email
A common failure point in Ory Kratos self-service flows is the "silent failure" of email verification. Users complete the registration form and receive a success response from the API, but the identity remains in the email_verification state because the verification email never arrives.
This typically indicates a disconnect between the Kratos identity management logic and the Courier—the internal component responsible for dispatching messages via SMTP or a third-party API.
Diagnostic Quick-Reference
| Observed Behavior | Likely Cause | Primary Check |
|---|---|---|
Kratos logs show auth failure or connection refused |
SMTP Misconfiguration | kratos.yml courier block |
| No logs regarding email dispatch during registration | Schema mismatch | Identity Schema JSON |
Logs show 429 Too Many Requests |
Provider Rate Limiting | Email Provider Console |
| Courier API returns error, but SMTP is correct | Network/Firewall Block | Port connectivity (25, 465, 587) |
Step-by-Step Diagnostic Flow
1. Inspect the Kratos Logs
Start by monitoring the Kratos pod or process logs during a registration attempt. Look for keywords such as courier, smtp, or failed to send email.
If you see authentication failed, the issue is almost certainly your SMTP credentials. If you see i/o timeout, Kratos cannot reach the mail server on the specified port.
2. Validate the Identity Schema
Kratos will not trigger a verification email if the identity schema does not explicitly support verifiable addresses. If the logs are completely silent regarding the courier during registration, check your schema.
Run the following command using the Ory CLI to inspect your current schema:
ory kratos identities schema
Ensure the traits section includes verifiable_addresses. A missing trait here means Kratos doesn't know where to store the verification status, so it skips the email trigger entirely.
3. Test the Courier API Directly
To isolate the issue from the registration flow, trigger a test email using the Kratos Admin API. This confirms if the Courier is functional regardless of the identity state.
Run this curl command from a machine with access to the Kratos Admin port (usually 4434):
curl -X POST http://localhost:4434/courier/test -d '{"email": "[contact removed]"}'
Risk: Ensure you use a test email address you control to avoid spamming users during diagnostics.
Fixes Based on Findings
Issue: SMTP Authentication or Connection Failure
Update your kratos.yml configuration. Ensure the courier block matches your provider's requirements. For most modern providers (like SendGrid or AWS SES), use STARTTLS on port 587.
courier:
smtp:
host: smtp.provider.com
port: 587
username: your_username
password: your_password
# Use 'starttls' for port 587 or 'tls' for port 465
tls:
enabled: true
skip_verify: false
Rollback: If the new configuration causes Kratos to fail to start, revert the kratos.yml to the previous known-working state and restart the service.
Issue: Missing Schema Traits
If the schema is missing the necessary traits, you must update the JSON schema file and redeploy Kratos. Add the verifiable_addresses property to the traits object. Note that existing identities may need to be migrated or manually updated if they were created before the schema change.
Issue: Network/Firewall Blocks
If the Courier API fails with a timeout but credentials are correct, verify that your container or VM is allowed to send outbound traffic on the SMTP port. Use nc or telnet to check connectivity:
nc -zv smtp.provider.com 587
Verification of Resolution
- Log Confirmation: Attempt a new registration; logs should now show
Successfully sent email. - State Check: Use the Ory CLI to check the identity status. The identity should remain in
email_verification, but theverifiable_addressestrait should now be populated with the target email. - End-to-End: Complete the verification by clicking the link in the received email and confirming the identity state transitions to
active.
Escalation Criteria
If the Courier API returns a 200 OK but no email is received and no errors appear in Kratos logs, the issue is external. Escalate to your email service provider to check for:
- IP address blacklisting.
- Strict SPF/DKIM/DMARC failures causing the provider to drop the mail before it hits the inbox.
- Account-level sending limits or "sandbox mode" restrictions.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.