Permalink
Browse files

Fixed merge conflicts in favour of Luke's code

  • Loading branch information...
2 parents fa97593 + 1989c42 commit 28a0bfa36b512d20e9e50bdb5356537cc6178285 @mmower committed Jan 21, 2010
Showing with 299 additions and 28 deletions.
  1. +1 −10 Manifest.txt
  2. +10 −7 README.txt
  3. +2 −3 Rakefile
  4. +14 −5 bin/mailtrap
  5. +106 −0 lib/mailshovel.rb
  6. +13 −3 lib/mailtrap.rb
  7. +11 −0 mailtrap.gemspec
  8. +142 −0 test/mailshovel_test.rb
View
@@ -4,13 +4,4 @@ README.txt
Rakefile
bin/mailtrap
lib/mailtrap.rb
-lib/mailtrap/log_parser.rb
-spec
-spec/mailtrap
-spec/mailtrap/log_parser_spec.rb
-spec/mailtrap/sample_logs
-spec/mailtrap/sample_logs/sample.log
-spec/mailtrap/sample_logs/sample_empty.log
-spec/spec.opts
-test
-test/test_mailtrap.rb
+lib/mailshovel.rb
View
@@ -2,13 +2,15 @@ mailtrap
by Matt Mower <self@mattmower.com>
http://matt.blogs.it/
+ modified (and Mailshovel added) by Gwyn Morfey <mail@gwynmorfey.com>
+
== DESCRIPTION:
-Mailtrap is a mock SMTP server for use in Rails development.
+Mailtrap is a mock SMTP server for use in Rails development. This package also includes Mailshovel, a mock POP3 server that works with Mailtrap. You can configure your mail client (eg Mail.App) to connect to Mailshovel, and then manage messages that ActionMailer has "sent" using its GUI.
-Mailtrap waits on your choosen port for a client to connect and talks _just enough_ SMTP protocol for ActionMailer to successfully deliver its message.
+Mailtrap waits on your chosen port for a client to connect and talks _just enough_ SMTP protocol for ActionMailer to successfully deliver its message.
-Mailtrap makes *no* attempt to actually deliver messages and, instead, writes them into a file (hence the name Mail_trap_). Handy tip: use tail -f to see emails being received.
+Mailtrap makes *no* attempt to actually deliver messages and, instead, writes them into a series of files which are read by Mailshovel.
You can configure the hostname (default: localhost) and port (default: 2525) for the server and also where the messages get written (default: /var/tmp/mailtrap.log).
@@ -21,14 +23,15 @@ You can configure the hostname (default: localhost) and port (default: 2525) for
== SYNOPSIS:
-To use the defaults host:localhost, port:2525, file:/var/log/mailtrap.log
+To use the defaults host:localhost, port:2525 and port:1100, file:/var/log/mailtrap.log
* mailtrap start
-Customise startup:
+This will start both mailtrap and mailshovel.
-* sudo mailtrap start --host my.host --port 25 --once --file=/var/log/messages.txt
+Customise startup:
+* sudo mailtrap start --host my.host --smtp_port 25 --pop3_port 110 --once --file=/var/log/messages.txt --msg_dir=/tmp/msgs
(sudo because you want to use restricted port 25)
For more info:
@@ -47,7 +50,7 @@ All these are automatically installed if you use gem install -y
== INSTALL:
-* sudo gem install -y mailtrap
+* sudo gem install -y mailshovel
== LICENSE:
View
@@ -2,9 +2,8 @@
require 'rubygems'
require 'hoe'
-require 'spec'
-require 'spec/rake/spectask'
-require './lib/mailtrap'
+require './lib/mailtrap.rb'
+require './lib/mailshovel.rb'
Hoe.new('mailtrap', Mailtrap::VERSION ) do |p|
p.rubyforge_name = 'simplyruby'
View
@@ -6,12 +6,16 @@
require 'rubygems'
require 'daemons'
require 'mailtrap'
+require 'mailshovel'
opts = Trollop::options do
- opt :host, "The host SMTP clients will connect to", :default => 'localhost'
- opt :port, "The port SMTP clients will connect to", :default => 2525
+ opt :smtp_host, "The host SMTP clients will connect to", :default => 'localhost'
+ opt :smtp_port, "The port SMTP clients will connect to", :default => 2525
+ opt :pop3_host, "The host POP3 clients will connect to", :default => 'localhost'
+ opt :pop3_port, "The port POP3 clients will connect to", :default => 1100
opt :once, "Whether to terminate after serving the first client", :default => false
- opt :file, "File where messages get written", :default => "/var/tmp/mailtrap.log"
+ opt :file, "File where messages get written as a single file", :default => "/var/tmp/mailtrap.log"
+ opt :msg_dir, "Dir where messages are stored temporarily until served via POP3", :default=>"/var/tmp/mailtrap"
end
options = {
@@ -24,5 +28,10 @@ options = {
}
Daemons.run_proc( 'mailtrap', options ) do
- Mailtrap.new( opts[:host], opts[:port], opts[:once], opts[:file] )
-end
+ Mailtrap.new( opts[:smtp_host], opts[:smtp_port], opts[:once], opts[:file], opts[:msg_dir])
+end
+
+Daemons.run_proc( 'mailshovel', options ) do
+ Mailshovel.connect( opts[:pop3_host], opts[:pop3_port], opts[:msg_dir] )
+end
+
View
@@ -0,0 +1,106 @@
+require 'rubygems'
+require 'daemons'
+require 'socket'
+require 'trollop'
+
+#
+# Speaks pidgin-POP3 to serve out mail in mailtrap's folder format.
+# If nothing works, look at the \r\n conversion: this was written and tested on a mac.
+#
+class Mailshovel
+ VERSION = '0.1'
+
+ def initialize(service, msgdir)
+ @service = service
+ @msgdir = msgdir
+ @deletion_queue = []
+
+ accept(service)
+ end
+
+ def self.connect(host, port, msgdir)
+ service = TCPServer.new(host, port)
+ new(service, msgdir)
+ end
+
+ # Service one or more POP3 client connections
+ def accept( service )
+ while session = service.accept
+ class << session
+ def get_line
+ line = gets
+ line.chomp! unless line.nil?
+ line
+ end
+ end
+ begin
+ serve( session )
+ rescue Exception => e
+ warn e.message
+ puts "Erk! #{e.message}"
+ end
+ end
+ end
+
+ #Return an array of full filenames, in the proper order
+ def messages
+ Dir.entries(@msgdir).collect{|e| File.join(@msgdir,e) if e[0..0] != "."}.compact.sort
+ end
+
+ # Talk pidgin-POP3 to the client
+ def serve( connection )
+ puts "Connected."
+ senddata connection, "+OK Mailshovel. I'm a testing server that speaks poor POP3: try Apple's Mail.App if nothing else works.\r\n"
+ loop do
+ if incoming = connection.get_line
+ puts "< #{incoming}"
+ case incoming.split(" ")[0]
+ when "USER", "PASS"
+ senddata connection, "+OK Whatever, man.\r\n"
+ when "STAT"
+ senddata connection, "+OK #{messages.length} #{messages.length}\r\n"
+ when "UIDL"
+ senddata connection, "+OK\r\n"
+ 0.upto(messages.length-1) do |n| #Fudging needed since POP3 indices start at 1, not 0
+ senddata connection, "#{n+1} #{messages[n].gsub("/","Z")}\r\n"
+ end
+ senddata connection, ".\r\n"
+ when "LIST"
+ senddata connection, "+OK\r\n"
+ 0.upto(messages.length-1) do |n|
+ senddata connection, "#{n+1} 100\r\n"
+ end
+ senddata connection, ".\r\n"
+ when "RETR"
+ senddata connection, "+OK\r\n"
+ senddata connection, File.new(messages[incoming.split(" ")[1].to_i-1],"r").read.gsub("\r","\r\n")
+ senddata connection, "\r\n.\r\n"
+ when "DELE"
+ senddata connection, "+OK\r\n"
+ schedule_for_delete(messages[incoming.split(" ")[1].to_i-1])
+ when "QUIT"
+ senddata connection, "+OK Closing connection.\r\n"
+ delete_pending_mail
+ connection.close
+ else
+ senddata connection, "-ERR I don't understand '#{incoming}'.\r\n"
+ end
+ end
+ end
+ end
+
+ def senddata(connection,data)
+ puts "> #{data}"
+ connection.puts data
+ end
+
+ private
+
+ def schedule_for_delete(message)
+ @deletion_queue << message
+ end
+
+ def delete_pending_mail
+ @deletion_queue.each { |message| FileUtils.rm(message) }
+ end
+end
View
@@ -10,17 +10,21 @@
# clients. Accepts the connection and talks just enough of the SMTP protocol
# for them to deliver a message which it writes to disk.
#
+# Based on Matt Mower's original; slightly modified by Gwyn Morfey to write messages
+# as separate files so that we can serve them out by POP3.
class Mailtrap
- VERSION = '0.2.1'
+ VERSION = '0.2.2'
# Create a new Mailtrap on the specified host:port. If once it true it
# will listen for one message then exit. Specify the msgdir where messages
# are written.
- def initialize( host, port, once, msgfile )
+ def initialize( host, port, once, msgfile, msgdir )
@host = host
@port = port
@once = once
@msgfile = msgfile
+ @msgdir = msgdir
+ @msgnum = 0
File.open( @msgfile, "a" ) do |file|
file.puts "\n* Mailtrap started at #{@host}:#{port}\n"
@@ -56,6 +60,7 @@ def get_line
# file. The file will be in the @msgdir folder and will
# be called smtp0001.msg, smtp0002.msg, and so on.
def write( from, to_list, message )
+ @msgnum += 1
# Strip SMTP commands from To: and From:
from.gsub!( /MAIL FROM:\s*/, "" )
@@ -70,7 +75,12 @@ def write( from, to_list, message )
file.puts message
file.puts "\n* Message ends"
end
-
+
+ #Write into msgs dir, also - Mailshovel needs this.
+ Dir.mkdir(@msgdir) if !File.exist?(@msgdir)
+ File.open(File.join(@msgdir,Time.now.to_i.to_s + "_" + sprintf("%03.0f",@msgnum) + ".txt"),"w") do |file|
+ file.puts message
+ end
end
# Talk pidgeon-SMTP to the client to get them to hand over the message
View
@@ -0,0 +1,11 @@
+Gem::Specification.new do |s|
+ s.name = 'mailtrap'
+ s.author = 'Matt Mower'
+ s.email = 'self@mattmower.com'
+ s.summary = 'Mailtrap is a mock SMTP server for use in Rails development'
+ s.version = '0.2.1'
+
+ s.require_paths = ["lib"]
+ s.files = %w{lib/mailtrap.rb lib/mailshovel.rb bin/mailtrap}
+ s.executables = ['mailtrap']
+end
Oops, something went wrong. Retry.

0 comments on commit 28a0bfa

Please sign in to comment.