mailfakk2 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/MIT-LICENSE +20 -0
- data/README.markdown +52 -0
- data/Rakefile +44 -0
- data/bin/mailfakk2 +12 -0
- data/config/env.rb +14 -0
- data/config/forward +2 -0
- data/config/procmail +3 -0
- data/lib/configuration.rb +50 -0
- data/lib/facsimile.rb +170 -0
- data/lib/logging.rb +6 -0
- data/lib/mailfakk2.rb +53 -0
- data/spec/configuration_spec.rb +21 -0
- data/spec/facsimile_spec.rb +70 -0
- data/spec/mailfakk2_spec.rb +57 -0
- data/spec/spec_helper.rb +25 -0
- metadata +130 -0
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
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
data/config/procmail
ADDED
|
@@ -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
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
|
data/spec/spec_helper.rb
ADDED
|
@@ -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
|