mailfakk2 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2006 Sean Treadway
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.markdown ADDED
@@ -0,0 +1,52 @@
1
+ MailFaKK2
2
+ =========
3
+
4
+ A email to fax gateway for asterisk. It will work as a procmail filter.
5
+
6
+
7
+ Motivation
8
+ ==========
9
+
10
+ After trying out several other email to fax gateways we came to the conclusion that not any of them
11
+
12
+ * does not need java
13
+ * is compatible with asterisk 1.6
14
+ * does not cost money
15
+ * has tests
16
+ * just works
17
+
18
+ MailFaKK2 tries to live up to all these requirements.
19
+
20
+
21
+ Installation
22
+ ============
23
+
24
+ Debian / Ubuntu
25
+ ---------------
26
+
27
+ * sudo apt-get install ruby ruby-dev gs unoconv openoffice.org-headless rubygems xvfb librmagick-ruby
28
+ * sudo gem install activesupport andand mail prawn
29
+
30
+ Cons
31
+ ====
32
+
33
+ If you plan to spam by fax you should consider another product. MailFaKK2 is
34
+ kind of slow. This is caused by launching OpenOffice.org for every conversion.
35
+ Speed is not a priority for us (yet).
36
+
37
+ TODO
38
+ ====
39
+
40
+ * [x] generate cover sheet TIFF frame from email body
41
+ * [x] append OpenOffice.org documents
42
+ * [ ] append MS Office documents
43
+ * [ ] write TIFF and callfile
44
+ * [-] procmail mode (untested)
45
+ * [ ] header and footer for every frame
46
+ * [ ] gemspec
47
+ * [ ] check if fax was delivered (callfile moved to outgoing_done)
48
+
49
+ Meta
50
+ ====
51
+
52
+ This product is proudly presented to you by [Planetary Networks](http://planetary-networks.de).
data/Rakefile ADDED
@@ -0,0 +1,44 @@
1
+ begin
2
+ require 'rubygems'
3
+ require 'jeweler'
4
+ Jeweler::Tasks.new do |gemspec|
5
+ gemspec.name = %q{mailfakk2}
6
+ gemspec.summary = %q{email to fax gateway in ruby}
7
+ gemspec.description = %q{
8
+ MailFaKK2 acts as a fax gateway. With the proper setup you can send
9
+ an email to <number>@fax.local and it generates a multipage tiff and
10
+ a callfile for asterisk
11
+ }
12
+ gemspec.email = %q{niklas+mailfakk2@lanpartei.de}
13
+ gemspec.homepage = %q{http://github.com/niklas/MailFaKK2/}
14
+ gemspec.authors = ["Niklas Hofer"]
15
+ gemspec.executables = %w{mailfakk2}
16
+
17
+ gemspec.has_rdoc = false
18
+ gemspec.files = %w{
19
+ README.mardown
20
+ Rakefile
21
+
22
+ bin/mailfakk2
23
+
24
+ config/env.rb
25
+ config/forward
26
+ config/procmail
27
+
28
+ lib/logging.rb
29
+ lib/configuration.rb
30
+ lib/facsimile.rb
31
+ lib/mailfakk2.rb
32
+
33
+ MIT-LICENSE
34
+ }
35
+
36
+ gemspec.add_dependency('activesupport', '>=2.3.5')
37
+ gemspec.add_dependency('andand', '>=1.3.1')
38
+ gemspec.add_dependency('mail', '>=2.2.0')
39
+ gemspec.add_dependency('prawn', '>=0.8.4')
40
+ end
41
+ Jeweler::GemcutterTasks.new
42
+ rescue LoadError
43
+ puts "Jeweler not available. Install it with: sudo gem install jeweler"
44
+ end
data/bin/mailfakk2 ADDED
@@ -0,0 +1,12 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require File.expand_path(File.join(File.dirname(__FILE__),'..','config','env'))
4
+
5
+
6
+ include Logging
7
+ begin
8
+ fakk = MailFakk2.deliver!(STDIN)
9
+ rescue Exception => e
10
+ log(e.message, :err)
11
+ STDERR.puts e.message
12
+ end
data/config/env.rb ADDED
@@ -0,0 +1,14 @@
1
+ APP_ROOT = File.join File.basename(__FILE__), '..'
2
+ require 'rubygems'
3
+ require 'active_support'
4
+ require 'fileutils'
5
+ require 'andand'
6
+ require 'mail'
7
+ require 'prawn'
8
+ require 'RMagick'
9
+ require 'tempfile'
10
+
11
+ require 'logging'
12
+ require 'facsimile'
13
+ require 'configuration'
14
+ require 'mailfakk2'
data/config/forward ADDED
@@ -0,0 +1,2 @@
1
+ # put this in ~/.forward
2
+ "|/usr/bin/procmail"
data/config/procmail ADDED
@@ -0,0 +1,3 @@
1
+ # put this into ~fax/.procmailrc
2
+ :0
3
+ | mailfakk2
@@ -0,0 +1,50 @@
1
+ require 'ostruct'
2
+ class Configuration < Hash
3
+ Defaults = {
4
+ 'outgoing_call_dir' => '/var/spool/asterisk/outgoing',
5
+ 'archive_path' => File.join(ENV['HOME'], 'facsimiles')
6
+ }
7
+
8
+ # Config files are read in this order
9
+ Sources = [
10
+ '/etc/mailfakk2.yml',
11
+ File.join( ENV['HOME'], '.mailfakk2.yml')
12
+ ]
13
+
14
+ def method_missing(methname, *args, &block)
15
+ methname = methname.to_s
16
+ if has_key?(methname)
17
+ self[methname]
18
+ else
19
+ if !block_given? && args.empty?
20
+ raise NoMethodError, "unknown configuration field: #{methname}"
21
+ else
22
+ super
23
+ end
24
+ end
25
+ end
26
+
27
+ def self.load
28
+ conf = returning(Defaults) do |h|
29
+ Sources.each do |source|
30
+
31
+ if File.file?(source) && File.readable?(source)
32
+ loaded = YAML.load_file source
33
+ if loaded.is_a?(Hash)
34
+ h.merge! loaded
35
+ end
36
+ end
37
+
38
+ end
39
+ end
40
+ build conf
41
+ end
42
+
43
+ def self.default
44
+ build Defaults
45
+ end
46
+
47
+ def self.build(hash)
48
+ new.update(Defaults).update(hash)
49
+ end
50
+ end
data/lib/facsimile.rb ADDED
@@ -0,0 +1,170 @@
1
+ class Facsimile
2
+ include Logging
3
+
4
+ Width = 1728
5
+ Height = 2156
6
+
7
+ #include ActiveSupport::Memoization
8
+
9
+ class NoPhoneNumberFound < Exception; end
10
+ class NoContentFound < Exception; end
11
+
12
+ attr_reader :frames
13
+ attr_reader :mail
14
+
15
+ def initialize(source)
16
+ if source.is_a?(IO)
17
+ @mail = Mail.new(source.read)
18
+ else
19
+ @mail = Mail.read(source)
20
+ end
21
+ @frames = Magick::ImageList.new
22
+ @tempfiles = []
23
+ end
24
+
25
+ def number
26
+ n = mail.header['X-Original-To'].andand.to_s || mail.to.andand.first
27
+ if n.present? && n.to_s =~ /^(\d{5,})/
28
+ return $1
29
+ else
30
+ raise NoPhoneNumberFound, "could not find any phone number"
31
+ end
32
+ end
33
+
34
+ #memoize :number
35
+
36
+ def render
37
+
38
+ if mail.multipart?
39
+
40
+ mail.parts.each do |part|
41
+ case part.content_type
42
+ when %r'text/plain'
43
+ add_frames text2tiff( part.decoded )
44
+ when %r'opendocument\.text'
45
+ add_frames oo2tiff( part.decoded )
46
+ when %r'text/html'
47
+ # FIXME ignore html, let's hope a plain text contained everything important
48
+ else
49
+ STDERR.puts "unsupported content type: #{part.content_type}"
50
+ end
51
+ end
52
+
53
+ else
54
+
55
+ unless mail.body.decoded.blank?
56
+ text2tiff( mail.body.decoded ).each do |tiff|
57
+ frames << tiff
58
+ end
59
+ end
60
+
61
+ end
62
+
63
+ end
64
+
65
+ def write(path)
66
+ render
67
+ raise NoContentFound if frames.empty?
68
+ path = File.expand_path path
69
+ log("writing facsimile to #{path}")
70
+ path += '.tiff' unless path.ends_with?('.tiff')
71
+ dir = File.dirname path
72
+ FileUtils.mkdir_p(dir) unless File.directory?(dir)
73
+ frames.write(path)
74
+ end
75
+
76
+ def filename
77
+ "#{id}.tiff"
78
+ end
79
+
80
+ def callfile_name
81
+ "#{id}.call"
82
+ end
83
+
84
+ def id
85
+ unless mail.has_message_id?
86
+ mail.add_message_id("#{Time.now.iso8601}-#{Process.pid}")
87
+ end
88
+ mail.message_id
89
+ end
90
+
91
+ private
92
+
93
+ def add_frames(tiffs=nil)
94
+ return unless tiffs
95
+ tiffs.each do |tiff|
96
+ frames << tiff
97
+ end
98
+ end
99
+
100
+ def text2tiff(text)
101
+ pdf = text2pdf(text)
102
+ pdf2tiff(pdf)
103
+ end
104
+
105
+ def pdf2tiff(source)
106
+ dest = mktemp('tiff')
107
+ command = returning ['gs'] do |gs|
108
+ gs << '-dQUIET'
109
+ gs << '-sDEVICE=tiffg3'
110
+ gs << "-sPAPERSIZE=#{pagesize}"
111
+ gs << '-r204x196'
112
+ gs << '-dNOPAUSE'
113
+ gs << "-sOutputFile=#{dest.path}"
114
+ gs << '-c save pop'
115
+ gs << '-c "<< /Policies << /PageSize 5 >> /PageSize [595 842] /InputAttributes << 0 << /PageSize [595 842] >> >> >> setpagedevice"'
116
+ gs << "-f #{source}"
117
+ gs << '-c quit'
118
+ end.join(' ')
119
+ system(command)
120
+ read_frame dest.path
121
+ end
122
+
123
+ def oo2tiff(source_data)
124
+ source = mktemp('oo', false)
125
+ source.write source_data
126
+ source.close
127
+
128
+ dest = mktemp('pdf')
129
+ xvfb("unoconv -f pdf #{source.path}")
130
+ FileUtils.mv source.path + '.pdf', dest.path
131
+ pdf2tiff(dest.path)
132
+ end
133
+
134
+ def text2pdf(source)
135
+ document = Prawn::Document.new(:page_size => pagesize.upcase)
136
+ document.text source
137
+
138
+ dest = mktemp('pdf')
139
+ document.render_file dest.path
140
+
141
+ dest.path
142
+ end
143
+
144
+ def new_frame
145
+ tiff = Magick::Image.new(Width, Height) do
146
+ self.background_color = 'white'
147
+ end
148
+ tiff
149
+ end
150
+
151
+ def read_frame(source)
152
+ Magick::Image.read(source)
153
+ end
154
+
155
+ def mktemp(name,close=true)
156
+ tmp = Tempfile.new(name)
157
+ tmp.close if close
158
+ tmp
159
+ end
160
+
161
+ def pagesize
162
+ 'a4'
163
+ end
164
+
165
+ def xvfb(command)
166
+ system("xvfb-run --auto-servernum --server-num=23 #{command}")
167
+ end
168
+
169
+
170
+ end
data/lib/logging.rb ADDED
@@ -0,0 +1,6 @@
1
+ require 'syslog'
2
+ module Logging
3
+ def log(message, severity=:warning)
4
+ Syslog.open('mailfakk2', Syslog::LOG_PID | Syslog::LOG_CONS) { |s| s.send(severity, message) }
5
+ end
6
+ end
data/lib/mailfakk2.rb ADDED
@@ -0,0 +1,53 @@
1
+ class MailFakk2
2
+ include Logging
3
+
4
+ def self.deliver!(source)
5
+ new(source).deliver!
6
+ end
7
+
8
+ attr_reader :fax
9
+
10
+ def initialize(source)
11
+ @fax = Facsimile.new(source)
12
+ end
13
+
14
+ def deliver!
15
+ log("sending fax to #{@fax.number}")
16
+ @fax.write( archive_path )
17
+ write_callfile
18
+ self
19
+ end
20
+
21
+ def archive_path
22
+ File.expand_path File.join( config.archive_path, @fax.filename)
23
+ end
24
+
25
+ def callfile_path
26
+ File.join( config.outgoing_call_dir, @fax.callfile_name)
27
+ end
28
+
29
+ def config
30
+ @config ||= Configuration.load
31
+ end
32
+
33
+ def write_callfile
34
+ tmp = Tempfile.new('call')
35
+ tmp.puts callfile_contents
36
+ tmp.close
37
+ FileUtils.mkdir_p config.outgoing_call_dir
38
+ FileUtils.mv tmp.path, callfile_path
39
+ FileUtils.chmod 0666, callfile_path
40
+ end
41
+
42
+ def callfile_contents
43
+ <<-EOCALL
44
+ Channel: DAHDI/g0/#{@fax.number}
45
+ MaxRetries: 5
46
+ WaitTime: 20
47
+ Context: incoming-fax
48
+ Application: SendFax
49
+ Data:#{archive_path}
50
+ Archive: yes
51
+ EOCALL
52
+ end
53
+ end
@@ -0,0 +1,21 @@
1
+ require 'spec_helper'
2
+
3
+ describe Configuration do
4
+ describe "loading" do
5
+ it 'should try system, then home' do
6
+ File.should_receive(:file?).ordered.with('/etc/mailfakk2.yml').and_return(false)
7
+ File.should_receive(:file?).ordered.with( File.join(ENV['HOME'], '.mailfakk2.yml') ).and_return(false)
8
+ c = Configuration.load
9
+ c.should be_a(Configuration)
10
+ end
11
+
12
+ it 'should fall back to defaults' do
13
+ File.stub!(:file?).and_return(false)
14
+ c = Configuration.load
15
+ Configuration::Defaults.each do |k,v|
16
+ c[k].should == v
17
+ c.send(k).should == v
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,70 @@
1
+ require 'spec_helper'
2
+
3
+ describe "text only" do
4
+ before(:each) do
5
+ @mail_path = mail_path('only_text')
6
+ @fax = Facsimile.new @mail_path
7
+ end
8
+
9
+ it 'should find #number' do
10
+ @fax.number.should == '01189998819991197253'
11
+ end
12
+
13
+ it 'should render 1 frame from body' do
14
+ @fax.write result_path('only_text')
15
+ @fax.frames.should be_an(Magick::ImageList)
16
+ @fax.should have(1).frame
17
+ end
18
+
19
+ it 'should add footer and header'
20
+ end
21
+
22
+ describe "text only as IO (like STDIN)" do
23
+ before(:each) do
24
+ @fax = Facsimile.new File.open( mail_path('only_text') )
25
+ end
26
+
27
+ it 'should find #number' do
28
+ @fax.number.should == '01189998819991197253'
29
+ end
30
+
31
+ it 'should provide id (even if no message_id in mail)' do
32
+ @fax.id.should_not be_blank
33
+ end
34
+
35
+ it 'should provide filename' do
36
+ @fax.filename.should =~ /.{10,}\.tiff/
37
+ end
38
+
39
+ end
40
+
41
+ describe "multipart from word mail client" do
42
+ before(:each) do
43
+ @mail_path = mail_path('multipart')
44
+ @fax = Facsimile.new @mail_path
45
+ end
46
+
47
+ it 'should find #number' do
48
+ @fax.number.should == '01189998819991197253'
49
+ end
50
+
51
+ it 'should render 1 frame from parts' do
52
+ @fax.write result_path('multipart')
53
+ @fax.frames.should be_an(Magick::ImageList)
54
+ @fax.should have(1).frame
55
+ end
56
+ end
57
+
58
+
59
+ describe "text with attached OpenOffice Writer Document (2 Pages)" do
60
+ before(:each) do
61
+ @mail_path = mail_path('oo_writer_attached')
62
+ @fax = Facsimile.new @mail_path
63
+ end
64
+
65
+ it 'should produce 1+2 frames' do
66
+ @fax.write result_path('oo_writer_attached')
67
+ @fax.should have(3).frames
68
+ end
69
+
70
+ end
@@ -0,0 +1,57 @@
1
+ require 'spec_helper'
2
+
3
+ describe "MailFakk2" do
4
+ before(:each) do
5
+ @mail = mail_path('only_text')
6
+ @fakk = MailFakk2.new @mail
7
+ end
8
+
9
+ it 'should create a Facsimile' do
10
+ @fakk.fax.should be_a(Facsimile)
11
+ end
12
+
13
+ it 'should load configuration' do
14
+ Configuration.should_receive(:load).once.and_return('config')
15
+ @fakk.config.should == 'config'
16
+ end
17
+
18
+ describe "delivery" do
19
+
20
+ before(:each) do
21
+ @conf = test_configuration
22
+ @fax_path = File.expand_path File.join( @conf.archive_path, @fakk.fax.filename)
23
+ @fakk.stub!(:config).and_return(@conf)
24
+ @fax = @fakk.fax
25
+ @fax.stub!(:render)
26
+ frames_mock = mock(:empty? => false, :write => true)
27
+ @fakk.fax.stub!(:frames).and_return(frames_mock)
28
+ @delivering = lambda { @fakk.deliver! }
29
+ end
30
+
31
+ after(:each) do
32
+ end
33
+
34
+ it 'should render the fax' do
35
+ @fax.should_receive(:render).once
36
+ @delivering.call
37
+ end
38
+
39
+ it 'should save the tiff to the archive path' do
40
+ @fax.should_receive(:write).with( @fax_path )
41
+ @delivering.call
42
+ end
43
+
44
+ it 'should create and move a callfile with proper permissions' do
45
+ @delivering.call
46
+ callfile_path = File.join( @conf.outgoing_call_dir, @fax.callfile_name)
47
+ File.file?(callfile_path).should be_true
48
+ # TODO permissions should be 0666, just to be sure. How to test this?
49
+ end
50
+
51
+ it 'should wait for the callfile to be moved to outgoing_done'
52
+ it 'should deliver a mail if no number was found'
53
+ it 'should deliver a mail if sending the fax failed'
54
+ it 'may deliver a mail report for successfull delivery'
55
+ end
56
+ it 'maybe should detach from procmail to enhance processing speed'
57
+ end
@@ -0,0 +1,25 @@
1
+ require 'spec/autorun'
2
+
3
+ require File.expand_path(File.join(File.dirname(__FILE__),'..','config','env'))
4
+
5
+ ResultsDir = File.join APP_ROOT, 'tmp', 'results'
6
+
7
+ FileUtils.rm_rf ResultsDir if File.exists?(ResultsDir)
8
+ FileUtils.mkdir_p ResultsDir
9
+
10
+ def mail_path(name)
11
+ name += '.mail' unless name.ends_with?('.mail')
12
+ File.join APP_ROOT, 'spec', 'fixtures', name
13
+ end
14
+
15
+ def result_path(name)
16
+ name += '.tiff' unless name.ends_with?('.tiff')
17
+ File.join ResultsDir, name
18
+ end
19
+
20
+ def test_configuration
21
+ @@test_configuration ||= Configuration.build({
22
+ 'outgoing_call_dir' => ResultsDir,
23
+ 'archive_path' => ResultsDir
24
+ })
25
+ end
metadata ADDED
@@ -0,0 +1,130 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: mailfakk2
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 1
8
+ - 1
9
+ version: 0.1.1
10
+ platform: ruby
11
+ authors:
12
+ - Niklas Hofer
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2010-04-16 00:00:00 +02:00
18
+ default_executable: mailfakk2
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: activesupport
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - ">="
26
+ - !ruby/object:Gem::Version
27
+ segments:
28
+ - 2
29
+ - 3
30
+ - 5
31
+ version: 2.3.5
32
+ type: :runtime
33
+ version_requirements: *id001
34
+ - !ruby/object:Gem::Dependency
35
+ name: andand
36
+ prerelease: false
37
+ requirement: &id002 !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - ">="
40
+ - !ruby/object:Gem::Version
41
+ segments:
42
+ - 1
43
+ - 3
44
+ - 1
45
+ version: 1.3.1
46
+ type: :runtime
47
+ version_requirements: *id002
48
+ - !ruby/object:Gem::Dependency
49
+ name: mail
50
+ prerelease: false
51
+ requirement: &id003 !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - ">="
54
+ - !ruby/object:Gem::Version
55
+ segments:
56
+ - 2
57
+ - 2
58
+ - 0
59
+ version: 2.2.0
60
+ type: :runtime
61
+ version_requirements: *id003
62
+ - !ruby/object:Gem::Dependency
63
+ name: prawn
64
+ prerelease: false
65
+ requirement: &id004 !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - ">="
68
+ - !ruby/object:Gem::Version
69
+ segments:
70
+ - 0
71
+ - 8
72
+ - 4
73
+ version: 0.8.4
74
+ type: :runtime
75
+ version_requirements: *id004
76
+ description: "\n MailFaKK2 acts as a fax gateway. With the proper setup you can send\n an email to <number>@fax.local and it generates a multipage tiff and\n a callfile for asterisk\n "
77
+ email: niklas+mailfakk2@lanpartei.de
78
+ executables:
79
+ - mailfakk2
80
+ extensions: []
81
+
82
+ extra_rdoc_files:
83
+ - README.markdown
84
+ files:
85
+ - MIT-LICENSE
86
+ - Rakefile
87
+ - bin/mailfakk2
88
+ - config/env.rb
89
+ - config/forward
90
+ - config/procmail
91
+ - lib/configuration.rb
92
+ - lib/facsimile.rb
93
+ - lib/logging.rb
94
+ - lib/mailfakk2.rb
95
+ - README.markdown
96
+ has_rdoc: true
97
+ homepage: http://github.com/niklas/MailFaKK2/
98
+ licenses: []
99
+
100
+ post_install_message:
101
+ rdoc_options:
102
+ - --charset=UTF-8
103
+ require_paths:
104
+ - lib
105
+ required_ruby_version: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - ">="
108
+ - !ruby/object:Gem::Version
109
+ segments:
110
+ - 0
111
+ version: "0"
112
+ required_rubygems_version: !ruby/object:Gem::Requirement
113
+ requirements:
114
+ - - ">="
115
+ - !ruby/object:Gem::Version
116
+ segments:
117
+ - 0
118
+ version: "0"
119
+ requirements: []
120
+
121
+ rubyforge_project:
122
+ rubygems_version: 1.3.6
123
+ signing_key:
124
+ specification_version: 3
125
+ summary: email to fax gateway in ruby
126
+ test_files:
127
+ - spec/configuration_spec.rb
128
+ - spec/spec_helper.rb
129
+ - spec/mailfakk2_spec.rb
130
+ - spec/facsimile_spec.rb