May 12, 2015 by Daniel P. Clark

Fake a SMTP Server with Python for Rails Testing

So I’ve been in the process of writing an integration test to verify the flow of registration through some unique conditions.  One thing I ran into while writing my Rails test was this error.

Connection refused – connect(2) for nil port 25

After looking around at documentation on what to do for testing it seemed that everything was as it should be except my test environment wasn’t bypassing the actual sending of email which lead to this error.  Since I couldn’t find the answer with any Rails, S.O., or github.com/mikel/mail documentation on a quick fix I decided to use a dummy SMTP server.

I didn’t want to keep any mail sent, so this question http://serverfault.com/questions/207619/how-to-setup-a-fake-smtp-server-to-catch-all-mails had an excellent answer with Python.  It seems Python has a smtpd debugging feature which just prints incoming SMTP email out to STDOUT.

Now I don’t want to have to type this every time I run my Rails test suite so I need to have my computer start with this running in the background.  On Ubuntu that was rather simple to do by creating a text file in /etc/init.d , making it executable, and adding it to the boot-up sequence with update-rc.d .  Since I don’t care about looking at the email I’ve routed the output to /dev/null.  But you could just as easily append it to a text file to read periodically.

You may get a message complaining about invalid header information.  But that’s not important as your background task will still start up on boot.  And even though it won’t shutdown properly through this script, the computer will be turning off anyways so that will close it.

And now my Rails test passes splendidly.  If you’d like to start the script without rebooting just type:

If you want to write to a text file just change /dev/null to the path and file you want written to.  If you want it to append to the text file and not overwrite then change the preceding greater than symbol to two greater than symbols >>.

Summary

I’m quite happy that Python has included this debugging tool as it allows me a no hassle use as I don’t have to install anything or worry about any file clutter.

Please feel free to comment, share, subscribe to my RSS Feed, and follow me on twitter @6ftdan!

God Bless!
-Daniel P. Clark

Image by greg westfall via the Creative Commons Attribution 2.0 Generic License.

#linux#mail#python#rails#smtp#smtpd#testing#ubuntu
0 0 vote
Article Rating
Subscribe
Notify of
guest
8 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
grosser
5 years ago

FYI You can use mailcrate gem to create a in-process smtp server.

Daniel P. Clark
5 years ago
Reply to  grosser

That sounds great! Is this the source? https://github.com/adscott/mailcrate

The ones I had found online all seemed to send to an online service (which is not what I wanted).

grosser
5 years ago

Yep that’s it

underpantsgnome
underpantsgnome
5 years ago

Is this what you were looking for? http://guides.rubyonrails.org/action_mailer_basics.html#action-mailer-configuration have a look at delivery_method

Daniel P. Clark
5 years ago

Yeah, this is what I’d seen. But my test environment already has the delivery_method set to :test and I was still getting this error. Setting perform_deliveries to false may fix this error as it “can be turned off to help functional testing.”. I didn’t see that in any testing documentation though. Should be easy enough to do in config/environments/test.rb

underpantsgnome
underpantsgnome
5 years ago

Strange, any possibility it’s being set someplace else? I’ve run in to that on some client apps, where they are setting one global config so no matter what you set for an environment it gets ignored.

Daniel P. Clark
5 years ago

Perhaps so. It seems to be in an initializer.

[/crayon]

underpantsgnome
underpantsgnome
5 years ago

That’ll do it. That mail initializer will run after your environment config. 🙂