sj26/mailcatcher · error
Error receiving message
Error message
Error receiving message
What it means
The SMTP server's receive_message (smtp.rb:57-67) finished the DATA phase and tried to store the message via MailCatcher::Mail.add_message and prune old messages; something in that path raised, the rescue caught it, logged this report with the half-built @current_message as context, and returned false — which makes the EventMachine SMTP server report a delivery error to the sending client. The message is lost from MailCatcher's UI, but the process stays up.
Source
Thrown at lib/mail_catcher/smtp.rb:63
end
def receive_data_chunk(lines)
current_message[:source] ||= +""
lines.each do |line|
current_message[:source] << line << "\r\n"
end
true
end
def receive_message
MailCatcher::Mail.add_message current_message
MailCatcher::Mail.delete_older_messages!
puts "==> SMTP: Received message from '#{current_message[:sender]}' (#{current_message[:source].length} bytes)"
true
rescue => exception
MailCatcher.log_exception("Error receiving message", @current_message, exception)
false
ensure
@current_message = nil
end
end
View on GitHub (pinned to 18a9cb7a79)
Solutions
- Run `mailcatcher --foreground --verbose` and send one failing message; read the `Exception:` line of the printed block to identify the real error.
- If it is sqlite3-related (null byte / argument errors), pin a compatible sqlite3 (`gem install sqlite3 -v 1.3.13`) or upgrade mailcatcher to the latest release whose gem constraints are compatible.
- If it is Mail/MIME parsing, capture the failing source (context line shows sender/recipients; re-send the same mail to a file with a catch-all like `nc -l 1025`) and fix the sending side's encoding/headers.
- If you use --messages-limit, try disabling it to rule out delete_older_messages! as the raiser.
- If it reproduces on the latest version with a valid email, file an issue with the full block.
Example fix
# before mailcatcher # daemonized; failures vanish after "Error receiving message" # after: visible triage + compatible sqlite3 mailcatcher --foreground --verbose gem uninstall sqlite3 gem install sqlite3 -v 1.3.13 # or: gem update mailcatcher
Defensive patterns
Strategy: try-catch
Validate before calling
# Sanity-check a message before handing the SMTP path a pathological payload
# (guards the two known raisers: SQLite3 insert and Mail MIME parsing)
def safe_to_send?(raw_source)
raw_source.is_a?(String) &&
!raw_source.include?("\0") && # null bytes break older sqlite3 inserts
raw_source.valid_encoding? &&
raw_source.each_line.none? { |l| l.bytesize > 998 } rescue false
end
abort "refusing to send malformed mail" unless safe_to_send?(mail_source) Type guard
# Narrow to the hash shape receive_message expects before injecting into MailCatcher::Mail
def valid_message_hash?(msg)
msg.is_a?(Hash) && msg.key?(:sender) && msg[:sender].is_a?(String) &&
msg[:recipients].is_a?(Array) && msg[:source].is_a?(String) && !msg[:source].empty?
end Try / catch
# receive_message already rescues and returns false; embedders should mirror that contract
begin
MailCatcher::Mail.add_message(current_message)
rescue => e
MailCatcher.log_exception("Error receiving message", current_message, e)
false # SMTP-equivalent: tell the client this delivery failed, keep serving
end Prevention
- Pin sqlite3 to the version your mailcatcher release was built against (classic break: sqlite3 1.4 under old mailcatcher).
- Send mail with correct MIME/charset headers from apps; avoid hand-rolled SMTP payloads in tests.
- Run MailCatcher in the foreground during test suites so receive-time reports are visible immediately.
- Archive raw sources of failed sends (trap them in your own rescue) so lost messages are reproducible.
When it happens
Trigger: A SMTP client completes MAIL FROM/RCPT TO/DATA for a message whose source then fails to parse (Mail.new in mail.rb:47 raising on malformed MIME/encoding) or fails to persist (SQLite3 insert errors in mail.rb:45-67, e.g. null bytes in the source with newer sqlite3 gems, or a prepared-statement type mismatch). Also fires if delete_older_messages! raises while honoring --messages-limit.
Common situations: ActionMailer/Rails apps sending 8-bit or malformed headers; upgrading the sqlite3 gem (1.3 -> 1.4+) under an old mailcatcher, producing ArgumentError/SQLite3 errors on insert; unusual attachments (embedded null bytes, odd charsets); automated test suites that send hand-rolled raw SMTP payloads.
Related errors
AI-assisted analysis of sj26/mailcatcher@18a9cb7a79 (2026-08-21).
Data as JSON: /api/errors/488419ae346291f2.
Report an issue: GitHub.