mail_daemon 0.0.5
Sign up to get free protection for your applications and to get access to all the features.
- 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
|