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

8
Leave a Reply

avatar
2 Comment threads
6 Thread replies
0 Followers
 
Most reacted comment
Hottest comment thread
3 Comment authors
Daniel P. Clarkunderpantsgnomegrosser Recent comment authors
  Subscribe  
newest oldest most voted
Notify of
grosser
Guest

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

Daniel P. Clark
Guest

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
Guest

Yep that’s it

underpantsgnome
Guest
underpantsgnome

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
Guest

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
Guest
underpantsgnome

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
Guest

Perhaps so. It seems to be in an initializer.

[/crayon]

underpantsgnome
Guest
underpantsgnome

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