received 0.2.0 → 0.3.0

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/bin/received CHANGED
@@ -46,6 +46,7 @@ if options.delete(:daemon)
46
46
  # Drop privileges if started as superuser
47
47
  params.merge!({:user => options[:user] || 'nobody', :group => options[:group] || 'nobody'}) if Process.uid == 0
48
48
  Daemons.daemonize(params)
49
+ File.umask(0007)
49
50
  end
50
51
 
51
52
  server = Received::Server.new(options)
@@ -18,8 +18,9 @@ module Received
18
18
  # Store mail in MongoDB
19
19
  #
20
20
  # @param [Hash] mail
21
+ # @return [ObjectId] object_id
21
22
  def store(mail)
22
- @coll.save(mail.merge({:ts => Time.now.to_i}), :safe => true)
23
+ @coll.insert(mail.merge({:ts => Time.now.to_i}), :safe => {:fsync => true})
23
24
  end
24
25
  end
25
26
  end
@@ -34,12 +34,19 @@ module Received
34
34
  #
35
35
  # @param [Hash] mail
36
36
  # @see Received::Backend::Base#store
37
+ # @return [Boolean] saving succeeded
37
38
  def mail_received(mail)
38
39
  begin
39
- @backend.store(mail)
40
- logger.info "stored mail from: #{mail[:from]}"
40
+ if insert_id = @backend.store(mail)
41
+ logger.info "stored mail from: #{mail[:from]} (#{insert_id})"
42
+ return true
43
+ else
44
+ logger.error "saving of mail from #{mail[:from]} failed"
45
+ end
46
+ false
41
47
  rescue Exception => e
42
- logger.error "saving failed with: #{e.message}"
48
+ logger.error "saving of mail from #{mail[:from]} failed with: #{e.message}"
49
+ false
43
50
  end
44
51
  end
45
52
 
data/lib/received/lmtp.rb CHANGED
@@ -71,9 +71,12 @@ module Received
71
71
  end
72
72
  when :data
73
73
  if ev == ".\r\n"
74
- @rcpt.size.times {ok}
75
74
  mail = {:from => @from, :rcpt => @rcpt, :body => @body.join}
76
- @conn.mail_received(mail)
75
+ if @conn.mail_received(mail)
76
+ @rcpt.size.times {ok}
77
+ else
78
+ @rcpt.size.times {error_in_processing}
79
+ end
77
80
  :data_received
78
81
  else
79
82
  @body << ev
@@ -123,6 +126,10 @@ module Received
123
126
  emit "500 command unrecognized"
124
127
  end
125
128
 
129
+ def error_in_processing
130
+ emit "451 Requested action aborted: local error in processing"
131
+ end
132
+
126
133
  def emit(str)
127
134
  @conn.send_data "#{str}\r\n"
128
135
  # return nil, so there won't be implicit state transition
@@ -1,3 +1,3 @@
1
1
  module Received
2
- VERSION = "0.2.0"
2
+ VERSION = "0.3.0"
3
3
  end
data/spec/lmtp_spec.rb CHANGED
@@ -5,33 +5,55 @@ describe Received::LMTP do
5
5
  before :each do
6
6
  @mock = mock 'conn'
7
7
  @mock.should_receive(:send_data).with("220 localhost LMTP server ready\r\n")
8
- @mock.stub!(:logger).and_return(Logger.new($stderr))
8
+ logger = Logger.new($stderr)
9
+ @mock.stub!(:logger).and_return(logger)
9
10
  @mock.logger.debug "*** Starting test ***"
10
11
  @proto = Received::LMTP.new(@mock)
11
12
  @proto.start!
12
13
  end
13
14
 
14
- it "does full receive flow" do
15
- @mock.should_receive(:send_data).with("250-localhost\r\n")
16
- @mock.should_receive(:send_data).with("250-8BITMIME\r\n250 PIPELINING\r\n")
17
- @mock.should_receive(:send_data).with("250 OK\r\n").exactly(3).times
18
- @mock.should_receive(:send_data).with("354 End data with <CR><LF>.<CR><LF>\r\n")
19
- @mock.should_receive(:send_data).with("250 OK\r\n").exactly(2).times
20
- @mock.should_receive(:send_data).with("221 Bye\r\n")
21
- body = "Subject: spec\r\nspec\r\n"
22
- @mock.should_receive(:mail_received).with({
23
- :from => 'spec1@example.com',
24
- :rcpt => ['spec2@example.com', 'spec3@example.com'],
25
- :body => body
26
- })
27
- @mock.should_receive(:close_connection_after_writing)
28
-
29
- ["LHLO", "MAIL FROM:<spec1@example.com>", "RCPT TO:<spec2@example.com>",
30
- "RCPT TO:<spec3@example.com>", "DATA", "#{body}.", "QUIT"].each do |line|
31
- @mock.logger.debug "client: #{line}"
32
- @proto.on_data(line + "\r\n")
15
+ describe "Full flow" do
16
+ let(:body) { "Subject: spec\r\nspec\r\n" }
17
+
18
+ def begin_flow!
19
+ ["LHLO", "MAIL FROM:<spec1@example.com>", "RCPT TO:<spec2@example.com>",
20
+ "RCPT TO:<spec3@example.com>", "DATA", "#{body}.", "QUIT"].each do |line|
21
+ @mock.logger.debug "client: #{line}"
22
+ @proto.on_data(line + "\r\n")
23
+ end
33
24
  end
34
25
 
26
+ def common_expectations!
27
+ @mock.should_receive(:send_data).with("250-localhost\r\n")
28
+ @mock.should_receive(:send_data).with("250-8BITMIME\r\n250 PIPELINING\r\n")
29
+ @mock.should_receive(:send_data).with("250 OK\r\n").exactly(3).times
30
+ @mock.should_receive(:send_data).with("354 End data with <CR><LF>.<CR><LF>\r\n")
31
+ end
32
+
33
+ it "receives mail" do
34
+ common_expectations!
35
+ @mock.should_receive(:send_data).with("250 OK\r\n").exactly(2).times
36
+ @mock.should_receive(:send_data).with("221 Bye\r\n")
37
+ @mock.should_receive(:mail_received).with({
38
+ :from => 'spec1@example.com',
39
+ :rcpt => ['spec2@example.com', 'spec3@example.com'],
40
+ :body => body
41
+ }).and_return(true)
42
+ @mock.should_receive(:close_connection_after_writing)
43
+
44
+ begin_flow!
45
+ end
46
+
47
+
48
+ it "returns error when it cannot save email" do
49
+ common_expectations!
50
+ @mock.should_receive(:mail_received).once.and_return(false)
51
+ @mock.should_receive(:send_data).with(/451/).exactly(2).times
52
+ @mock.should_receive(:send_data).with("221 Bye\r\n")
53
+ @mock.should_receive(:close_connection_after_writing)
54
+
55
+ begin_flow!
56
+ end
35
57
  end
36
58
 
37
59
  it "parses multiline" do
metadata CHANGED
@@ -1,12 +1,8 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: received
3
3
  version: !ruby/object:Gem::Version
4
- prerelease: false
5
- segments:
6
- - 0
7
- - 2
8
- - 0
9
- version: 0.2.0
4
+ prerelease:
5
+ version: 0.3.0
10
6
  platform: ruby
11
7
  authors:
12
8
  - Roman Shterenzon
@@ -14,8 +10,7 @@ autorequire:
14
10
  bindir: bin
15
11
  cert_chain: []
16
12
 
17
- date: 2011-06-02 00:00:00 +03:00
18
- default_executable:
13
+ date: 2011-09-13 00:00:00 Z
19
14
  dependencies:
20
15
  - !ruby/object:Gem::Dependency
21
16
  name: daemons
@@ -25,8 +20,6 @@ dependencies:
25
20
  requirements:
26
21
  - - ">="
27
22
  - !ruby/object:Gem::Version
28
- segments:
29
- - 0
30
23
  version: "0"
31
24
  type: :runtime
32
25
  version_requirements: *id001
@@ -38,8 +31,6 @@ dependencies:
38
31
  requirements:
39
32
  - - ">="
40
33
  - !ruby/object:Gem::Version
41
- segments:
42
- - 0
43
34
  version: "0"
44
35
  type: :runtime
45
36
  version_requirements: *id002
@@ -51,10 +42,6 @@ dependencies:
51
42
  requirements:
52
43
  - - ~>
53
44
  - !ruby/object:Gem::Version
54
- segments:
55
- - 1
56
- - 3
57
- - 0
58
45
  version: 1.3.0
59
46
  type: :runtime
60
47
  version_requirements: *id003
@@ -66,10 +53,6 @@ dependencies:
66
53
  requirements:
67
54
  - - ~>
68
55
  - !ruby/object:Gem::Version
69
- segments:
70
- - 1
71
- - 3
72
- - 0
73
56
  version: 1.3.0
74
57
  type: :runtime
75
58
  version_requirements: *id004
@@ -100,7 +83,6 @@ files:
100
83
  - received.gemspec
101
84
  - spec/lmtp_spec.rb
102
85
  - spec/spec_helper.rb
103
- has_rdoc: true
104
86
  homepage: ""
105
87
  licenses: []
106
88
 
@@ -114,21 +96,17 @@ required_ruby_version: !ruby/object:Gem::Requirement
114
96
  requirements:
115
97
  - - ">="
116
98
  - !ruby/object:Gem::Version
117
- segments:
118
- - 0
119
99
  version: "0"
120
100
  required_rubygems_version: !ruby/object:Gem::Requirement
121
101
  none: false
122
102
  requirements:
123
103
  - - ">="
124
104
  - !ruby/object:Gem::Version
125
- segments:
126
- - 0
127
105
  version: "0"
128
106
  requirements: []
129
107
 
130
108
  rubyforge_project:
131
- rubygems_version: 1.3.7
109
+ rubygems_version: 1.8.10
132
110
  signing_key:
133
111
  specification_version: 3
134
112
  summary: Receive mail from Postfix and store it somewhere