maillinks 0.1.5 → 0.2.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.
- checksums.yaml +4 -4
- data/bin/maillinks +18 -13
- data/doc/html/maillinks.html +154 -422
- data/doc/man/maillinks.1.gz +0 -0
- data/doc/pdf/maillinks.pdf +0 -0
- data/doc/rst/maillinks.rst +12 -1
- data/lib/basic_logging.rb +201 -0
- data/lib/color_output.rb +65 -0
- data/lib/constants.rb +7 -12
- data/lib/file_checking.rb +4 -11
- data/lib/maillinks.rb +52 -38
- data/maillinks.gemspec +17 -12
- metadata +21 -25
- data/lib/log.conf +0 -53
- data/lib/logging.rb +0 -104
- data/lib/translating.rb +0 -89
- data/lib/translations +0 -24
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
#!/bin/env ruby
|
|
2
|
+
#encoding: UTF-8
|
|
3
|
+
=begin
|
|
4
|
+
/***************************************************************************
|
|
5
|
+
* 2023-2026, Michael Uplawski <michael.uplawski@uplawski.eu> *
|
|
6
|
+
* This program is free software; you can redistribute it and/or modify *
|
|
7
|
+
* it under the terms of the WTFPL 2.0 or later, see *
|
|
8
|
+
* http://www.wtfpl.net/about/ *
|
|
9
|
+
* *
|
|
10
|
+
* This program is distributed in the hope that it will be useful, *
|
|
11
|
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
|
12
|
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
|
|
13
|
+
* *
|
|
14
|
+
***************************************************************************/
|
|
15
|
+
=end
|
|
16
|
+
|
|
17
|
+
#
|
|
18
|
+
# Simplified logging.
|
|
19
|
+
# See example code at the bottom of this file.
|
|
20
|
+
# Execute this file to see the output.
|
|
21
|
+
module BasicLogging
|
|
22
|
+
|
|
23
|
+
DEBUG = 0
|
|
24
|
+
INFO = 1
|
|
25
|
+
WARN = 2
|
|
26
|
+
ERROR = 3
|
|
27
|
+
FATAL = 4
|
|
28
|
+
UNKNOWN = nil
|
|
29
|
+
|
|
30
|
+
# this is mainly for the translation of method calls into log levels
|
|
31
|
+
Levels = {:debug => DEBUG, :info => INFO, :warn => WARN, :error => ERROR,
|
|
32
|
+
:fatal => FATAL, :unknown => UNKNOWN}
|
|
33
|
+
|
|
34
|
+
@@log_level = UNKNOWN
|
|
35
|
+
@@target = STDOUT
|
|
36
|
+
@@muted = []
|
|
37
|
+
|
|
38
|
+
# do not log, if caller is obj (class or instance)
|
|
39
|
+
def self.mute(obj)
|
|
40
|
+
name = obj.class == Class ? obj.name.dup : obj.class.name
|
|
41
|
+
@@muted << name
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def self.is_muted?(obj)
|
|
45
|
+
name = obj.class == Class ? obj.name.dup : obj.class.name
|
|
46
|
+
@@muted.include?(name)
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# set the log level
|
|
50
|
+
def set_level(lv)
|
|
51
|
+
if lv.respond_to?(:to_str) && Levels.keys.include?(lv.strip.to_sym)
|
|
52
|
+
lv = Levels[lv.to_sym]
|
|
53
|
+
elsif lv.respond_to?(:to_sym) && Levels.keys.include?(lv)
|
|
54
|
+
lv = Levels[lv]
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
if(!lv || (lv.respond_to?(:to_int) && lv >= DEBUG && lv <= FATAL) )
|
|
58
|
+
@@log_level = lv
|
|
59
|
+
else
|
|
60
|
+
msg = __FILE__.dup << ": ERROR : invalid log level \"" << lv.to_s << "\""
|
|
61
|
+
msg << "\n" << "Keepinng old log level " << Levels.keys.detect {| k| Levels[k] == @@log_level}.to_s
|
|
62
|
+
STDERR.puts msg
|
|
63
|
+
puts msg
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
# set the log target
|
|
68
|
+
def set_target(tg)
|
|
69
|
+
if tg.respond_to?(:to_io)
|
|
70
|
+
@@target = tg
|
|
71
|
+
elsif(!File::exist?(tg) || ( File.file?(tg) && File.writable?(tg) ) )
|
|
72
|
+
@@target = File.open(tg, 'w+')
|
|
73
|
+
elsif !tg || tg.respond_to?(:to_str) && tg.strip.empty?
|
|
74
|
+
@@target = nil
|
|
75
|
+
else
|
|
76
|
+
STDERR.puts __FILE__.dup << ': ERROR : target ' << tg << ' cannot be set'
|
|
77
|
+
STDERR.puts "Keeping old target " << @@target.inspect
|
|
78
|
+
return
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
# Output of log messages, depending on the log level set for the calling class
|
|
83
|
+
# and the name of the alias method which is actually called.
|
|
84
|
+
def log(message)
|
|
85
|
+
if !BasicLogging.is_muted?(self)
|
|
86
|
+
# how has this method been called?
|
|
87
|
+
mlevel = __callee__
|
|
88
|
+
if Levels.has_key?(mlevel) && Levels[mlevel] <= FATAL
|
|
89
|
+
# output only for levels equal or above the value that corresponds to
|
|
90
|
+
# the calling alias.
|
|
91
|
+
format_log( message, mlevel) if @@log_level && Levels[mlevel] >= @@log_level
|
|
92
|
+
else
|
|
93
|
+
STDERR.puts __FILE__.dup << ": ERROR : invalid log level \"" << mlevel.to_s << "\""
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def target
|
|
99
|
+
@@target.path if @@target
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
def level
|
|
103
|
+
@@level.to_s if @@level
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
# Clear the log (-file)
|
|
107
|
+
def clear_log
|
|
108
|
+
if @@target && @@target.respond_to?(:truncate)
|
|
109
|
+
lock_target{ @@target.truncate(0) }
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
alias :debug :log
|
|
114
|
+
alias :info :log
|
|
115
|
+
alias :warn :log
|
|
116
|
+
alias :error :log
|
|
117
|
+
alias :fatal :log
|
|
118
|
+
|
|
119
|
+
private
|
|
120
|
+
|
|
121
|
+
def lock_target(&block)
|
|
122
|
+
begin
|
|
123
|
+
if @@target.respond_to?(:flock)
|
|
124
|
+
@@target.flock(File::LOCK_EX)
|
|
125
|
+
block.call
|
|
126
|
+
@@target.flock(File::LOCK_UN)
|
|
127
|
+
elsif @@target.respond_to?(:to_io)
|
|
128
|
+
block.call
|
|
129
|
+
end
|
|
130
|
+
rescue => ex
|
|
131
|
+
STDERR.puts __FILE__.dup << ": ERROR : cannot lock target (" << ex.message << ")"
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
# 1 format_log for all loggers.
|
|
136
|
+
def format_log(message, mlevel)
|
|
137
|
+
if @@target
|
|
138
|
+
# indicate if a registered class or the registered object of a class is calling.
|
|
139
|
+
name = self.class == Class ? self.name.dup << ' [class]' : self.class.name
|
|
140
|
+
lock_target{@@target.puts '' << name << ' ' << mlevel.to_s << ' ' << Time.now.strftime("%H:%M:%S:%6N") << ': ' << message.gsub("\n", "\n |")}
|
|
141
|
+
end
|
|
142
|
+
end
|
|
143
|
+
end
|
|
144
|
+
#---------test: execute file----------
|
|
145
|
+
if $0 == __FILE__
|
|
146
|
+
Array.extend(BasicLogging)
|
|
147
|
+
Array.set_level(BasicLogging::INFO)
|
|
148
|
+
Array.info('TEST')
|
|
149
|
+
ar = Array.new
|
|
150
|
+
ar.extend(BasicLogging)
|
|
151
|
+
# --- no output :
|
|
152
|
+
l = __LINE__
|
|
153
|
+
ar.debug(l.next.to_s << ': debug-test 0')
|
|
154
|
+
# output
|
|
155
|
+
ar.set_level(BasicLogging::DEBUG)
|
|
156
|
+
l = __LINE__
|
|
157
|
+
ar.debug(l.next.to_s << ': debug-test 1')
|
|
158
|
+
|
|
159
|
+
obj = Object.new
|
|
160
|
+
obj.extend(BasicLogging)
|
|
161
|
+
obj.set_level(BasicLogging::DEBUG)
|
|
162
|
+
puts "--------debug-----------"
|
|
163
|
+
obj.debug('debug')
|
|
164
|
+
obj.info('info')
|
|
165
|
+
obj.warn('warn')
|
|
166
|
+
obj.error('error')
|
|
167
|
+
obj.fatal('fatal')
|
|
168
|
+
puts "--------info-----------"
|
|
169
|
+
obj.set_level("info")
|
|
170
|
+
obj.debug('debug')
|
|
171
|
+
obj.info('info')
|
|
172
|
+
obj.warn('warn')
|
|
173
|
+
obj.error('error')
|
|
174
|
+
obj.fatal('fatal')
|
|
175
|
+
puts "--------fatal-----------"
|
|
176
|
+
obj.set_level("fatal")
|
|
177
|
+
obj.debug('debug')
|
|
178
|
+
obj.info('info')
|
|
179
|
+
obj.warn('warn')
|
|
180
|
+
obj.error('error')
|
|
181
|
+
obj.fatal('fatal')
|
|
182
|
+
puts "--------UNKNOWN-----------"
|
|
183
|
+
obj.set_level(nil)
|
|
184
|
+
obj.debug('debug')
|
|
185
|
+
obj.info('info')
|
|
186
|
+
obj.warn('warn')
|
|
187
|
+
obj.error('error')
|
|
188
|
+
obj.fatal('fatal')
|
|
189
|
+
puts " ------ Output into file ----"
|
|
190
|
+
obj.set_target "/tmp/test_log.log"
|
|
191
|
+
puts " ------ INFO -----------"
|
|
192
|
+
obj.set_level BasicLogging::INFO
|
|
193
|
+
obj.info('info output')
|
|
194
|
+
|
|
195
|
+
obj.info('info output 2')
|
|
196
|
+
puts "---------- invalid -------"
|
|
197
|
+
obj.set_target "/dev/sr0"
|
|
198
|
+
obj.set_level "power"
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
# EOF
|
data/lib/color_output.rb
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
#encoding: UTF-8
|
|
2
|
+
=begin
|
|
3
|
+
/***************************************************************************
|
|
4
|
+
* 2023-2024, Michael Uplawski <michael.uplawski@uplawski.eu> *
|
|
5
|
+
* This program is free software; you can redistribute it and/or modify *
|
|
6
|
+
* it under the terms of the WTFPL 2.0 or later, see *
|
|
7
|
+
* http://www.wtfpl.net/about/ *
|
|
8
|
+
* *
|
|
9
|
+
* This program is distributed in the hope that it will be useful, *
|
|
10
|
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
|
11
|
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
|
|
12
|
+
* *
|
|
13
|
+
***************************************************************************/
|
|
14
|
+
=end
|
|
15
|
+
|
|
16
|
+
# Functions to apply colors to terminal output.
|
|
17
|
+
# This is stolen from the Internet and I have lost track of my own additions
|
|
18
|
+
# and modifications.
|
|
19
|
+
|
|
20
|
+
COLORS = {:default => 9, :black => 0, :red => 1, :green => 2, :yellow => 3, :blue => 4, :purple => 5, :cyan => 6, :white => 7 }
|
|
21
|
+
|
|
22
|
+
BG = 4
|
|
23
|
+
FG = 3
|
|
24
|
+
REGULAR = 0
|
|
25
|
+
BOLD = 1
|
|
26
|
+
UNDERLINE = 4
|
|
27
|
+
BLINK = 5
|
|
28
|
+
SWAP = 7
|
|
29
|
+
NEUTRAL = 0
|
|
30
|
+
|
|
31
|
+
STYLES = {:regular => REGULAR, :bold => BOLD, :underline => UNDERLINE, :blink => BLINK, :swap => SWAP, :neutral => NEUTRAL}
|
|
32
|
+
|
|
33
|
+
# Colorizes the given text. Color-code is either an escape-sequence or one of
|
|
34
|
+
# the symbols representing color-names in the COLORS hash.
|
|
35
|
+
def colorize(text, color_code)
|
|
36
|
+
if (COLORS.keys.include?(color_code) )
|
|
37
|
+
"\033[3#{COLORS[color_code]}m#{text}\033[0m"
|
|
38
|
+
else
|
|
39
|
+
"#{color_code}#{text}\033[0m"
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def style(text, style_code)
|
|
44
|
+
"#{style_code}#{text}\033[0m"
|
|
45
|
+
end
|
|
46
|
+
# a function which allows to manipulate every known aspect of the ansi-output.
|
|
47
|
+
def colored_output(output_text, fg_color = :default, bg_color = :default, style = :regular , mode = :neutral )
|
|
48
|
+
"\033[%i;%i;%i%i;%i%im%s\033[0m" %[STYLES[mode.to_sym], STYLES[style.to_sym], FG, COLORS[fg_color.to_sym], BG, COLORS[bg_color.to_sym], output_text]
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# convenience functions
|
|
52
|
+
def red(text); colorize(text, "\033[31m"); end
|
|
53
|
+
def green(text); colorize(text, "\033[32m"); end
|
|
54
|
+
def yellow(text); colorize(text, "\033[33m"); end
|
|
55
|
+
def purple(text); colorize(text, "\033[35m"); end
|
|
56
|
+
def cyan(text); colorize(text, "\033[36m"); end
|
|
57
|
+
def blue(text); colorize(text, "\033[34m"); end
|
|
58
|
+
def white(text); colorize(text, "\033[37m"); end
|
|
59
|
+
|
|
60
|
+
def black_on_white(text); colorize(colorize(text, "\033[30m"), "\033[47m");end
|
|
61
|
+
def white_on_black(text); colorize(colorize(text, "\033[37m"), "\033[40m");end
|
|
62
|
+
|
|
63
|
+
def bold(text); style(text, "\033[01m");end
|
|
64
|
+
def underline(text); style(text, "\033[04m");end
|
|
65
|
+
|
data/lib/constants.rb
CHANGED
|
@@ -1,22 +1,15 @@
|
|
|
1
1
|
#encoding: UTF-8
|
|
2
2
|
=begin
|
|
3
3
|
/***************************************************************************
|
|
4
|
-
*
|
|
5
|
-
* *
|
|
4
|
+
* 2023-2026, Michael Uplawski <michael.uplawski@uplawski.eu> *
|
|
6
5
|
* This program is free software; you can redistribute it and/or modify *
|
|
7
|
-
* it under the terms of the
|
|
8
|
-
*
|
|
9
|
-
* (at your option) any later version. *
|
|
6
|
+
* it under the terms of the WTFPL 2.0 or later, see *
|
|
7
|
+
* http://www.wtfpl.net/about/ *
|
|
10
8
|
* *
|
|
11
9
|
* This program is distributed in the hope that it will be useful, *
|
|
12
10
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
|
13
|
-
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
14
|
-
* GNU General Public License for more details. *
|
|
11
|
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
|
|
15
12
|
* *
|
|
16
|
-
* You should have received a copy of the GNU General Public License *
|
|
17
|
-
* along with this program; if not, write to the *
|
|
18
|
-
* Free Software Foundation, Inc., *
|
|
19
|
-
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
|
20
13
|
***************************************************************************/
|
|
21
14
|
=end
|
|
22
15
|
|
|
@@ -26,5 +19,7 @@ require 'tmpdir'
|
|
|
26
19
|
# ignore the rules for HTML. Now they write HTML-mail.
|
|
27
20
|
Block_Tags = %w~body div p hr table img~
|
|
28
21
|
|
|
29
|
-
|
|
22
|
+
# use the first one available
|
|
23
|
+
BROWSERS = ['dillo', 'w3m', 'lynx', 'brave-browser', 'firefox']
|
|
24
|
+
|
|
30
25
|
OUT_FILE = "%s/mail_message.html" %Dir.tmpdir
|
data/lib/file_checking.rb
CHANGED
|
@@ -1,22 +1,15 @@
|
|
|
1
1
|
#encoding: UTF-8
|
|
2
2
|
=begin
|
|
3
3
|
/***************************************************************************
|
|
4
|
-
*
|
|
5
|
-
* *
|
|
4
|
+
* 2011-2026, Michael Uplawski <michael.uplawski@uplawski.eu> *
|
|
6
5
|
* This program is free software; you can redistribute it and/or modify *
|
|
7
|
-
* it under the terms of the
|
|
8
|
-
*
|
|
9
|
-
* (at your option) any later version. *
|
|
6
|
+
* it under the terms of the WTFPL 2.0 or later, see *
|
|
7
|
+
* http://www.wtfpl.net/about/ *
|
|
10
8
|
* *
|
|
11
9
|
* This program is distributed in the hope that it will be useful, *
|
|
12
10
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
|
13
|
-
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
14
|
-
* GNU General Public License for more details. *
|
|
11
|
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
|
|
15
12
|
* *
|
|
16
|
-
* You should have received a copy of the GNU General Public License *
|
|
17
|
-
* along with this program; if not, write to the *
|
|
18
|
-
* Free Software Foundation, Inc., *
|
|
19
|
-
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
|
20
13
|
***************************************************************************/
|
|
21
14
|
=end
|
|
22
15
|
|
data/lib/maillinks.rb
CHANGED
|
@@ -1,86 +1,100 @@
|
|
|
1
1
|
#encoding: UTF-8
|
|
2
2
|
=begin
|
|
3
3
|
/***************************************************************************
|
|
4
|
-
*
|
|
5
|
-
* *
|
|
4
|
+
* 2023-2026, Michael Uplawski <michael.uplawski@uplawski.eu> *
|
|
6
5
|
* This program is free software; you can redistribute it and/or modify *
|
|
7
|
-
* it under the terms of the
|
|
8
|
-
*
|
|
9
|
-
* (at your option) any later version. *
|
|
6
|
+
* it under the terms of the WTFPL 2.0 or later, see *
|
|
7
|
+
* http://www.wtfpl.net/about/ *
|
|
10
8
|
* *
|
|
11
9
|
* This program is distributed in the hope that it will be useful, *
|
|
12
10
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
|
13
|
-
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
14
|
-
* GNU General Public License for more details. *
|
|
11
|
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
|
|
15
12
|
* *
|
|
16
|
-
* You should have received a copy of the GNU General Public License *
|
|
17
|
-
* along with this program; if not, write to the *
|
|
18
|
-
* Free Software Foundation, Inc., *
|
|
19
|
-
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
|
20
13
|
***************************************************************************/
|
|
21
14
|
=end
|
|
22
15
|
|
|
23
16
|
require_relative 'file_checking'
|
|
24
|
-
require_relative '
|
|
17
|
+
require_relative 'basic_logging'
|
|
25
18
|
require_relative 'constants'
|
|
19
|
+
require_relative 'color_output'
|
|
26
20
|
require 'mail'
|
|
27
21
|
require 'nokogiri'
|
|
28
22
|
require 'escape'
|
|
29
23
|
|
|
30
24
|
# show me the urls.
|
|
31
25
|
class MailLinks
|
|
32
|
-
include
|
|
26
|
+
include BasicLogging
|
|
33
27
|
def initialize(mail = nil)
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
# a file may be piped in from the command-line...
|
|
37
|
-
@log.debug('parameter is ' << (mail ? mail : ' N I L' ))
|
|
28
|
+
# a file may be piped in from the command-line...
|
|
29
|
+
debug('parameter is ' << (mail ? mail : ' N I L' ))
|
|
38
30
|
if(mail && '-' != mail.strip)
|
|
39
31
|
msg = File_Checking.file_check(mail, :exist, :file, :readable)
|
|
40
32
|
if(msg)
|
|
41
|
-
|
|
33
|
+
error(yellow(msg) )
|
|
42
34
|
usage
|
|
43
35
|
exit false
|
|
44
36
|
else
|
|
45
|
-
|
|
37
|
+
debug('will work on mail-file ' << mail)
|
|
46
38
|
@mail = mail
|
|
47
39
|
|
|
48
40
|
File::open(OUT_FILE, 'w+') {|of| of << File::read(@mail) }
|
|
49
41
|
end
|
|
50
42
|
elsif(!$<.eof?)
|
|
51
|
-
|
|
43
|
+
info('Reading data from STDIN. Hit Ctrl+D to interrupt')
|
|
52
44
|
input = $<.read
|
|
53
|
-
|
|
45
|
+
debug('input length is ' << input.length.to_s)
|
|
54
46
|
if(input.length < 10)
|
|
55
|
-
|
|
56
|
-
|
|
47
|
+
error(yellow('insufficient input data'))
|
|
48
|
+
error(yellow('No mail text provided'))
|
|
57
49
|
usage()
|
|
58
50
|
exit false
|
|
59
51
|
end
|
|
60
52
|
# ... provide a temporary file in that case,
|
|
61
|
-
# @mail = OUT_FILE
|
|
62
53
|
File.open(OUT_FILE, 'w+') {|of| of << input}
|
|
63
54
|
@mail = OUT_FILE.dup
|
|
64
|
-
|
|
55
|
+
debug('Temporary eml-file is written.')
|
|
65
56
|
end
|
|
66
57
|
|
|
67
58
|
procede
|
|
68
59
|
end
|
|
69
60
|
|
|
70
61
|
private
|
|
62
|
+
|
|
63
|
+
def browser()
|
|
64
|
+
BROWSERS.detect do |b|
|
|
65
|
+
debug 'trying to find browser: ' << b.to_s
|
|
66
|
+
ENV['PATH'].split(':').each do |dir_name|
|
|
67
|
+
return b if Dir.entries(dir_name).include?(b)
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
error 'Cannot find any of the given browsers: ' << BROWSERS.join(', ')
|
|
71
|
+
return nil
|
|
72
|
+
end
|
|
73
|
+
|
|
71
74
|
def procede
|
|
72
75
|
handle_mail
|
|
73
76
|
show_mail
|
|
74
77
|
end
|
|
75
78
|
def usage
|
|
76
|
-
msg =
|
|
79
|
+
msg = "\nUsage: " << $0 << ' ' << '<mail-file>'
|
|
77
80
|
msg << "\n or: " << 'cat <mail-file> |' << $0
|
|
81
|
+
msg << "\nYou can name a log level as second parameter:\n"
|
|
82
|
+
msg << " " << $0 << ' ' << '<mail-file>' << ' ' << 'debug'
|
|
83
|
+
msg << "\nThis will create more verbose program output.\n"
|
|
78
84
|
puts msg
|
|
79
85
|
end
|
|
80
86
|
|
|
81
87
|
def show_mail
|
|
82
|
-
|
|
83
|
-
|
|
88
|
+
prog = browser()
|
|
89
|
+
if prog
|
|
90
|
+
cmd = Escape.shell_command([prog, OUT_FILE])
|
|
91
|
+
info cyan('<----------- Output from ' << prog << '---------->')
|
|
92
|
+
system(cmd)
|
|
93
|
+
info cyan('-----------> ' << prog << ' END <----------')
|
|
94
|
+
else
|
|
95
|
+
fatal yellow('Cannot open browser!' + bold(' ABORTING.') )
|
|
96
|
+
exit false
|
|
97
|
+
end
|
|
84
98
|
end
|
|
85
99
|
|
|
86
100
|
def handle_mail
|
|
@@ -89,8 +103,8 @@ class MailLinks
|
|
|
89
103
|
mail_body = mail_content.split("</head>")[1].split("</html>")[0]
|
|
90
104
|
mail_body = Mail::Encodings::QuotedPrintable.decode(mail_body)
|
|
91
105
|
rescue Exception => ex
|
|
92
|
-
|
|
93
|
-
|
|
106
|
+
error('Cannot find the html-body in this mail. Maybe it is not a HTML-mail?')
|
|
107
|
+
debug(ex.message)
|
|
94
108
|
end
|
|
95
109
|
if !mail_body
|
|
96
110
|
mail_body = mail_content
|
|
@@ -100,7 +114,7 @@ class MailLinks
|
|
|
100
114
|
|
|
101
115
|
a_nodes = html_mail.xpath(".//a")
|
|
102
116
|
if(! a_nodes || a_nodes.empty? )
|
|
103
|
-
|
|
117
|
+
info(green('no links in this mail') )
|
|
104
118
|
exit true
|
|
105
119
|
end
|
|
106
120
|
begin
|
|
@@ -114,30 +128,30 @@ class MailLinks
|
|
|
114
128
|
body.add_child("<hr/>")
|
|
115
129
|
body.add_child("<h2>HTML-links in this mail</h2>")[0]
|
|
116
130
|
if(!body)
|
|
117
|
-
|
|
131
|
+
error('cannot find a body-tag in this mail')
|
|
118
132
|
exit false
|
|
119
133
|
end
|
|
120
134
|
dl = body.add_child("<dl id='links'></dl>")[0]
|
|
121
135
|
if(!dl)
|
|
122
|
-
|
|
136
|
+
error('cannot add a list-tag')
|
|
123
137
|
exit false
|
|
124
138
|
end
|
|
125
139
|
links_hash = Hash.new
|
|
126
140
|
a_nodes.each_with_index do |a, i|
|
|
127
|
-
|
|
141
|
+
debug('a is ' << a.to_s.gsub("=\" ", ''))
|
|
128
142
|
caption = a.inner_text.to_s.strip
|
|
129
143
|
href = a.attribute('href')
|
|
130
144
|
if(href)
|
|
131
|
-
|
|
145
|
+
debug('href is: ' << href.to_s)
|
|
132
146
|
link = href.content
|
|
133
|
-
|
|
147
|
+
debug('link is ex href.content: ' << link.to_s)
|
|
134
148
|
a.add_next_sibling("<span>[" << (i.next).to_s << "]</span>")
|
|
135
149
|
dl.add_child("<dt>%i) %s</dt>"%[i.next, caption])
|
|
136
|
-
dl.add_child("<dd style='white-space:nowrap;'><a href='%s'>%s</a></dd>"%[link,link])
|
|
150
|
+
dl.add_child("<dd style='white-space:nowrap;'><a style='white-space:nowrap;' href='%s'>%s</a></dd>"%[link,link])
|
|
137
151
|
end
|
|
138
152
|
end
|
|
139
153
|
rescue Exception => ex
|
|
140
|
-
|
|
154
|
+
error(yellow("cannot handle the HTML in this mail: ") << bold(ex.message) )
|
|
141
155
|
exit false
|
|
142
156
|
end
|
|
143
157
|
|
data/maillinks.gemspec
CHANGED
|
@@ -1,20 +1,25 @@
|
|
|
1
|
+
require_relative "lib/version"
|
|
1
2
|
require 'date'
|
|
2
3
|
|
|
3
4
|
Gem::Specification.new do |s|
|
|
4
|
-
s.name =
|
|
5
|
-
s.version =
|
|
5
|
+
s.name = PROGNAME
|
|
6
|
+
s.version = VERSION
|
|
6
7
|
s.date = Date.today.strftime('%Y-%m-%d')
|
|
7
|
-
s.summary = "
|
|
8
|
+
s.summary = "Documentation in HTML formatted. Alternative Browsers allowed."
|
|
8
9
|
s.description = "Marks in an email HTMl-links and creates a list of all links at the bottom of the mail-text. Best used with the Mutt MUA"
|
|
9
|
-
s.authors =
|
|
10
|
-
s.email =
|
|
11
|
-
s.files = %w~maillinks~.collect{|f| 'bin/' << f} + %w~constants.rb
|
|
12
|
-
s.homepage = '
|
|
13
|
-
s.requirements = 'Linux,
|
|
14
|
-
s.add_runtime_dependency 'nokogiri', '~> 1.
|
|
10
|
+
s.authors = AUTHORS
|
|
11
|
+
s.email = MAIL_ADDRESS
|
|
12
|
+
s.files = %w~maillinks~.collect{|f| 'bin/' << f} + %w~constants.rb color_output.rb file_checking.rb basic_logging.rb maillinks.rb ~.collect{|f| 'lib/' << f} + %w~html/maillinks.html man/maillinks.1.gz pdf/maillinks.pdf rst/maillinks.rst~.collect{|f| 'doc/' << f} + %w~maillinks.gemspec~.collect{|f|f}
|
|
13
|
+
s.homepage = 'https://www.uplawski.eu/software'
|
|
14
|
+
s.requirements = 'Linux, one of the browsers Dillo, W3M, Lynx, Brave-browser or Firefox'
|
|
15
|
+
s.add_runtime_dependency 'nokogiri', '~> 1.19', '>= 1.19.0'
|
|
15
16
|
s.add_runtime_dependency 'escape', '~> 0.0', '>= 0.0.4'
|
|
16
|
-
s.add_runtime_dependency 'mail', '~> 2.
|
|
17
|
+
s.add_runtime_dependency 'mail', '~> 2.9', '>= 2.9.0'
|
|
17
18
|
s.executables = 'maillinks'
|
|
18
|
-
s.license = '
|
|
19
|
-
s.required_ruby_version = '>=
|
|
19
|
+
s.license = 'Nonstandard'
|
|
20
|
+
s.required_ruby_version = '>= 4.0'
|
|
21
|
+
s.metadata = {
|
|
22
|
+
"homepage_uri" => 'https://www.uplawski.eu/software/',
|
|
23
|
+
"documentation_uri" => 'https://www.uplawski.eu/software/maillinks/maillinks.html'
|
|
24
|
+
}
|
|
20
25
|
end
|
metadata
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: maillinks
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.1
|
|
4
|
+
version: 0.2.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Michael Uplawski
|
|
8
|
-
autorequire:
|
|
9
8
|
bindir: bin
|
|
10
9
|
cert_chain: []
|
|
11
|
-
date:
|
|
10
|
+
date: 2026-04-28 00:00:00.000000000 Z
|
|
12
11
|
dependencies:
|
|
13
12
|
- !ruby/object:Gem::Dependency
|
|
14
13
|
name: nokogiri
|
|
@@ -16,20 +15,20 @@ dependencies:
|
|
|
16
15
|
requirements:
|
|
17
16
|
- - "~>"
|
|
18
17
|
- !ruby/object:Gem::Version
|
|
19
|
-
version: '1.
|
|
18
|
+
version: '1.19'
|
|
20
19
|
- - ">="
|
|
21
20
|
- !ruby/object:Gem::Version
|
|
22
|
-
version: 1.
|
|
21
|
+
version: 1.19.0
|
|
23
22
|
type: :runtime
|
|
24
23
|
prerelease: false
|
|
25
24
|
version_requirements: !ruby/object:Gem::Requirement
|
|
26
25
|
requirements:
|
|
27
26
|
- - "~>"
|
|
28
27
|
- !ruby/object:Gem::Version
|
|
29
|
-
version: '1.
|
|
28
|
+
version: '1.19'
|
|
30
29
|
- - ">="
|
|
31
30
|
- !ruby/object:Gem::Version
|
|
32
|
-
version: 1.
|
|
31
|
+
version: 1.19.0
|
|
33
32
|
- !ruby/object:Gem::Dependency
|
|
34
33
|
name: escape
|
|
35
34
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -56,20 +55,20 @@ dependencies:
|
|
|
56
55
|
requirements:
|
|
57
56
|
- - "~>"
|
|
58
57
|
- !ruby/object:Gem::Version
|
|
59
|
-
version: '2.
|
|
58
|
+
version: '2.9'
|
|
60
59
|
- - ">="
|
|
61
60
|
- !ruby/object:Gem::Version
|
|
62
|
-
version: 2.
|
|
61
|
+
version: 2.9.0
|
|
63
62
|
type: :runtime
|
|
64
63
|
prerelease: false
|
|
65
64
|
version_requirements: !ruby/object:Gem::Requirement
|
|
66
65
|
requirements:
|
|
67
66
|
- - "~>"
|
|
68
67
|
- !ruby/object:Gem::Version
|
|
69
|
-
version: '2.
|
|
68
|
+
version: '2.9'
|
|
70
69
|
- - ">="
|
|
71
70
|
- !ruby/object:Gem::Version
|
|
72
|
-
version: 2.
|
|
71
|
+
version: 2.9.0
|
|
73
72
|
description: Marks in an email HTMl-links and creates a list of all links at the bottom
|
|
74
73
|
of the mail-text. Best used with the Mutt MUA
|
|
75
74
|
email: michael.uplawski@uplawski.eu
|
|
@@ -83,19 +82,18 @@ files:
|
|
|
83
82
|
- doc/man/maillinks.1.gz
|
|
84
83
|
- doc/pdf/maillinks.pdf
|
|
85
84
|
- doc/rst/maillinks.rst
|
|
85
|
+
- lib/basic_logging.rb
|
|
86
|
+
- lib/color_output.rb
|
|
86
87
|
- lib/constants.rb
|
|
87
88
|
- lib/file_checking.rb
|
|
88
|
-
- lib/log.conf
|
|
89
|
-
- lib/logging.rb
|
|
90
89
|
- lib/maillinks.rb
|
|
91
|
-
- lib/translating.rb
|
|
92
|
-
- lib/translations
|
|
93
90
|
- maillinks.gemspec
|
|
94
|
-
homepage:
|
|
91
|
+
homepage: https://www.uplawski.eu/software
|
|
95
92
|
licenses:
|
|
96
|
-
-
|
|
97
|
-
metadata:
|
|
98
|
-
|
|
93
|
+
- Nonstandard
|
|
94
|
+
metadata:
|
|
95
|
+
homepage_uri: https://www.uplawski.eu/software/
|
|
96
|
+
documentation_uri: https://www.uplawski.eu/software/maillinks/maillinks.html
|
|
99
97
|
rdoc_options: []
|
|
100
98
|
require_paths:
|
|
101
99
|
- lib
|
|
@@ -103,17 +101,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
103
101
|
requirements:
|
|
104
102
|
- - ">="
|
|
105
103
|
- !ruby/object:Gem::Version
|
|
106
|
-
version:
|
|
104
|
+
version: '4.0'
|
|
107
105
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
108
106
|
requirements:
|
|
109
107
|
- - ">="
|
|
110
108
|
- !ruby/object:Gem::Version
|
|
111
109
|
version: '0'
|
|
112
110
|
requirements:
|
|
113
|
-
- Linux,
|
|
114
|
-
rubygems_version:
|
|
115
|
-
signing_key:
|
|
111
|
+
- Linux, one of the browsers Dillo, W3M, Lynx, Brave-browser or Firefox
|
|
112
|
+
rubygems_version: 4.0.10
|
|
116
113
|
specification_version: 4
|
|
117
|
-
summary:
|
|
118
|
-
decoding is done correctly, now.
|
|
114
|
+
summary: Documentation in HTML formatted. Alternative Browsers allowed.
|
|
119
115
|
test_files: []
|