tuktuk 0.1.0 → 0.1.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.
- data/lib/tuktuk/package.rb +4 -20
- data/lib/tuktuk/tuktuk.rb +105 -105
- data/lib/tuktuk/version.rb +1 -1
- metadata +3 -3
data/lib/tuktuk/package.rb
CHANGED
@@ -10,7 +10,7 @@ module Package
|
|
10
10
|
|
11
11
|
mail['In-Reply-To'] = message[:in_reply_to] if message[:in_reply_to]
|
12
12
|
mail['List-Archive'] = message[:list_archive] if message[:list_archive] # https://github.com/tomas/prey
|
13
|
-
mail['List-Id'] = message[:list_id] if message[:list_id]
|
13
|
+
mail['List-Id'] = message[:list_id] if message[:list_id] # <prey.tomas.github.com>
|
14
14
|
|
15
15
|
if message[:return_path]
|
16
16
|
mail['Return-Path'] = message[:return_path]
|
@@ -29,7 +29,7 @@ module Package
|
|
29
29
|
# sender message[:sender] if message[:sender]
|
30
30
|
subject message[:subject]
|
31
31
|
message_id message[:message_id] if message[:message_id]
|
32
|
-
body message[:
|
32
|
+
body message[:body]
|
33
33
|
end
|
34
34
|
end
|
35
35
|
|
@@ -42,31 +42,15 @@ module Package
|
|
42
42
|
subject message[:subject]
|
43
43
|
message_id message[:message_id] if message[:message_id]
|
44
44
|
text_part do
|
45
|
-
body message[:
|
45
|
+
body message[:body]
|
46
46
|
end
|
47
47
|
html_part do
|
48
48
|
content_type 'text/html; charset=UTF-8'
|
49
|
-
body message[:
|
49
|
+
body message[:html_body]
|
50
50
|
end
|
51
51
|
end
|
52
52
|
end
|
53
53
|
|
54
|
-
def link_plain_attachments(attachments, body)
|
55
|
-
text = "\n\nAttachments\n==========\n"
|
56
|
-
attachments.each_with_index do |att, i|
|
57
|
-
text += "[#{att[:name]}] #{att[:link]} \n"
|
58
|
-
end
|
59
|
-
body + text
|
60
|
-
end
|
61
|
-
|
62
|
-
def link_html_attachments(attachments, body)
|
63
|
-
text = "\n\n<h4>Attachments</h4>\n<ul>\n"
|
64
|
-
attachments.each_with_index do |att, i|
|
65
|
-
text += "<li>[<a href='#{att[:link]}' target='_blank'>#{att[:name]}</a>] <a href='#{att[:link]}' target='_blank'>#{att[:link]}</a></li>\n"
|
66
|
-
end
|
67
|
-
body + text + "</ul>"
|
68
|
-
end
|
69
|
-
|
70
54
|
end
|
71
55
|
|
72
56
|
end
|
data/lib/tuktuk/tuktuk.rb
CHANGED
@@ -5,114 +5,114 @@ require 'logger'
|
|
5
5
|
require 'tuktuk/package'
|
6
6
|
|
7
7
|
DEFAULTS = {
|
8
|
-
|
9
|
-
|
8
|
+
:retry_sleep => 10,
|
9
|
+
:max_attempts => 3
|
10
10
|
}
|
11
11
|
|
12
12
|
module Tuktuk
|
13
13
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
14
|
+
class << self
|
15
|
+
|
16
|
+
def deliver(message, opts = {})
|
17
|
+
config.merge(opts)
|
18
|
+
mail = Package.new(message)
|
19
|
+
mail['X-Mailer'] = opts[:smtp_server_name] || "Tuktuk SMTP #{VERSION}"
|
20
|
+
lookup_and_deliver(mail)
|
21
|
+
mail
|
22
|
+
end
|
23
|
+
|
24
|
+
def dkim=(dkim_opts)
|
25
|
+
Dkim::domain = dkim_opts[:domain]
|
26
|
+
Dkim::selector = dkim_opts[:selector]
|
27
|
+
Dkim::private_key = dkim_opts[:private_key]
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def config
|
33
|
+
@config ||= DEFAULTS
|
34
|
+
end
|
35
|
+
|
36
|
+
def use_dkim?
|
37
|
+
!Dkim::domain.nil?
|
38
|
+
end
|
39
|
+
|
40
|
+
def logger
|
41
|
+
@logger ||= Logger.new(config[:logfile])
|
42
|
+
end
|
43
|
+
|
44
|
+
def get_domain(email_address)
|
45
|
+
email_address[/@([a-z0-9\._-]+)/i, 1]
|
46
|
+
end
|
47
|
+
|
48
|
+
def success(destination)
|
49
|
+
logger.info("#{destination} - Successfully sent mail!")
|
50
|
+
end
|
51
|
+
|
52
|
+
def error(mail, destination, error, attempt = 1)
|
53
|
+
if attempt <= config[:max_attempts] && (error.is_a?(Net::SMTPServerBusy) or error.is_a?(EOFError))
|
54
|
+
logger.info "#{destination} - Got #{error.class.name} error. Retrying after #{config[:retry_sleep]} secs..."
|
55
|
+
sleep config[:retry_sleep]
|
56
|
+
lookup_and_deliver(mail, attempt+1)
|
57
|
+
else
|
58
|
+
error_message = error.respond_to?(:message) ? "#{error.message} [#{error.class.name}]" : error
|
59
|
+
logger.error("#{destination} - Unable to send: #{error_message}")
|
60
|
+
raise "Unable to send to #{destination}: #{error_message}"
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def smtp_servers_for_domain(domain)
|
65
|
+
res = Net::DNS::Resolver.new
|
66
|
+
if mx = res.mx(domain)
|
67
|
+
mx.sort {|x,y| x.preference <=> y.preference}.map {|rr| rr.exchange}
|
68
|
+
else
|
69
|
+
raise RuntimeError, "Could not locate MX records for domain #{domain}."
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def lookup_and_deliver(mail, attempt = 1)
|
74
|
+
raise "No destinations found! Forgot to pass the to: field?" if mail.destinations.empty?
|
75
|
+
|
76
|
+
mail.destinations.each do |destination|
|
77
|
+
|
78
|
+
domain = get_domain(destination)
|
79
|
+
servers = smtp_servers_for_domain(domain)
|
80
|
+
error(mail, destination, "Unknown host: #{domain}") && next if servers.empty?
|
81
|
+
|
82
|
+
last_error = nil
|
83
|
+
servers.each do |server|
|
84
|
+
begin
|
85
|
+
send_now(mail, server, destination)
|
86
|
+
break
|
87
|
+
rescue => e
|
88
|
+
last_error = e
|
89
|
+
end
|
90
|
+
end
|
91
|
+
error(mail, destination, last_error, attempt) if last_error
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
def send_now(mail, server, to)
|
96
|
+
raw_mail = use_dkim? ? Dkim.sign(mail.to_s).to_s : mail.to_s
|
97
|
+
|
98
|
+
from = mail.return_path || mail.sender || mail.from_addrs.first
|
99
|
+
logger.info "#{to} - Delivering email at #{server}..."
|
100
|
+
|
101
|
+
context = OpenSSL::SSL::SSLContext.new
|
102
|
+
context.verify_mode = OpenSSL::SSL::VERIFY_NONE # OpenSSL::SSL::VERIFY_PEER
|
103
|
+
|
104
|
+
domain = config[:domain] || get_domain(to)
|
105
|
+
|
106
|
+
smtp = Net::SMTP.new(server, nil)
|
107
|
+
smtp.enable_starttls_auto(context)
|
108
|
+
smtp.start(domain, nil, nil, nil) do |smtp|
|
109
|
+
result = smtp.send_message(raw_mail, from, to)
|
110
|
+
logger.info res.string
|
111
|
+
end
|
112
|
+
|
113
|
+
success(to)
|
114
|
+
end
|
115
|
+
|
116
|
+
end
|
117
117
|
|
118
118
|
end
|
data/lib/tuktuk/version.rb
CHANGED
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: tuktuk
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 25
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 1
|
9
|
-
-
|
10
|
-
version: 0.1.
|
9
|
+
- 1
|
10
|
+
version: 0.1.1
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- "Tom\xC3\xA1s Pollak"
|