at_email 0.0.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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 074b5f8e272c1f28f2fa4089e5396b13b061c1dd
4
+ data.tar.gz: f5eaf714aa99285d339078fe5ee59965ca12614c
5
+ SHA512:
6
+ metadata.gz: e689e838a44d38ec50bee5c5afc6624bcefb5eb064fdc2f01231799d229bf84d8b15287d05e1cd93f84a18811da2e354672e3c8a4f5cd5d3bbc15b9e2afacd95
7
+ data.tar.gz: 83e37a70a22770e6abb9ee613aeb40af85668f196223a81f1a767b7da9af09afba065cd2cc12f13f8de24ac005a9e4cd35cd2f1957d51f607d6896f24d9e2b6b
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2018 Robin Patel
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.
@@ -0,0 +1,28 @@
1
+ # at_email
2
+
3
+ A project to build an e-mail management and support toolkit.
4
+
5
+ The project is currently at a very early stage and the functionality is likely to be unstable and possible destructive for the time being, I would not recommend using this software at this time. We will update this information when the software is in a more stable stage of development.
6
+
7
+ ## Prerequisites
8
+
9
+ * ruby 2.3.7+
10
+ * GEM: concurrent-ruby (1.1.3)
11
+
12
+ ## License
13
+
14
+ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details
15
+
16
+ ## Acknowledgments
17
+
18
+ * https://github.com/joeyates
19
+
20
+ ## Disclaimer
21
+
22
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
25
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28
+ SOFTWARE.
@@ -0,0 +1,24 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $LOAD_PATH.unshift(File.expand_path("../lib/", __dir__))
4
+ require 'at_email'
5
+ $runtime_configure = At_email::RuntimeConfigure.new
6
+ $runtime_configure.get_app_path
7
+ $options = At_email::Config::Cmd_Opt_Parser.new(ARGV)
8
+ config_file = At_email::Config::Config_File.new
9
+ $config = config_file.get_config()
10
+ $runtime_configure.configure_logger
11
+
12
+ $logger.debug ''
13
+ $logger.warn 'Welcome to atEmail - Build: ' + At_email::VERSION + ' - PID: ' + Process.pid.to_s
14
+ $logger.debug ''
15
+ $logger.warn 'Config File: ' + $options.config_file + ' - Task Starting'
16
+ $logger.warn 'Log File: ' + $logger.log_file_default
17
+
18
+ $runtime_configure.output_config
19
+
20
+ task = At_email::Tasks::Imap_To_Fs.new()
21
+
22
+ task.execute
23
+
24
+ $logger.warn 'Config File: ' + $options.config_file + ' - Task Complete'
@@ -0,0 +1,210 @@
1
+ module At_email ; end
2
+
3
+ ### libs
4
+ require 'fileutils'
5
+ require "logger"
6
+ require 'digest'
7
+
8
+ ### at_email libs
9
+ require "at_email/core"
10
+ require "at_email/version"
11
+ require "at_email/config"
12
+ require "at_email/account"
13
+ require "at_email/tasks"
14
+ require "at_email/threads"
15
+
16
+ module At_email
17
+
18
+ DEFAULT_CONFIG_FILE = 'cfg/defaults/default_config.json'
19
+
20
+ end
21
+
22
+ module At_email
23
+
24
+ class At_email::At_Logger
25
+
26
+ attr_reader :log_file_default
27
+
28
+ def initialize
29
+
30
+ filename_timestamp = Time.now.strftime("%Y%m%d_%H%M%S")
31
+ log_file_dir = $config[:output_base_dir] + '/_logs'
32
+
33
+ @log_file_default = log_file_dir + '/' + $config[:task] + '.' + $config[:account_id] + '.' + filename_timestamp + '.log'
34
+ if !Dir.exists?(log_file_dir)
35
+ FileUtils.mkdir_p log_file_dir
36
+ end
37
+ @logger_stdout = Logger.new(STDOUT)
38
+ @logger_stderr = Logger.new(STDERR)
39
+ @logger_file_default = Logger.new(@log_file_default)
40
+ @logger_stdout.datetime_format = '%Y-%m-%d %H:%M:%S'
41
+ @logger_stdout.formatter = proc do |severity, datetime, progname, msg|
42
+ "#{datetime} - " + $config[:task] + " - " + $config[:account_id] + " - #{msg}\n"
43
+ end
44
+ @logger_stderr.datetime_format = '%Y-%m-%d %H:%M:%S'
45
+ @logger_stderr.formatter = proc do |severity, datetime, progname, msg|
46
+ "#{datetime} - " + $config[:task] + " - " + $config[:account_id] + " - #{msg}\n"
47
+ end
48
+ @logger_file_default.datetime_format = '%Y-%m-%d %H:%M:%S'
49
+ @logger_file_default.formatter = proc do |severity, datetime, progname, msg|
50
+ "#{datetime} - " + $config[:task] + " - " + $config[:account_id] + " - #{msg}\n"
51
+ end
52
+ if $options.silent
53
+ @logger_stdout.level = Logger::FATAL
54
+ @logger_stderr.level = Logger::FATAL
55
+ @logger_file_default.level = Logger::FATAL
56
+ elsif $options.quiet
57
+ @logger_stdout.level = Logger::WARN
58
+ @logger_stderr.level = Logger::WARN
59
+ @logger_file_default.level = Logger::WARN
60
+ elsif $options.verbose
61
+ @logger_stdout.level = Logger::DEBUG
62
+ @logger_stderr.level = Logger::DEBUG
63
+ @logger_file_default.level = Logger::DEBUG
64
+ else
65
+ @logger_stdout.level = Logger::INFO
66
+ @logger_stderr.level = Logger::INFO
67
+ @logger_file_default.level = Logger::INFO
68
+ end
69
+ end
70
+
71
+ def debug(event)
72
+ @logger_stdout.debug(event)
73
+ @logger_file_default.debug(event)
74
+ end
75
+
76
+ def info(event)
77
+ @logger_stdout.info(event)
78
+ @logger_file_default.info(event)
79
+ end
80
+
81
+ def warn(event)
82
+ @logger_stderr.warn(event)
83
+ @logger_file_default.warn(event)
84
+ end
85
+
86
+ def error(event)
87
+ @logger_stderr.error(event)
88
+ @logger_file_default.error(event)
89
+ end
90
+
91
+ def fatal(event)
92
+ @logger_stderr.fatal(event)
93
+ @logger_file_default.fatal(event)
94
+ end
95
+
96
+ def unknown(event)
97
+ @logger_stderr.unknown(event)
98
+ @logger_file_default.unknown(event)
99
+ end
100
+
101
+ def event(event_level, event_tag, event_data)
102
+ event_tag_formatted = get_event_tag_formatted(event_tag)
103
+ if event_tag_formatted === ''
104
+ log_string = event_data
105
+ else
106
+ log_string = event_tag_formatted + ' - ' + event_data
107
+ end
108
+ case event_level
109
+ when 'DEBUG'
110
+ $logger.debug log_string
111
+ when 'WARN'
112
+ $logger.error log_string
113
+ when 'ERROR'
114
+ $logger.fatal ''
115
+ $logger.error log_string
116
+ $logger.error ''
117
+ $logger.error 'Error at line number: ' + __LINE__.to_s + ' of file: ' + __FILE__
118
+ caller.each do |stack_line|
119
+ $logger.error ' ' + stack_line
120
+ end
121
+ $logger.error ''
122
+ when 'FATAL'
123
+ error_code = 1
124
+ $logger.fatal ''
125
+ $logger.fatal log_string
126
+ $logger.fatal ''
127
+ $logger.fatal 'Fatal Error at line number: ' + __LINE__.to_s + ' of file: ' + __FILE__
128
+ caller.each do |stack_line|
129
+ $logger.fatal ' ' + stack_line
130
+ end
131
+ $logger.fatal ''
132
+ $logger.fatal 'Exiting with error code: ' + error_code.to_s
133
+ $logger.fatal ''
134
+ puts "\n"
135
+ exit(error_code)
136
+ else
137
+ $logger.info log_string
138
+ end
139
+ end
140
+
141
+ def get_event_tag_formatted(event_tag)
142
+ event_tag_formatted = ''
143
+ if event_tag.length == 0
144
+ event_tag_formatted = ''
145
+ else
146
+ if event_tag.length <= 2
147
+ event_tag_formatted = '*' + event_tag + '*'
148
+ else
149
+ event_tag_formatted = '***** ' + event_tag + ' *****'
150
+ end
151
+ end
152
+ return event_tag_formatted
153
+ end
154
+
155
+ end
156
+
157
+ class At_email::RuntimeConfigure
158
+
159
+ def configure_logger
160
+ $logger = At_email::At_Logger.new()
161
+ end
162
+
163
+ def output_config
164
+ $logger.debug ''
165
+ $logger.debug 'Configuration'
166
+ $config.each do |key, value|
167
+ if key.to_s === 'password'
168
+ $logger.debug ' ' + key.to_s + ' = ' + '*' * value.to_s.length
169
+ else
170
+ $logger.debug ' ' + key.to_s + ' = ' + value.to_s
171
+ end
172
+ end
173
+ $logger.debug ''
174
+ end
175
+
176
+ def get_app_path
177
+ $app_path = File.dirname(File.expand_path(File.dirname($0)))
178
+ end
179
+
180
+ end
181
+
182
+ class At_email::Formatting
183
+
184
+ def initialize
185
+ end
186
+
187
+ def get_hash(data, hash_length)
188
+ if !hash_length.is_a? Numeric
189
+ $logger.event('FATAL', 'FATAL ERROR', 'hash_length variable is not numeric')
190
+ return false
191
+ end
192
+ if (hash_length > 32)
193
+ $logger.event('FATAL', 'FATAL ERROR', 'hash_length maximum limit is 32 - Requested length: ' + hash_length.to_s)
194
+ return false
195
+ end
196
+ return Digest::MD5.hexdigest(data)[0...hash_length]
197
+ end
198
+
199
+ def get_random_id(id_length)
200
+ hash = get_hash(Time.now.to_f.to_s + '-' + rand(1..1000000000000).to_s, id_length)
201
+ if hash
202
+ return hash
203
+ else
204
+ return false
205
+ end
206
+ end
207
+
208
+ end
209
+
210
+ end
@@ -0,0 +1,3 @@
1
+ module At_email::Account ; end
2
+
3
+ require "at_email/account/connection"
@@ -0,0 +1,32 @@
1
+
2
+ require 'net/imap'
3
+
4
+ class At_email::Account::Imap < Net::IMAP
5
+ attr_accessor :debug
6
+ end
7
+
8
+ class At_email::Account::ImapConnection
9
+
10
+ attr_reader :imap
11
+
12
+ METADATA_ATTRIBUTES = [ 'ENVELOPE', 'FLAGS' ].freeze
13
+ REQUESTED_ATTRIBUTES = [ 'INTERNALDATE', 'RFC822', 'RFC822.SIZE' ].freeze
14
+
15
+ def initialize()
16
+ $logger.info 'Connecting to IMAP server - Host: ' + $config[:server] + ' - Port: ' + $config[:port].to_s
17
+ connect_config = {port: $config[:port], ssl: $config[:ssl]}
18
+ @imap = At_email::Account::Imap.new($config[:server], connect_config)
19
+ end
20
+
21
+ def login
22
+ $logger.info 'Logging into IMAP server - Username: ' + $config[:username]
23
+ @imap.login($config[:username], $config[:password])
24
+ end
25
+
26
+ def disconnect
27
+ $logger.debug 'Logging out from IMAP server'
28
+ @imap.logout
29
+ @imap.disconnect
30
+ end
31
+
32
+ end
@@ -0,0 +1,4 @@
1
+ module At_email::Config ; end
2
+
3
+ require "at_email/config/config_file"
4
+ require "at_email/config/cmd_opt_parser"
@@ -0,0 +1,58 @@
1
+
2
+ require 'optparse'
3
+ require 'optparse/time'
4
+ require 'ostruct'
5
+ require 'pp'
6
+
7
+ class At_email::Config::Cmd_Opt_Parser
8
+
9
+ attr_reader :config_file
10
+ attr_reader :verbose
11
+ attr_reader :quiet
12
+ attr_reader :silent
13
+
14
+ CODES = %w[iso-2022-jp shift_jis euc-jp utf8 binary]
15
+ CODE_ALIASES = { "jis" => "iso-2022-jp", "sjis" => "shift_jis" }
16
+
17
+ def initialize(args)
18
+ @silent = false
19
+ @quiet = false
20
+ @verbose = false
21
+ opt_parser = OptionParser.new do |opts|
22
+ opts.banner = "Usage: #{$PROGRAM_NAME} [options]"
23
+ opts.separator ""
24
+ opts.separator "Options:"
25
+ opts.on("-c [CONFIG FILE]", "--config-file [CONFIG FILE]", String, "Config File (JSON)") do |config_file|
26
+ @config_file = config_file
27
+ end
28
+ opts.on("-s", "--silent", "Run silently") do
29
+ @silent = true
30
+ end
31
+ opts.on("-q", "--quiet", "Run quietly") do
32
+ @quiet = true
33
+ if @silent
34
+ @silent = false
35
+ end
36
+ end
37
+ opts.on("-v", "--verbose", "Run verbosely") do
38
+ @verbose = true
39
+ if @quiet
40
+ @quiet = false
41
+ end
42
+ if @silent
43
+ @silent = false
44
+ end
45
+ end
46
+ opts.on_tail("-h", "--help", "Show this message") do
47
+ puts opts
48
+ exit
49
+ end
50
+ opts.on_tail("--version", "Show version") do
51
+ puts At_email::VERSION
52
+ exit
53
+ end
54
+ end
55
+ opt_parser.parse!(args)
56
+ end
57
+
58
+ end
@@ -0,0 +1,100 @@
1
+
2
+ require 'json'
3
+
4
+ class At_email::Config::Config_File
5
+
6
+ def get_config()
7
+
8
+ if File.exist?($options.config_file)
9
+ contents = File.read($options.config_file)
10
+ config = JSON.parse(contents, symbolize_names: true)
11
+ else
12
+ raise "Config file does not exist: " + $options.config_file
13
+ end
14
+
15
+ default_config_file_path = $app_path + '/' + At_email::DEFAULT_CONFIG_FILE
16
+ if File.exist?(default_config_file_path)
17
+ default_config_contents = File.read(default_config_file_path)
18
+ default_config = JSON.parse(default_config_contents, symbolize_names: true)
19
+ else
20
+ raise "Default config file does not exist: " + default_config_file_path
21
+ end
22
+
23
+ config.each do |key, value|
24
+ if !default_config[key]
25
+ raise 'Config Error: Property: ' + key.to_s + ' is not a valid configuration option for this system'
26
+ end
27
+ end
28
+
29
+ default_config.each do |key, data|
30
+ if !config[key] && data[:value]
31
+ config[key] = data[:value]
32
+ end
33
+ end
34
+
35
+ default_config.each do |key, data|
36
+ if config[key]
37
+ if data[:type]
38
+ if data[:type] === 'boolean'
39
+ if ![true, false].include? config[key]
40
+ raise 'Config Error: Property: ' + key.to_s + ' is not type: boolean - config value: ' + config[key].to_s
41
+ end
42
+ end
43
+ if data[:type] === 'numeric'
44
+ if !config[key].is_a? Numeric
45
+ raise 'Config Error: Property: ' + key.to_s + ' is not type: numeric - config value: ' + config[key].to_s
46
+ end
47
+ if data[:min_value]
48
+ if config[key] < data[:min_value]
49
+ raise 'Config Error: Property: ' + key.to_s + ' is below minimum value: ' + data[:min_value].to_s + ' - config value: ' + config[key].to_s
50
+ end
51
+ end
52
+ if data[:max_value]
53
+ if config[key] > data[:max_value]
54
+ raise 'Config Error: Property: ' + key.to_s + ' is above maximum value: ' + data[:max_value].to_s + ' - config value: ' + config[key].to_s
55
+ end
56
+ end
57
+ end
58
+ if data[:type] === 'string'
59
+ if !config[key].is_a? String
60
+ raise 'Config Error: Property: ' + key.to_s + ' is not type: string - value: ' + config[key].to_s
61
+ end
62
+ if data[:min_length]
63
+ if config[key].length < data[:min_length]
64
+ raise 'Config Error: Property: ' + key.to_s + ' is below minimum lenth: ' + data[:min_length].to_s + ' - config value: ' + config[key].to_s
65
+ end
66
+ end
67
+ if data[:max_length]
68
+ if config[key].length > data[:max_length]
69
+ raise 'Config Error: Property: ' + key.to_s + ' is above minimum lenth: ' + data[:max_length].to_s + ' - config value: ' + config[key].to_s
70
+ end
71
+ end
72
+ end
73
+ if data[:type] === 'path'
74
+ if data[:path_type]
75
+ if data[:path_type] === 'dir'
76
+ if !Dir.exists?(config[key].to_s)
77
+ raise 'Config Error: Property: ' + key.to_s + ' is not a directory path - config value: ' + config[key].to_s
78
+ end
79
+ end
80
+ if data[:path_type] === 'file'
81
+ if !File.exists?(config[key].to_s)
82
+ raise 'Config Error: Property: ' + key.to_s + ' is not a file path - config value: ' + config[key].to_s
83
+ end
84
+ end
85
+ end
86
+ end
87
+ end
88
+ end
89
+ end
90
+
91
+ output = {}
92
+ config.sort_by { |k, v| k }.each do |key, value|
93
+ output[key] = value
94
+ end
95
+
96
+ return output
97
+
98
+ end
99
+
100
+ end