From b7a6f20975e5174fabf39b149c5403ecbfbb201a Mon Sep 17 00:00:00 2001 From: Oskar Eichler Date: Thu, 27 Aug 2026 23:55:00 +0300 Subject: [PATCH 1/2] Restore SMTP IO sync even when DATA flushing fails --- lib/net/smtp.rb | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/lib/net/smtp.rb b/lib/net/smtp.rb index cca06e6..3bbbd66 100644 --- a/lib/net/smtp.rb +++ b/lib/net/smtp.rb @@ -973,8 +973,11 @@ def data(msgstr = nil, &block) #:yield: stream @socket.write_message_by_block(&block) end ensure - @socket.io.flush - @socket.io.sync = socket_sync_bak + begin + @socket.io.flush + ensure + @socket.io.sync = socket_sync_bak + end end recv_response() } From 1f8b1c2ffc25cf08b87074817e8615a72fe7642d Mon Sep 17 00:00:00 2001 From: Oskar Eichler <62393985+OskarEichler@users.noreply.github.com> Date: Fri, 28 Aug 2026 15:24:20 +0300 Subject: [PATCH 2/2] Add regression coverage for restore smtp io sync even when data flushing fails --- test/net/smtp/test_smtp.rb | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/test/net/smtp/test_smtp.rb b/test/net/smtp/test_smtp.rb index 3b9e245..8d84fb3 100644 --- a/test/net/smtp/test_smtp.rb +++ b/test/net/smtp/test_smtp.rb @@ -253,6 +253,30 @@ def server.data assert_equal "250", err.response.status end + def test_data_restores_sync_when_flush_fails + io = Object.new + class << io + attr_accessor :sync + + def flush + raise IOError, "flush failed" + end + end + io.sync = true + socket = Object.new + socket.define_singleton_method(:io) { io } + socket.define_singleton_method(:write_message) { |_| } + + smtp = Net::SMTP.new("example.invalid", starttls: false) + smtp.instance_variable_set(:@socket, socket) + smtp.define_singleton_method(:get_response) do |_| + Net::SMTP::Response.parse("354 continue") + end + + assert_raise(IOError) { smtp.data("message") } + assert_equal true, io.sync + end + def test_crlf_injection server = FakeServer.new smtp = Net::SMTP.new 'localhost', server.port