Skip to content

Troubleshooting

Start in the console. Every mail carries its current state, every send attempt with the provider’s exact response, and the full SMTP transcript of the ingest conversation. Usually the answer is on the mail’s page; this guide maps what you see there to a cause and a fix.

Find your symptom below (the literal error codes are in the headings, so Ctrl-F for the one you’re staring at). Every entry names the Cause. and the Fix.

AUTH is rejected with 535 Authentication failed

Section titled “AUTH is rejected with 535 Authentication failed”

Cause. Mailway answers 535 5.7.8 Authentication failed: the username and password don’t match an active SMTP credential. Usually one of these: a typo or a truncated paste, a credential that was revoked, the username of one credential with the password of another, or an API key (mw_live_…) pasted where the password belongs. 535 is permanent: your mailer won’t retry it.

Fix. Open the project’s page in the console, go to its Access section, and check that the credential is still listed. Reveal its password there and paste the username (mw_user_…) and password (mw_pass_…) again. If the credential was revoked, create a new one with New SMTP credential.

A mail is refused with 530 (credential revoked)

Section titled “A mail is refused with 530 (credential revoked)”

Cause. The SMTP credential was revoked while your app’s connection was still open. Within a minute of the revoke, Mailway refuses the next mail on that connection with 530 5.7.0 This SMTP credential was revoked. Mail that Mailway received with it in the 5 minutes after the revoke is still sent. Mail received later (possible only if Mailway couldn’t check the credential in time) is kept as Rejected and not sent (mail.failed, reason smtp_credential_revoked). 530 is permanent: a mail server (Postfix, Exim) returns the mail to its sender instead of retrying, and an app library (nodemailer, PHPMailer, Symfony Mailer) reports an error.

Fix. Create a new credential with New SMTP credential in the project’s Access section, switch your app to it, and resend what was refused.

Cause. You tried to authenticate on a plaintext connection. Mailway never accepts credentials in the clear, and answers 538 5.7.11 Encryption required for requested authentication mechanism; send STARTTLS first.

Fix. Negotiate TLS before AUTH — use STARTTLS on a submission port (587, 25, 2525, 2587, 588) or connect with implicit TLS on 465 or 2465. Most libraries do this automatically once you set the right port and enable TLS. See the ports table.

Cause. Your platform is blocking outbound SMTP, not Mailway rejecting you — this is extremely common. GCP blocks outbound port 25 to external destinations. DigitalOcean blocks 25, 465, and 587 by default. AWS blocks 25 by default.

Fix. Try another port — Mailway listens on seven for this exact reason (587 → 2525 → 2587 → 588, or 465 → 2465). Same host, same credentials. Whatever your network lets out, one gets through.

Cause. smtp.mailway.net has an IPv6 address as well as an IPv4 one, and a system with IPv6 usually tries it first. Some hosts block a port over IPv6 even when it works over IPv4. On a DigitalOcean Droplet, 587 can answer over IPv4 and hang over IPv6. Gmail’s SMTP server hangs there too, so the block is the host’s, not Mailway’s. To check, run telnet -4 smtp.mailway.net 587: it shows 220 mailway.net ESMTP Mailway ready, while telnet smtp.mailway.net 587 stops at Trying 2a01:…. Depending on the client, the send fails with a timeout, or reaches IPv4 only after the IPv6 attempt times out.

Fix. Use an alternate port: 2525, 2587, or 588 for STARTTLS, or 2465 for implicit TLS. On a DigitalOcean Droplet they answer over IPv6 too. Or make your client connect over IPv4.

Cause. A temporary throttle, not a bad credential — Mailway’s auth backend was rate-limited or unavailable for a moment. The text is 454 4.7.0 Too many authentication attempts, please retry in a moment or 454 4.7.0 Authentication service temporarily unavailable, please retry in a moment.

Fix. Retry with backoff. Your credential is fine; don’t rotate it. A persistent 454 on every attempt is worth a support request.

Cause. Mailway refused the connection, not your mail. 421 is temporary, and the text says why:

  • 421 4.7.0 Too many SMTP sessions for this team at once, please retry in a moment, in reply to AUTH: your team already has 128 SMTP sessions open at once, counted across all its credentials and projects (16 on the sandbox, smtp.mailway.dev).
  • 421 4.7.0 Too many connections from your host, please retry in a moment: one sending host (one IPv4 address, or one IPv6 /64) has 128 connections open at once (16 on the sandbox).
  • 421 4.7.0 Too many new connections from your host, please retry in a moment: one sending host opened more than 3,000 connections in a minute (120 on the sandbox).
  • 421 4.7.0 Too many connected clients, please retry in a moment: the relay as a whole, or the port you use, is at its connection limit. The alternate ports (25, 588, 2465, 2525, 2587) take 8 connections each; if your network allows it, use 587 or 465.
  • 421 4.7.1 Too many failed authentication attempts from your host, please retry later: 10 authentication attempts from your host failed within 10 minutes. Each failure stops counting 10 minutes after it happened, and a successful authentication clears them all. Check the credential first (see 535), or the retries keep the host locked out.
  • 421 4.7.1 Your IP address is on a blocklist; …: your sending address is on one of the public lists of abusive addresses that Mailway checks. If that’s wrong, write to hello@mailway.net.

Fix. Retry with backoff. A mail server queues the message and retries on its own; an app library such as nodemailer, PHPMailer, or Symfony Mailer reports an error instead, so the retry has to come from your app (see the 451 fix). If you open a new connection per message, reuse one connection for several messages instead.

Cause. A temporary refusal on Mailway’s side, after your app sent the message. The text says which: 451 4.3.0 Too much mail in flight, please retry (the relay is already receiving as much mail at once as it allows, or your team’s uploads in progress already take a quarter of that), or 451 4.3.0 Temporary local error, nothing was stored, please retry (Mailway couldn’t store the message), or 451 4.3.0 Temporary local error, please retry at any other step, when something failed inside Mailway. Either way, Mailway did not receive the message, so nothing was stored and nothing will be sent.

Fix. Retry with backoff. Who retries depends on what sends the mail. A mail server (Postfix, Exim) keeps the message in its queue and retries on its own, and the message goes through on a later attempt. An app library such as nodemailer, PHPMailer, or Symfony Mailer doesn’t: it reports an error to your code, and the mail is lost unless your app tries again. Send from a job queue that retries with a delay, for example a queued Laravel mailable with $tries above 1 and a $backoff.

A sender or recipient is refused with 501 or 550

Section titled “A sender or recipient is refused with 501 or 550”

Cause. Mailway checks the envelope addresses (MAIL FROM and RCPT TO) before your app sends the message, and refuses an address it can’t relay:

  • 550 5.1.7 Null sender …: the envelope sender is empty (MAIL FROM:<>), which is how bounces and auto-replies are usually sent. Mailway hands each mail to your provider from the MAIL FROM address, so a mail without one can’t go out.
  • 501 5.1.7 Bad sender address syntax or 501 5.1.3 Bad recipient address syntax: the address isn’t valid. Examples: an unquoted comma, bracket, or colon before the @ (a,b@example.com), a domain that starts or ends with a hyphen, or an emoji anywhere in the address.

Fix. Set MAIL FROM to an address on a domain your provider has verified, and correct any malformed address. A refused recipient doesn’t stop the mail: Mailway can still receive it for the recipients that got a 250. What happens next depends on your app’s mailer. Some send to the other recipients and report the refused one; others, Symfony Mailer and Laravel among them, stop and send nothing.

A mail is stuck in accepted and never reaches delivered

Section titled “A mail is stuck in accepted and never reaches delivered”

Cause. Usually not a problem. accepted means a provider took the handoff; delivered means the recipient’s server confirmed receipt, reported back through delivery events. Only providers that emit those events can ever show delivered — every supported provider except Gmail / Google Workspace and generic SMTP servers, once its delivery events are wired up. Those two stop at accepted by design, and that is not a failure.

Fix. If you want real delivered/bounced signal, use a provider that reports it and wire up its delivery events (SES: configuration set → SNS; the others: a webhook pointed at Mailway). The provider’s Delivery tracking button in the console walks you through it. See the Amazon SES, Brevo, Mailgun, Mailjet, MailerSend, Mailtrap, Mandrill, Nuntly, Postmark, Resend, SendGrid and SMTP2GO guides. Otherwise, read accepted as “the provider has it.”

Cause. The mail was stopped for good before delivery. The console labels the failed state Rejected, and the mail’s page says who stopped it:

  • A recipient is on the project’s suppression list — auto-added from an earlier permanent bounce or complaint, or added manually. The send is blocked before it goes out.
  • A provider permanently refused a single-recipient send — a hard bounce (bad mailbox, blocked sender) stops the retry chain instead of retrying an address that can’t receive.
  • A person or a rule rejected it — for example, a held mail someone chose Reject on.

Fix. Open the mail and read what stopped it. If it’s a suppression you disagree with, un-suppress the address. If it’s a hard bounce, the recipient address is the problem. If the rejection was a mistake, Retry sends it again (Pro and up).

Cause. Every provider in the project’s chain refused the mail, so Mailway stopped trying. This is almost always about the provider accounts, not the recipient: a rotated or revoked API key (535 from the provider), credits or a quota used up, or a billing problem on every attached account at once. A project with only one provider has no chain to fall back on.

Fix. Open the mail and read each send attempt: it shows which provider answered and its exact response. Repair the account at that provider (and update its credentials under Providers if you created a new key), then choose Retry on the mail (Pro and up): retrying starts the chain again. To stop one broken account taking every mail down, attach a second provider to the project. Failover is included on Pro and up.

Cause. The mail is held for review: a rule paused it, the project is paused, or it was sent with "paused": true over the HTTP API. Nothing is sent until someone releases it.

Fix. Open the mail and choose Release to send it, or Reject to stop it for good. If the whole project is paused, resume the project from its page first. Resuming doesn’t send what the pause held: release those mails one by one, or all at once with Release held mails on the project’s page.

Cause. A provider delivery event came back negative. Hard (bounced) is permanent — the address is invalid or blocking you, and every address the bounce report names is added to the project’s suppressions. Soft (soft_bounced) is transient — a full mailbox, greylisting, a momentary defer — and the provider keeps retrying.

Fix. Hard bounces mean fix or drop the address. Soft bounces usually resolve themselves; a persistent one is a receiver-side issue. Filter your list with state:bounced to review them in bulk.

Cause. Authentication passing is necessary, not sufficient — alignment, reputation, and content still decide placement.

Fix. Follow the deliverability guide. The most common BYOK cause is DMARC not aligned to your domain; a Mail Tester score points at the rest.

Cause. You’ve hit a plan quota at SMTP time.

  • 550 (permanent) — a monthly cap is spent for this billing period: the message quota (Free plan only; every other plan soft-overages past it) or the data-volume limit (any plan, once its grace margin is used). A 550 can also mean the team is a person’s second Free team: only one Free team per person can send real mail (Limits & quotas). An admin or someone with the Finance role can choose a paid plan for it under Billing in the console. The text starts 550 5.7.0 Monthly email limit reached for this plan., 550 5.7.0 Monthly data volume limit reached for this plan. or 550 5.7.0 This is a second Free team: ….
  • 452 (transient) — the Free plan’s daily send limit. It resets at 00:00 UTC; retry after that. The text starts 452 4.7.0 Daily send limit reached for this plan.

A 550 whose text starts 5.1.7 Null sender isn’t a quota: see A sender or recipient is refused. A 452 4.3.1 Insufficient system storage, please retry later isn’t a quota either: Mailway’s SMTP relay is short of disk space and refuses new mail at MAIL FROM until it has room. It is temporary; retry with backoff.

Fix. Check usage against your plan quotas. The permanent 550 needs a plan change or the month to roll over; the daily 452 just needs to wait for the reset. (On the HTTP API the equivalents are 402 and 429 — see Errors.)

Cause. Mailway answers 552 5.3.4 Message size exceeds the 25 MB limit: the message exceeds the 25 MB SMTP size limit, the same overall ceiling the HTTP API enforces. (The API is stricter inside it: html and text are capped at 2 MB each, a single attachment at 10 MB; see Limits.)

Fix. Shrink it — host large attachments and link them, or split the send. The HTTP API’s attachment caps are listed under Limits.

Cause. Mailway read the whole message and won’t relay it as it is. The text says why:

  • 554 5.6.0 Message has no From header field; add one: the message names no author. Mailway can’t pick one for you, and many providers and inboxes refuse such a mail.
  • 554 5.6.0 Message contains a NUL byte, which email does not allow; encode binary data as base64.
  • 554 5.6.0 Message header contains a bare carriage return; end every header line with CRLF.
  • 554 5.6.0 Message header has a line starting with a dot; start every header line with a field name: in SMTP, a line that is only a dot ends the message. Header lines start with a field name such as Subject:, so Mailway refuses a mail whose header has a line that starts with a dot instead of relaying it.

Nothing was stored, and 554 is permanent: a mail server returns the mail to its sender, and an app library reports an error.

Fix. Add a From: header field naming the author, send binary attachments base64-encoded (mail libraries do this by default), end every header line with CRLF, and start every header line with a field name. If your app builds the message itself, check that an empty line separates the header from the body: without one, a body line that starts with a dot counts as a header line. Then send the mail again.

Recipients over 50, or Amazon SES returns 554 … exceeds 50

Section titled “Recipients over 50, or Amazon SES returns 554 … exceeds 50”

Cause. SES caps a message at 50 recipients, counting the union of the SMTP envelope and the To/Cc/Bcc header addresses, evaluated after DATA — which is why splitting the envelope alone doesn’t fix it. Mailway handles this for you: above the cap it collapses the visible recipient headers and fans the send out BCC-style across sub-cap chunks. A raw 554 reaching your app means it came from somewhere Mailway’s fan-out didn’t cover.

Fix. You shouldn’t normally see it on relayed SMTP mail. On the HTTP API, requests over 50 recipients are rejected up front with 422 — batch them instead. Full behavior, the live-SES probes, and what changes for your recipients: 554 Recipient count exceeds 50.

A delivered mail doesn’t match what I sent

Section titled “A delivered mail doesn’t match what I sent”

Cause. Most often, the provider changed its copy. For example, Amazon SES replaces Message-ID and Date, Postmark composes a new message, and Brevo converts plain text to HTML and adds a tracking pixel. Each provider’s changes are listed in What providers change. The other cause is on Mailway’s side: the message was re-encoded instead of relayed byte-for-byte. That only happens when SMTP mail goes out through a provider account that can’t relay it (one limited to a structured-only API — every provider’s API except Amazon SES’s and Mailgun’s — because it’s set to Send via: API only or holds only an API key) and an admin has explicitly enabled re-encoding for that project–provider pair. It’s off by default; without it, relayed mail skips such an account.

Fix. Check the mail’s fidelity — relayed (Mailway relayed your app’s message byte-for-byte, apart from the automatic exceptions), constructed (born on the API/console), or re-encoded. Filter with fidelity:re-encoded to find mail Mailway rebuilt. For those, set the account’s Send via back to Auto (it then relays over the provider’s SMTP), use a raw-capable provider (SES, Mailgun), or leave re-encoding disabled (SMTP mail through API providers). For relayed mail, compare the delivered copy with the archived one. The archived copy already has the changes Mailway makes on receipt (a missing Message-ID or Date added, a Bcc field removed, line endings sent as CRLF; see SMTP relay), and above a provider’s recipient limit Mailway also replaces the visible recipient headers. Any other difference is the provider’s: check its settings (tracking, especially).

Cause. Your endpoint isn’t accepting the delivery, or the endpoint was auto-disabled after repeated failures.

Fix. Work through these in order:

  • Your endpoint must respond 2xx quickly. Non-2xx (or a redirect — Mailway does not follow them) counts as a failure.
  • Mailway retries a failed delivery on a backoff ladder and auto-disables an endpoint after 24 hours of continuous failure. Re-enable it in the console once it’s healthy.
  • Verify you’re checking the HMAC signature correctly — a signature mismatch is often a raw-body/parsing bug on your side. The verification snippet is on the Webhooks page.
  • Delivery is at-least-once — dedupe on (type, data.mail.uid) so a retry can’t double-process. A “missing” event is sometimes one your handler acknowledged with 200 and then discarded.

The search box on the mails list turns these symptoms into filters. The operators:

Operator Example Finds
state: state:failed Mail in a lifecycle state (aliases: held, sent, rejected, soft, undeliverable, capture)
to: / from: to:user@example.com An exact address or a fragment
provider: provider:amazon-ses Mail routed through a provider (its family, or one account’s pv.… id)
fidelity: fidelity:re-encoded relayed / constructed / re-encoded
dkim: dkim:fail Sender-DKIM verdict on the stored message (pass / fail / none / error / unsupported)
rescued: rescued:yes Mail a failover saved (a later provider succeeded)
after: / before: after:2026-07-01 A date window (after:D before:D+1 = one day)
last: last:24h A rolling window (s/m/h/d/w)
size: size>5mb The only operator that takes comparators
subject: / category: subject:invoice Subject substring / exact send category

They combine: state:failed after:2026-07-01, state:soft_bounced provider:amazon-ses, rescued:yes last:7d.

A mail sits in the highest state it has reached. Highest-priority first:

State Meaning
complained Recipient marked it as spam (delivery event)
bounced Permanent hard bounce (delivery event)
delivered Recipient’s server confirmed receipt (delivery event)
soft_bounced Transient defer; the provider is retrying
accepted A provider took the handoff — no delivery event yet
failed Stopped for good before delivery (a person, a rule, the suppression list, or a single-recipient hard bounce) — shown as “Rejected”
exhausted Every delivery attempt failed (retries used up) — shown as “Exhausted”
captured Sandbox capture (*.mailway.dev), never forwarded
paused Held (project paused, over daily cap, or awaiting release)
pending Mailway has the mail and is sending it to a provider

If several things fail at once, check status.mailway.net first: it shows whether Mailway’s SMTP relay, HTTP API, and console are up right now.

If you’re stuck, email hello@mailway.net or use the contact form. A support request moves fastest with:

  • the mail ID (m.01k8w9…) — it threads the whole timeline together,
  • which send attempt failed and the provider response it shows, and
  • the SMTP transcript from the mail detail page, if it’s an ingest issue.