mailhandler 1.0.36 → 1.0.37
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +2 -2
- data/Rakefile +2 -2
- data/lib/mailhandler.rb +13 -37
- data/lib/mailhandler/errors.rb +1 -5
- data/lib/mailhandler/receiver.rb +4 -22
- data/lib/mailhandler/receiving/base.rb +16 -45
- data/lib/mailhandler/receiving/filelist/base.rb +25 -49
- data/lib/mailhandler/receiving/filelist/filter/base.rb +10 -52
- data/lib/mailhandler/receiving/filelist/filter/email.rb +4 -44
- data/lib/mailhandler/receiving/folder.rb +16 -54
- data/lib/mailhandler/receiving/imap.rb +34 -78
- data/lib/mailhandler/receiving/mail.rb +5 -19
- data/lib/mailhandler/receiving/notification/console.rb +2 -18
- data/lib/mailhandler/receiving/notification/email.rb +5 -28
- data/lib/mailhandler/receiving/notification/email/content.rb +9 -20
- data/lib/mailhandler/receiving/notification/email/states.rb +1 -36
- data/lib/mailhandler/receiving/observer.rb +5 -16
- data/lib/mailhandler/sender.rb +2 -14
- data/lib/mailhandler/sending/api.rb +1 -7
- data/lib/mailhandler/sending/api_batch.rb +1 -13
- data/lib/mailhandler/sending/base.rb +1 -13
- data/lib/mailhandler/sending/smtp.rb +20 -22
- data/lib/mailhandler/version.rb +2 -2
- data/mailhandler.gemspec +14 -17
- data/readme.md +33 -8
- data/spec/spec_helper.rb +1 -5
- data/spec/unit/mailhandler/receiver_spec.rb +8 -30
- data/spec/unit/mailhandler/receiving/base_spec.rb +4 -14
- data/spec/unit/mailhandler/receiving/folder_spec.rb +61 -155
- data/spec/unit/mailhandler/receiving/imap_spec.rb +18 -42
- data/spec/unit/mailhandler/receiving/notification/console_spec.rb +6 -16
- data/spec/unit/mailhandler/receiving/notification/email/content_spec.rb +10 -44
- data/spec/unit/mailhandler/receiving/notification/email_spec.rb +9 -15
- data/spec/unit/mailhandler/sender_spec.rb +12 -23
- data/spec/unit/mailhandler/sending/sender_api_batch_spec.rb +7 -19
- data/spec/unit/mailhandler/sending/sender_api_spec.rb +4 -14
- data/spec/unit/mailhandler/sending/sender_smtp_spec.rb +24 -6
- data/spec/unit/mailhandler_spec.rb +33 -25
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8f4daed68e55b824dbcad5321f41fd3aa4374769
|
4
|
+
data.tar.gz: 12934cc4aa8d94d6647c2049291f40910b939a7b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5f3f94f0de2600cc2d99d8cfeeb43f3b33ec74e5917a0a045b103f0f2c63ccb52ecdcc1bd0a77300ea13de5f8820d834c679edfc6e955a01754d2dcf72a95f09
|
7
|
+
data.tar.gz: 23355aac8afd26e73c3f04b34a75dd65d823e78cdf8f95cce040df3482a5cf1f14c18d276726b42df23d86eb626a44b58bd26c716cc42fd65b3de2c9fb0caf33
|
data/Gemfile
CHANGED
data/Rakefile
CHANGED
@@ -1,3 +1,3 @@
|
|
1
|
-
require
|
1
|
+
require 'bundler/gem_tasks'
|
2
2
|
require 'rspec/core/rake_task'
|
3
|
-
RSpec::Core::RakeTask.new(:default)
|
3
|
+
RSpec::Core::RakeTask.new(:default)
|
data/lib/mailhandler.rb
CHANGED
@@ -8,31 +8,26 @@ require_relative 'mailhandler/errors'
|
|
8
8
|
# Main MailHandler class, for creating sender and receiver objects.
|
9
9
|
# Sender objects for sending emails, receiver objects for searching and receiving emails.
|
10
10
|
module MailHandler
|
11
|
-
|
12
|
-
extend self
|
11
|
+
module_function
|
13
12
|
|
14
13
|
# sending accessor
|
15
14
|
# @return [Object] - sender for sending emails
|
16
15
|
def sender(type = :postmark_api)
|
17
|
-
|
18
16
|
handler = Handler.new
|
19
17
|
handler.init_sender(type)
|
20
18
|
yield(handler.sender.dispatcher) if block_given?
|
21
19
|
|
22
20
|
handler.sender
|
23
|
-
|
24
21
|
end
|
25
22
|
|
26
23
|
# receiving accessor
|
27
24
|
# @return [Object] - receiver for searching emails
|
28
25
|
def receiver(type = :folder, notifications = [])
|
29
|
-
|
30
26
|
handler = Handler.new
|
31
27
|
handler.init_receiver(type, notifications)
|
32
28
|
yield(handler.receiver.checker) if block_given?
|
33
29
|
|
34
30
|
handler.receiver
|
35
|
-
|
36
31
|
end
|
37
32
|
|
38
33
|
# Holder for receiving and sending handlers
|
@@ -40,92 +35,73 @@ module MailHandler
|
|
40
35
|
# @param [Receiving::Class] receiver
|
41
36
|
# @param [Sending::Class] sender
|
42
37
|
def handler(receiver, sender)
|
43
|
-
|
44
38
|
handler = Handler.new
|
45
39
|
handler.handler(receiver, sender)
|
46
|
-
|
47
40
|
end
|
48
41
|
|
49
42
|
# main handler class for creating sender, receiver handlers
|
50
43
|
class Handler
|
51
|
-
|
52
44
|
attr_accessor :sender,
|
53
45
|
:receiver
|
54
46
|
|
55
47
|
def init_sender(type = :postmark_api)
|
56
|
-
|
57
48
|
verify_type(type, SENDER_TYPES)
|
58
49
|
@sender = MailHandler::Sender.new(SENDER_TYPES[type].new)
|
59
|
-
|
60
50
|
end
|
61
51
|
|
62
|
-
|
63
52
|
def init_receiver(type = :folder, notifications = [])
|
64
|
-
|
65
53
|
verify_type(type, CHECKER_TYPES)
|
66
54
|
@receiver = MailHandler::Receiver.new(CHECKER_TYPES[type].new)
|
67
55
|
add_receiving_notifications(@receiver, notifications)
|
68
56
|
@receiver
|
69
|
-
|
70
57
|
end
|
71
58
|
|
72
59
|
def handler(sender, receiver)
|
73
|
-
|
74
60
|
handler = new
|
75
61
|
handler.sender = sender
|
76
62
|
handler.receiver = receiver
|
77
63
|
handler
|
78
|
-
|
79
64
|
end
|
80
65
|
|
81
66
|
private
|
82
67
|
|
83
|
-
# Add notifications, in case email receiving is delayed.
|
68
|
+
# Add notifications, in case email receiving is delayed.
|
84
69
|
# When email is delayed, email notification can be sent or console status update.
|
85
70
|
#
|
86
71
|
# @param [Receiving::Object] receiver
|
87
72
|
# @param [Array<Receiving::Notification::Class>] notifications
|
88
73
|
def add_receiving_notifications(receiver, notifications)
|
89
|
-
|
90
74
|
if (notifications - NOTIFICATION_TYPES.keys).empty?
|
91
75
|
|
92
76
|
notifications.each { |n| receiver.add_observer(NOTIFICATION_TYPES[n].new) }
|
93
77
|
|
94
78
|
end
|
95
|
-
|
96
79
|
end
|
97
80
|
|
98
81
|
def verify_type(type, types)
|
99
|
-
|
100
|
-
raise MailHandler::TypeError, "Unknown type - #{type}, possible options: #{types.keys}." unless types.keys.include? type
|
101
|
-
|
82
|
+
raise MailHandler::TypeError, "Unknown type - #{type}, possible options: #{types.keys}." unless types.key?(type)
|
102
83
|
end
|
103
84
|
|
104
85
|
CHECKER_TYPES = {
|
105
86
|
|
106
|
-
|
107
|
-
|
87
|
+
folder: Receiving::FolderChecker,
|
88
|
+
imap: Receiving::IMAPChecker
|
108
89
|
|
109
|
-
}
|
90
|
+
}.freeze
|
110
91
|
|
111
92
|
SENDER_TYPES = {
|
112
93
|
|
113
|
-
|
114
|
-
|
115
|
-
|
94
|
+
postmark_api: Sending::PostmarkAPISender,
|
95
|
+
postmark_batch_api: Sending::PostmarkBatchAPISender,
|
96
|
+
smtp: Sending::SMTPSender
|
116
97
|
|
117
|
-
}
|
98
|
+
}.freeze
|
118
99
|
|
119
100
|
NOTIFICATION_TYPES = {
|
120
101
|
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
}
|
102
|
+
console: Receiving::Notification::Console,
|
103
|
+
email: Receiving::Notification::Email
|
125
104
|
|
105
|
+
}.freeze
|
126
106
|
end
|
127
|
-
|
128
107
|
end
|
129
|
-
|
130
|
-
|
131
|
-
|
data/lib/mailhandler/errors.rb
CHANGED
@@ -1,16 +1,12 @@
|
|
1
1
|
module MailHandler
|
2
|
-
|
3
2
|
class Error < StandardError
|
4
|
-
|
5
3
|
def initialize(message = nil)
|
6
4
|
super(message)
|
7
5
|
end
|
8
|
-
|
9
6
|
end
|
10
7
|
|
11
8
|
class UnknownError < Error; end
|
12
9
|
class TypeError < Error; end
|
13
10
|
class FileError < Error; end
|
14
11
|
class InterfaceError < Error; end
|
15
|
-
|
16
|
-
end
|
12
|
+
end
|
data/lib/mailhandler/receiver.rb
CHANGED
@@ -4,9 +4,7 @@ require_relative 'receiving/observer'
|
|
4
4
|
require_relative 'receiving/mail.rb'
|
5
5
|
|
6
6
|
module MailHandler
|
7
|
-
|
8
7
|
class Receiver
|
9
|
-
|
10
8
|
include Receiving::Observer
|
11
9
|
|
12
10
|
attr_accessor :checker,
|
@@ -15,10 +13,8 @@ module MailHandler
|
|
15
13
|
:search_frequency
|
16
14
|
|
17
15
|
module DEFAULTS
|
18
|
-
|
19
16
|
MAX_SEARCH_DURATION = 240 # maximum time for search to last in [seconds]
|
20
17
|
SEARCH_FREQUENCY = 0.5 # how frequently to check for email in inbox [seconds]
|
21
|
-
|
22
18
|
end
|
23
19
|
|
24
20
|
# @param [Hash] - search options
|
@@ -31,18 +27,15 @@ module MailHandler
|
|
31
27
|
# @param [boolean] - result of search
|
32
28
|
# @param [Mail] - first email found
|
33
29
|
# @param [Array] - all emails found
|
34
|
-
Search = Struct.new(
|
30
|
+
Search = Struct.new(:options, :started_at, :finished_at, :duration, :max_duration, :result, :email, :emails)
|
35
31
|
|
36
32
|
def initialize(checker)
|
37
|
-
|
38
33
|
@checker = checker
|
39
34
|
@max_search_duration = DEFAULTS::MAX_SEARCH_DURATION
|
40
35
|
@search_frequency = DEFAULTS::SEARCH_FREQUENCY
|
41
|
-
|
42
36
|
end
|
43
37
|
|
44
38
|
def find_email(options)
|
45
|
-
|
46
39
|
init_search_details(options)
|
47
40
|
checker.start
|
48
41
|
|
@@ -58,40 +51,29 @@ module MailHandler
|
|
58
51
|
|
59
52
|
notify_observers(search)
|
60
53
|
checker.search_result
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
checker.stop
|
65
|
-
|
54
|
+
ensure
|
55
|
+
checker.stop
|
66
56
|
end
|
67
57
|
|
68
58
|
private
|
69
59
|
|
70
60
|
def init_search_details(options)
|
71
|
-
|
72
61
|
@search = Search.new
|
73
62
|
@search.options = options
|
74
63
|
@search.started_at = Time.now
|
75
64
|
@search.max_duration = @max_search_duration
|
76
|
-
|
77
65
|
end
|
78
66
|
|
79
67
|
def update_search_details
|
80
|
-
|
81
68
|
search.finished_at = Time.now
|
82
69
|
search.duration = search.finished_at - search.started_at
|
83
70
|
search.result = checker.search_result
|
84
71
|
search.emails = checker.found_emails
|
85
72
|
search.email = search.emails.first
|
86
|
-
|
87
73
|
end
|
88
74
|
|
89
75
|
def search_time_expired?
|
90
|
-
|
91
76
|
(Time.now - search.started_at) > @max_search_duration
|
92
|
-
|
93
77
|
end
|
94
|
-
|
95
78
|
end
|
96
|
-
|
97
|
-
end
|
79
|
+
end
|
@@ -1,83 +1,64 @@
|
|
1
1
|
require_relative '../errors'
|
2
2
|
|
3
3
|
module MailHandler
|
4
|
-
|
5
4
|
module Receiving
|
6
|
-
|
7
5
|
#
|
8
6
|
# Email receiving checker main class.
|
9
7
|
# @see MailHandler::Receiving::FolderChecker for example for one of implemented checkers.
|
10
8
|
#
|
11
9
|
class Checker
|
12
|
-
|
13
10
|
attr_accessor :search_options,
|
14
11
|
:found_emails,
|
15
12
|
:available_search_options
|
16
13
|
|
17
14
|
def initialize
|
18
|
-
|
19
15
|
@available_search_options = AVAILABLE_SEARCH_OPTIONS
|
20
16
|
set_base_search_options
|
21
17
|
reset_found_emails
|
22
|
-
|
23
18
|
end
|
24
19
|
|
25
|
-
def start
|
26
|
-
|
27
|
-
end
|
20
|
+
def start; end
|
28
21
|
|
29
|
-
def stop
|
30
|
-
|
31
|
-
end
|
32
|
-
|
33
|
-
def find(options)
|
22
|
+
def stop; end
|
34
23
|
|
24
|
+
def find(_options)
|
35
25
|
raise MailHandler::InterfaceError, 'Find interface not implemented.'
|
36
|
-
|
37
26
|
end
|
38
27
|
|
39
28
|
def search_result
|
40
|
-
|
41
29
|
!found_emails.empty?
|
42
|
-
|
43
30
|
end
|
44
31
|
|
45
32
|
def reset_found_emails
|
46
|
-
|
47
33
|
@found_emails = []
|
48
|
-
|
49
34
|
end
|
50
35
|
|
51
36
|
private
|
52
37
|
|
53
|
-
AVAILABLE_SEARCH_OPTIONS = [
|
38
|
+
AVAILABLE_SEARCH_OPTIONS = %i[
|
54
39
|
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
]
|
40
|
+
by_subject
|
41
|
+
by_content
|
42
|
+
since
|
43
|
+
before
|
44
|
+
by_recipient
|
45
|
+
count
|
46
|
+
archive
|
47
|
+
fast_check
|
48
|
+
].freeze
|
65
49
|
|
66
50
|
protected
|
67
51
|
|
68
52
|
def verify_and_set_search_options(options)
|
69
|
-
|
70
53
|
validate_used_options(options)
|
71
54
|
validate_option_values(options)
|
72
55
|
|
73
56
|
set_base_search_options
|
74
57
|
add_additional_search_options(options)
|
75
58
|
reset_found_emails
|
76
|
-
|
77
59
|
end
|
78
60
|
|
79
61
|
def validate_option_values(options)
|
80
|
-
|
81
62
|
if options[:since]
|
82
63
|
|
83
64
|
raise MailHandler::Error, "Incorrect option options[:since]=#{options[:since]}." unless options[:since].is_a? Time
|
@@ -87,13 +68,13 @@ module MailHandler
|
|
87
68
|
unless options[:count].nil?
|
88
69
|
|
89
70
|
count = options[:count]
|
90
|
-
raise MailHandler::Error, "Incorrect option options[:count]=#{options[:count]}." if count < 0
|
71
|
+
raise MailHandler::Error, "Incorrect option options[:count]=#{options[:count]}." if (count < 0) || (count > 2000)
|
91
72
|
|
92
73
|
end
|
93
74
|
|
94
75
|
if options[:archive]
|
95
76
|
|
96
|
-
raise MailHandler::Error, "Incorrect option options[:archive]=#{options[:archive]}." unless options[:archive] == true
|
77
|
+
raise MailHandler::Error, "Incorrect option options[:archive]=#{options[:archive]}." unless (options[:archive] == true) || (options[:archive] == false)
|
97
78
|
|
98
79
|
end
|
99
80
|
|
@@ -102,32 +83,22 @@ module MailHandler
|
|
102
83
|
raise MailHandler::Error, "Incorrect option options[:by_recipient]=#{options[:by_recipient]}." unless options[:by_recipient].is_a?(Hash)
|
103
84
|
|
104
85
|
end
|
105
|
-
|
106
86
|
end
|
107
87
|
|
108
88
|
def validate_used_options(options)
|
109
|
-
|
110
89
|
unless (options.keys - available_search_options).empty?
|
111
90
|
raise MailHandler::Error, "#{(options.keys - available_search_options)} - Incorrect search option values, options are #{available_search_options}."
|
112
91
|
end
|
113
|
-
|
114
92
|
end
|
115
93
|
|
116
94
|
def set_base_search_options
|
117
|
-
|
118
95
|
# Default number of email results to return, and whether to archive emails.
|
119
|
-
@search_options = {:
|
120
|
-
|
96
|
+
@search_options = { count: 50, archive: false }
|
121
97
|
end
|
122
98
|
|
123
99
|
def add_additional_search_options(options)
|
124
|
-
|
125
100
|
@search_options = @search_options.merge options
|
126
|
-
|
127
101
|
end
|
128
|
-
|
129
102
|
end
|
130
|
-
|
131
103
|
end
|
132
|
-
|
133
104
|
end
|
@@ -4,25 +4,17 @@ require 'fileutils'
|
|
4
4
|
# Patterns to be used can be checked here: http://ruby-doc.org/core-1.9.3/Dir.html
|
5
5
|
|
6
6
|
module MailHandler
|
7
|
-
|
8
7
|
module Receiving
|
9
|
-
|
10
8
|
module FileHandling
|
11
|
-
|
12
9
|
# if file exists, execute file operation, otherwise return default return value when it doesn't
|
13
|
-
def access_file(file, default_return = false
|
14
|
-
|
15
|
-
if File.exists? file
|
10
|
+
def access_file(file, default_return = false)
|
11
|
+
if File.exist? file
|
16
12
|
|
17
13
|
begin
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
rescue => e
|
22
|
-
|
23
|
-
raise e if File.exists? file
|
14
|
+
yield
|
15
|
+
rescue StandardError => e
|
16
|
+
raise e if File.exist? file
|
24
17
|
default_return
|
25
|
-
|
26
18
|
end
|
27
19
|
|
28
20
|
else
|
@@ -30,69 +22,53 @@ module MailHandler
|
|
30
22
|
default_return
|
31
23
|
|
32
24
|
end
|
33
|
-
|
34
25
|
end
|
35
|
-
|
36
26
|
end
|
37
27
|
|
38
28
|
class FileList
|
39
|
-
|
40
29
|
include FileHandling
|
41
30
|
|
42
31
|
def get(pattern)
|
43
|
-
|
44
32
|
Dir.glob(pattern)
|
45
|
-
|
46
33
|
end
|
47
34
|
|
48
35
|
def sort(files)
|
49
|
-
|
50
36
|
swapped = true
|
51
37
|
j = 0
|
52
38
|
|
53
|
-
while swapped
|
39
|
+
while swapped
|
54
40
|
|
55
41
|
swapped = false
|
56
|
-
j+=1
|
42
|
+
j += 1
|
57
43
|
|
58
44
|
(files.size - j).times do |i|
|
59
|
-
|
60
45
|
file1 = access_file(files[i], false) { File.new(files[i]).ctime }
|
61
|
-
file2 = access_file(files[i+1], false) { File.new(files[i+1]).ctime }
|
62
|
-
|
63
|
-
if file1 && file2 && file1 < file2
|
64
|
-
tmp = files[i]
|
65
|
-
files[i] = files[i + 1]
|
66
|
-
files[i + 1] = tmp
|
67
|
-
swapped = true
|
68
|
-
|
69
|
-
end
|
46
|
+
file2 = access_file(files[i + 1], false) { File.new(files[i + 1]).ctime }
|
70
47
|
|
48
|
+
next unless file1 && file2 && file1 < file2
|
49
|
+
tmp = files[i]
|
50
|
+
files[i] = files[i + 1]
|
51
|
+
files[i + 1] = tmp
|
52
|
+
swapped = true
|
71
53
|
end
|
72
54
|
|
73
55
|
end
|
74
56
|
|
75
57
|
files
|
76
|
-
|
77
58
|
end
|
78
|
-
|
79
59
|
end
|
80
|
-
|
81
60
|
end
|
82
|
-
|
83
61
|
end
|
84
62
|
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
FileList.
|
90
|
-
FileList::Filter::
|
91
|
-
FileList::Filter::
|
92
|
-
FileList::Filter::
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
=end
|
63
|
+
#
|
64
|
+
# TEST EXAMPLE
|
65
|
+
#
|
66
|
+
# FileList.get('*.*')
|
67
|
+
# FileList::Filter::ByEmailSubject.new(files,'subject').get
|
68
|
+
# FileList::Filter::ByEmailContent.new(files,'content').get
|
69
|
+
# FileList::Filter::ByEmailDate.new(files, date).get
|
70
|
+
# FileList::Filter::ByEmailRecipient.new(files, recipient).get
|
71
|
+
#
|
72
|
+
# f = FileList::Filter::ByEmailSubject.new(FileList.get("*.*"), "binding")
|
73
|
+
# puts f.get
|
74
|
+
#
|