mail_daemon 0.0.5
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.
- checksums.yaml +7 -0
- data/.gitignore +23 -0
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/Gemfile +6 -0
- data/LICENSE +22 -0
- data/LICENSE.txt +22 -0
- data/README.md +51 -0
- data/Rakefile +2 -0
- data/bin/mail_daemon +22 -0
- data/config.yml +27 -0
- data/lib/mail_daemon.rb +71 -0
- data/lib/mail_daemon/email_body_parser.rb +28 -0
- data/lib/mail_daemon/email_handler.rb +109 -0
- data/lib/mail_daemon/email_watcher.rb +155 -0
- data/lib/mail_daemon/encryption.rb +42 -0
- data/lib/mail_daemon/helpers.rb +16 -0
- data/lib/mail_daemon/imap/connection.rb +155 -0
- data/lib/mail_daemon/imap/statuses.rb +17 -0
- data/lib/mail_daemon/imap/watcher.rb +42 -0
- data/lib/mail_daemon/imap_watcher.rb +80 -0
- data/lib/mail_daemon/version.rb +3 -0
- data/lib/public/custom.css +19 -0
- data/lib/public/dashboard.css +105 -0
- data/lib/server.rb +6 -0
- data/lib/views/settings.erb +113 -0
- data/lib/views/stats.erb +100 -0
- data/mail_daemon.gemspec +35 -0
- data/test/lib/order2cb/order_test.rb +20 -0
- data/test/lib/order2cb/version_test.rb +7 -0
- data/test/lib/order2cb_test.rb +25 -0
- data/test/test_helper.rb +3 -0
- metadata +221 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 48feab4732334f1c8c9286c661a700b603ef6189
|
4
|
+
data.tar.gz: 410115f6ee8a2e51c3a46907b5639ceb160c8810
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 6b41e1e61aaca95d8f32e5967b4d2a488dd292f8f211ebb3d33530045121307be75c667026a2a6dab1b1219eb172dfc02efda21a5d482333b7bf06801a9a02ca
|
7
|
+
data.tar.gz: f3458d0f73b2df26d6a119a89680aabc4cb7f8248769c8b46cf04d4eaa8941b6ef9c2d1ad761b4f56dc5031460ef54dbb6e8aa3af87660c4bf5ad5f7c99a3f5c
|
data/.gitignore
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
*.gem
|
2
|
+
*.rbc
|
3
|
+
.bundle
|
4
|
+
.config
|
5
|
+
.yardoc
|
6
|
+
Gemfile.lock
|
7
|
+
InstalledFiles
|
8
|
+
_yardoc
|
9
|
+
coverage
|
10
|
+
doc/
|
11
|
+
lib/bundler/man
|
12
|
+
pkg
|
13
|
+
rdoc
|
14
|
+
spec/reports
|
15
|
+
test/tmp
|
16
|
+
test/version_tmp
|
17
|
+
tmp
|
18
|
+
*.bundle
|
19
|
+
*.so
|
20
|
+
*.o
|
21
|
+
*.a
|
22
|
+
mkmf.log
|
23
|
+
*.swp
|
data/.ruby-gemset
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
mail_daemon
|
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
ruby-2.2.3
|
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2015 EmergeAdapt
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
22
|
+
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2015 Ijonas Kisselbach
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
# mail_daemon
|
2
|
+
|
3
|
+
TODO: Write a gem description
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
gem 'mail_daemon'
|
10
|
+
|
11
|
+
And then execute:
|
12
|
+
|
13
|
+
$ bundle
|
14
|
+
|
15
|
+
Or install it yourself as:
|
16
|
+
|
17
|
+
$ gem install mail_daemon
|
18
|
+
|
19
|
+
## Design
|
20
|
+
|
21
|
+
###Gems
|
22
|
+
|
23
|
+
* mail_room - retrieves mail from multiple mailboxes at once and sends them through sidekiq or an http postback
|
24
|
+
* mail - mail parsing and sending gem
|
25
|
+
* talon - python code to extract the relevant body of the message
|
26
|
+
|
27
|
+
|
28
|
+
### Notes
|
29
|
+
|
30
|
+
* config for office365 smtp needs authentication type 'login' gmail is 'plain'
|
31
|
+
* gmail apps authentication is by ip address only, suggest a feature of being able to host the send daemon on another box
|
32
|
+
|
33
|
+
## Usage
|
34
|
+
|
35
|
+
Ensure the following environment variables are set:
|
36
|
+
|
37
|
+
REDIS_URL=redis://localhost:6379
|
38
|
+
CB_API_ENDPOINT=https://login.caseblocks.com
|
39
|
+
CB_API_TOKEN=...
|
40
|
+
|
41
|
+
And run the daemon from the CLI
|
42
|
+
|
43
|
+
mail_daemon
|
44
|
+
|
45
|
+
## Contributing
|
46
|
+
|
47
|
+
1. Fork it ( https://github.com/[my-github-username]/mail_daemon/fork )
|
48
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
49
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
50
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
51
|
+
5. Create a new Pull Request
|
data/Rakefile
ADDED
data/bin/mail_daemon
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
#!/usr/bin/env ruby -Ilib
|
2
|
+
require 'rubygems'
|
3
|
+
require 'bundler/setup'
|
4
|
+
# Prepares the $LOAD_PATH by adding to it lib directories of the gem and
|
5
|
+
# its dependencies:
|
6
|
+
require 'mail_daemon'
|
7
|
+
require 'ap'
|
8
|
+
|
9
|
+
|
10
|
+
mailboxes = [
|
11
|
+
{:host => "imap.gmail.com", :username => "stewart@emergeadapt.com", :port => 993, :start_tls => true, :password => "junction1", :ssl => true}
|
12
|
+
]
|
13
|
+
|
14
|
+
handler = MailDaemon::Handler.new(:connections => mailboxes)
|
15
|
+
|
16
|
+
handler.start do |message, type|
|
17
|
+
if type == "status_update"
|
18
|
+
puts "#{message[:status][0].upcase}#{message[:status][1..-1]} #{message[:mailbox][:username]}"
|
19
|
+
else
|
20
|
+
ap message
|
21
|
+
end
|
22
|
+
end
|
data/config.yml
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
---
|
2
|
+
:mailboxes:
|
3
|
+
-
|
4
|
+
:email: "stewart@activeinformationdesign.com"
|
5
|
+
:password: "junction1"
|
6
|
+
:name: "inbox"
|
7
|
+
:search_command: 'UNSEEN'
|
8
|
+
:delivery_method: sidekiq
|
9
|
+
:delivery_options:
|
10
|
+
:worker: EmailHandlerWorker
|
11
|
+
-
|
12
|
+
:email: "stewart@emergeadapt.com"
|
13
|
+
:password: "junction1"
|
14
|
+
:name: "inbox"
|
15
|
+
:search_command: 'UNSEEN'
|
16
|
+
:delivery_method: sidekiq
|
17
|
+
:delivery_options:
|
18
|
+
:worker: EmailHandlerWorker
|
19
|
+
-
|
20
|
+
:email: "stewartmckee@emergeadapttest.onmicrosoft.com"
|
21
|
+
:host: "outlook.office365.com"
|
22
|
+
:password: "Katr1n33"
|
23
|
+
:name: "inbox"
|
24
|
+
:search_command: 'UNSEEN'
|
25
|
+
:delivery_method: sidekiq
|
26
|
+
:delivery_options:
|
27
|
+
:worker: EmailHandlerWorker
|
data/lib/mail_daemon.rb
ADDED
@@ -0,0 +1,71 @@
|
|
1
|
+
require_relative 'mail_daemon/version'
|
2
|
+
require_relative 'mail_daemon/helpers'
|
3
|
+
require_relative 'mail_daemon/email_body_parser'
|
4
|
+
require_relative 'mail_daemon/email_handler'
|
5
|
+
require_relative 'mail_daemon/imap/statuses'
|
6
|
+
require_relative 'mail_daemon/imap/connection'
|
7
|
+
require_relative 'mail_daemon/imap/watcher'
|
8
|
+
require_relative 'mail_daemon/encryption'
|
9
|
+
require 'sinatra/base'
|
10
|
+
require 'json'
|
11
|
+
require 'open3'
|
12
|
+
require 'mail'
|
13
|
+
|
14
|
+
include MailDaemon::Helpers
|
15
|
+
|
16
|
+
module MailDaemon
|
17
|
+
class Handler
|
18
|
+
def initialize(options)
|
19
|
+
setup_options(options)
|
20
|
+
default_option :connections, []
|
21
|
+
|
22
|
+
Signal.trap("INT") {
|
23
|
+
Thread.new {self.stop}.join
|
24
|
+
}
|
25
|
+
# Trap `Kill `
|
26
|
+
Signal.trap("TERM") {
|
27
|
+
Thread.new {self.stop}.join
|
28
|
+
}
|
29
|
+
end
|
30
|
+
|
31
|
+
def restart
|
32
|
+
self.stop if self.running?
|
33
|
+
self.reload unless @mailbox_config
|
34
|
+
self.start
|
35
|
+
end
|
36
|
+
|
37
|
+
def running?
|
38
|
+
@watchers && @watchers.detect{|watcher| watcher.running?}
|
39
|
+
end
|
40
|
+
|
41
|
+
# Signal catching
|
42
|
+
def stop
|
43
|
+
@watchers.map{|watcher| watcher.stop}
|
44
|
+
@threads.map{|t| t.kill }
|
45
|
+
end
|
46
|
+
|
47
|
+
def start(&block)
|
48
|
+
@watchers = []
|
49
|
+
|
50
|
+
@options[:connections].each do |mailbox|
|
51
|
+
mailbox[:ssl_options] = {:verify_mode => OpenSSL::SSL::VERIFY_NONE} if mailbox[:ssl]
|
52
|
+
|
53
|
+
puts "Setting up watcher for #{mailbox[:username]}"
|
54
|
+
@watchers << MailDaemon::Imap::Watcher.new(mailbox)
|
55
|
+
end
|
56
|
+
@threads = []
|
57
|
+
@watchers.each do |watcher|
|
58
|
+
@threads << Thread.new do
|
59
|
+
watcher.start do |message|
|
60
|
+
type = message.delete(:type)
|
61
|
+
yield message, type
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
@threads.map{|t| t.join}
|
67
|
+
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'open3'
|
2
|
+
|
3
|
+
module MailDaemon
|
4
|
+
class EmailBodyParser
|
5
|
+
def self.parse(text, type="text/plain")
|
6
|
+
|
7
|
+
data_hash = {:body => text, :type => type}
|
8
|
+
|
9
|
+
json_hash = data_hash.to_json
|
10
|
+
|
11
|
+
stdin, stdout, stderr, wait_thr = Open3.popen3('python', '/Users/stewartmckee/code/talon/test.py')
|
12
|
+
stdin.write(json_hash)
|
13
|
+
stdin.close
|
14
|
+
result = stdout.read
|
15
|
+
stdout.close
|
16
|
+
error = stderr.read
|
17
|
+
stderr.close
|
18
|
+
exit_code = wait_thr.value
|
19
|
+
if exit_code == 0
|
20
|
+
result
|
21
|
+
else
|
22
|
+
puts result
|
23
|
+
raise error
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,109 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
require 'mail'
|
3
|
+
require_relative "email_body_parser"
|
4
|
+
require 'nokogiri'
|
5
|
+
require 'sanitize'
|
6
|
+
|
7
|
+
module MailDaemon
|
8
|
+
class EmailHandler
|
9
|
+
def initialize(options)
|
10
|
+
@options = options
|
11
|
+
@email = Mail.read_from_string(options[:inbound_message])
|
12
|
+
|
13
|
+
puts "Handling inbound email from #{@email.from}"
|
14
|
+
|
15
|
+
if @email.multipart?
|
16
|
+
@email.parts.each do |part|
|
17
|
+
content_type = part.content_type.split(";")[0]
|
18
|
+
if content_type[0..3] == "text"
|
19
|
+
if content_type == "text/html"
|
20
|
+
@html_body = part.body.decoded.force_encoding("ASCII-8BIT").encode('UTF-8', undef: :replace, replace: '')
|
21
|
+
elsif content_type == "text/plain"
|
22
|
+
@text_body = part.body.decoded.force_encoding("ASCII-8BIT").encode('UTF-8', undef: :replace, replace: '')
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
else
|
27
|
+
@text_body = @email.body.decoded.force_encoding("ASCII-8BIT").encode('UTF-8', undef: :replace, replace: '')
|
28
|
+
end
|
29
|
+
|
30
|
+
@body = @html_body || @text_body
|
31
|
+
end
|
32
|
+
|
33
|
+
def generate_message_hash
|
34
|
+
|
35
|
+
message_hash = {
|
36
|
+
"from" => @email.from,
|
37
|
+
"to" => @email.to,
|
38
|
+
"subject" => @email.subject,
|
39
|
+
"body" => @body,
|
40
|
+
"attachements" => prepare_attachments,
|
41
|
+
"metadata" => fetch_metadata
|
42
|
+
}
|
43
|
+
message_hash.delete(:inbound_message)
|
44
|
+
message_hash
|
45
|
+
end
|
46
|
+
|
47
|
+
def fetch_metadata
|
48
|
+
fetch_fingerprints.merge({
|
49
|
+
"references" => references
|
50
|
+
})
|
51
|
+
end
|
52
|
+
|
53
|
+
def references
|
54
|
+
@email.header["References"] ? @email.header["References"].field.element.message_ids : []
|
55
|
+
end
|
56
|
+
|
57
|
+
def fetch_fingerprints
|
58
|
+
previous_id = references.last
|
59
|
+
match = /(.*?)\.(.*?)@emergeadapt.com/.match(previous_id)
|
60
|
+
if match
|
61
|
+
if match[2] == "case"
|
62
|
+
{"case_id" => match[1]}
|
63
|
+
else
|
64
|
+
{"message_id" => match[1]}
|
65
|
+
end
|
66
|
+
else
|
67
|
+
{}
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def prepare_attachments
|
72
|
+
attachments = []
|
73
|
+
@email.attachments.each do | attachment |
|
74
|
+
filename = attachment.filename
|
75
|
+
random_tag = Random.rand(100000000000)
|
76
|
+
attachment_folder = File.join(["/", "tmp", "caseblocks", @options[:mailbox][:account_code], "attachments"])
|
77
|
+
FileUtils::mkdir_p(attachment_folder)
|
78
|
+
file_path = File.join([attachment_folder, "#{random_tag}.#{filename}"])
|
79
|
+
File.open(file_path, "w+b", 0644) {|f| f.write attachment.body.decoded}
|
80
|
+
attachments << {
|
81
|
+
"filename" => attachment.filename,
|
82
|
+
"filepath" => file_path
|
83
|
+
}
|
84
|
+
end
|
85
|
+
attachments
|
86
|
+
end
|
87
|
+
|
88
|
+
|
89
|
+
def content_type
|
90
|
+
@html_body.nil? ? "text/plain" : "text/html"
|
91
|
+
end
|
92
|
+
|
93
|
+
def sanitize!
|
94
|
+
@body = Sanitize.fragment(@body, Sanitize::Config::RELAXED)
|
95
|
+
end
|
96
|
+
|
97
|
+
def clean_replies!
|
98
|
+
@body = MailDaemon::EmailBodyParser.parse(@body, content_type)
|
99
|
+
end
|
100
|
+
|
101
|
+
def queue!
|
102
|
+
$redis
|
103
|
+
end
|
104
|
+
|
105
|
+
def body
|
106
|
+
@body
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
@@ -0,0 +1,155 @@
|
|
1
|
+
require 'redis'
|
2
|
+
require 'ap'
|
3
|
+
require 'mysql2'
|
4
|
+
|
5
|
+
module MailDaemon
|
6
|
+
class EmailWatcher
|
7
|
+
|
8
|
+
def initialize
|
9
|
+
|
10
|
+
raise "REDIS_URL environment variable is required (eg redis://localhost:6739)" unless ENV["REDIS_URL"]
|
11
|
+
raise "MYSQL_HOST environment variable is required" unless ENV["MYSQL_HOST"]
|
12
|
+
raise "MYSQL_DATABASE environment variable is required" unless ENV["MYSQL_DATABASE"]
|
13
|
+
raise "MYSQL_USERNAME environment variable is required" unless ENV["MYSQL_USERNAME"]
|
14
|
+
raise "MYSQL_PASSWORD environment variable is required" unless ENV["MYSQL_PASSWORD"]
|
15
|
+
|
16
|
+
ENV["MYSQL_PASSWORD"] = "" unless ENV["MYSQL_PASSWORD"]
|
17
|
+
ENV["MYSQL_PORT"] = "3306"
|
18
|
+
|
19
|
+
redis_url = URI.parse(ENV["REDIS_URL"])
|
20
|
+
|
21
|
+
$redis = Redis.new(:host => redis_url.host, :port => redis_url.port)
|
22
|
+
|
23
|
+
Signal.trap("INT") {
|
24
|
+
Thread.new {self.stop}.join
|
25
|
+
}
|
26
|
+
# Trap `Kill `
|
27
|
+
Signal.trap("TERM") {
|
28
|
+
Thread.new {self.stop}.join
|
29
|
+
}
|
30
|
+
|
31
|
+
|
32
|
+
|
33
|
+
start
|
34
|
+
end
|
35
|
+
|
36
|
+
def configuration
|
37
|
+
mailboxes = []
|
38
|
+
mysql_client do |mysql|
|
39
|
+
statement = mysql.prepare("SELECT case_blocks_email_accounts.id, case_blocks_accounts.nickname, case_blocks_email_accounts.imap_username, case_blocks_email_accounts.imap_encrypted_password, case_blocks_email_accounts.imap_host, case_blocks_email_accounts.imap_port, case_blocks_email_accounts.imap_ssl, case_blocks_email_accounts.imap_start_tls, case_blocks_email_accounts.imap_folder_name, case_blocks_email_accounts.imap_search_command, case_blocks_email_accounts.imap_messages_processed, case_blocks_email_accounts.imap_last_processed_at FROM case_blocks_email_accounts JOIN case_blocks_accounts ON case_blocks_email_accounts.account_id = case_blocks_accounts.id where imap_enabled=1")
|
40
|
+
result = statement.execute()
|
41
|
+
result.each do |row|
|
42
|
+
ssl_options = row["imap_ssl"]==1 ? {:verify_mode => OpenSSL::SSL::VERIFY_NONE} : false
|
43
|
+
decrypted_password = Encryption.new.decrypt(row["imap_encrypted_password"])
|
44
|
+
mailboxes << {:id => row["id"], :account_code => row["nickname"], :username => row["imap_username"], :host => row["imap_host"], :port => row["imap_port"], :password => decrypted_password, :ssl_options => ssl_options, :start_tls => row["imap_start_tls"]==1, :name => row["imap_folder_nam"], :search_command => row["imap_search_command"], :message_count => row["imap_messages_processed"], :last_delivered_at => row["imap_last_processed_at"]}
|
45
|
+
end
|
46
|
+
end
|
47
|
+
mailboxes
|
48
|
+
end
|
49
|
+
|
50
|
+
def restart
|
51
|
+
self.stop if self.running?
|
52
|
+
self.reload unless @mailbox_config
|
53
|
+
self.start
|
54
|
+
end
|
55
|
+
|
56
|
+
def running?
|
57
|
+
@watchers.detect{|watcher| watcher.running?}
|
58
|
+
end
|
59
|
+
|
60
|
+
# Signal catching
|
61
|
+
def stop
|
62
|
+
@watchers.map{|watcher| watcher.stop}
|
63
|
+
@threads.map{|t| t.kill }
|
64
|
+
end
|
65
|
+
|
66
|
+
def start
|
67
|
+
@watchers = []
|
68
|
+
|
69
|
+
configuration.each do |mailbox|
|
70
|
+
puts "Setting up watcher for #{mailbox[:username]}"
|
71
|
+
@watchers << MailDaemon::Imap::Watcher.new(mailbox)
|
72
|
+
end
|
73
|
+
|
74
|
+
@threads = []
|
75
|
+
@watchers.each do |watcher|
|
76
|
+
@threads << Thread.new do
|
77
|
+
watcher.start do |message|
|
78
|
+
if message[:type] == "status_update"
|
79
|
+
update_status(message)
|
80
|
+
elsif message[:type] == "incoming_email"
|
81
|
+
handle_incoming_message(message)
|
82
|
+
else
|
83
|
+
puts "Unknown message type"
|
84
|
+
ap message
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
@threads.map{|t| t.join}
|
90
|
+
|
91
|
+
end
|
92
|
+
|
93
|
+
def handle_incoming_message(options)
|
94
|
+
@handler = MailDaemon::EmailHandler.new(options)
|
95
|
+
@handler.sanitize!
|
96
|
+
@handler.clean_replies!
|
97
|
+
|
98
|
+
hash = @handler.generate_message_hash
|
99
|
+
|
100
|
+
$redis.lpush(redis_key(options), hash)
|
101
|
+
puts "Queued."
|
102
|
+
end
|
103
|
+
|
104
|
+
def redis_key(options)
|
105
|
+
"cb:comms:#{options[:mailbox][:account_code]}:inbox"
|
106
|
+
end
|
107
|
+
|
108
|
+
def update_status(options)
|
109
|
+
puts "Status Update: #{options[:status]} for #{options[:mailbox][:username]}"
|
110
|
+
mysql_client do |mysql|
|
111
|
+
status_message = options[:status]
|
112
|
+
statement = mysql.prepare("UPDATE case_blocks_email_accounts SET imap_status='#{options[:status]}', imap_status_message='#{status_message}' where id=?")
|
113
|
+
statement.execute(options[:mailbox][:id])
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
private
|
118
|
+
|
119
|
+
def mysql_client(&block)
|
120
|
+
client = Mysql2::Client.new(:host => ENV["MYSQL_HOST"], :port => ENV["MYSQL_PORT"], :username => ENV["MYSQL_USERNAME"], :password => ENV["MYSQL_PASSWORD"], :database => ENV["MYSQL_DATABASE"])
|
121
|
+
yield client
|
122
|
+
client.close
|
123
|
+
end
|
124
|
+
|
125
|
+
def mailbox_status_message(watcher)
|
126
|
+
if watcher.logging_in?
|
127
|
+
"Connecting and Logging into server"
|
128
|
+
elsif watcher.logged_in?
|
129
|
+
"Connected"
|
130
|
+
else
|
131
|
+
"Disconnected"
|
132
|
+
end
|
133
|
+
end
|
134
|
+
def mailbox_status(watcher)
|
135
|
+
if watcher.logging_in?
|
136
|
+
:logging_in
|
137
|
+
elsif watcher.logged_in?
|
138
|
+
:connected
|
139
|
+
else
|
140
|
+
:disconnected
|
141
|
+
end
|
142
|
+
end
|
143
|
+
def mailbox_status_colour(watcher)
|
144
|
+
if watcher.logging_in?
|
145
|
+
"orange"
|
146
|
+
elsif watcher.logged_in?
|
147
|
+
"green"
|
148
|
+
else
|
149
|
+
"red"
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
|
154
|
+
end
|
155
|
+
end
|