bulkmail 0.2 → 0.3.0
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/CHANGELOG +17 -1
- data/README +18 -20
- data/Rakefile +4 -2
- data/bin/bulkmail +19 -44
- data/doc/rdoc/created.rid +1 -1
- data/lib/bulkmail.rb +4 -110
- data/lib/bulkmail/dns_mx.rb +18 -0
- data/lib/bulkmail/message.rb +103 -0
- data/lib/bulkmail/sender.rb +90 -0
- data/lib/bulkmail/thread_pool.rb +113 -0
- metadata +17 -20
- data/doc/rdoc/classes/Array.html +0 -155
- data/doc/rdoc/classes/BulkMail.html +0 -310
- data/doc/rdoc/classes/String.html +0 -178
- data/doc/rdoc/classes/Symbol.html +0 -155
- data/doc/rdoc/files/CHANGELOG.html +0 -165
- data/doc/rdoc/files/COPYING.html +0 -129
- data/doc/rdoc/files/README.html +0 -160
- data/doc/rdoc/files/lib/bulkmail_rb.html +0 -108
- data/doc/rdoc/fr_class_index.html +0 -30
- data/doc/rdoc/fr_file_index.html +0 -30
- data/doc/rdoc/fr_method_index.html +0 -35
- data/doc/rdoc/index.html +0 -24
- data/doc/rdoc/rdoc-style.css +0 -208
@@ -0,0 +1,90 @@
|
|
1
|
+
require 'net/smtp'
|
2
|
+
|
3
|
+
module BulkMail
|
4
|
+
# Sender instances perform the actual work of sending an email. Each sender
|
5
|
+
# sets up a thread pool (by default with up to 20 threads) for performing the
|
6
|
+
# work. When creating a Sender instance, a hash of options is supplied:
|
7
|
+
#
|
8
|
+
# BulkMail::Sender.new({
|
9
|
+
# :list => addresses,
|
10
|
+
# :from => my_address,
|
11
|
+
# :helo => my_helo_domain,
|
12
|
+
# :concurrent => 50, # size of thread pool
|
13
|
+
# :message => message
|
14
|
+
# })
|
15
|
+
#
|
16
|
+
# To start sending, invoke Sender#start. The start method will block until
|
17
|
+
# all addresses have been processed.
|
18
|
+
class Sender
|
19
|
+
# Initializes a new instance with the supplied options hash, and creates a
|
20
|
+
# thread pool (with a default maximum size of 20).
|
21
|
+
def initialize(opts)
|
22
|
+
@opts = opts
|
23
|
+
@pool = ThreadPool.new(@opts[:concurrent] || 20)
|
24
|
+
@smtp_servers = {}
|
25
|
+
@mutex = Mutex.new
|
26
|
+
end
|
27
|
+
|
28
|
+
# Starts processing the addresses by sending each one a message, and waits
|
29
|
+
# for the thread pool to finish its work.
|
30
|
+
def start
|
31
|
+
@opts[:list].each {|a| @pool.process {send(a)}}
|
32
|
+
@pool.join
|
33
|
+
end
|
34
|
+
|
35
|
+
# returns an array of SMTP servers for the email address. If an invalid
|
36
|
+
# address is specified, an error is raised. SMTP servers for each email
|
37
|
+
# domain are memoized to improve performance.
|
38
|
+
def smtp_servers_for_addr(addr)
|
39
|
+
if (addr =~ /<(.*)@(.*)>/) or (addr =~ /(.*)@(.*)/)
|
40
|
+
domain = $2
|
41
|
+
else
|
42
|
+
raise RuntimeError, "Invalid email address."
|
43
|
+
end
|
44
|
+
@mutex.synchronize do
|
45
|
+
@smtp_servers[domain] ||= BulkMail.smtp_servers_for_domain(domain)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
# Sends an email to a recipient by trying any of the SMTP servers available
|
50
|
+
# for the recipient.
|
51
|
+
def send(addr)
|
52
|
+
servers = smtp_servers_for_addr(addr)
|
53
|
+
if servers.empty?
|
54
|
+
report_addr(addr, :error, 'Unknown domain')
|
55
|
+
return
|
56
|
+
end
|
57
|
+
servers.each do |server|
|
58
|
+
begin
|
59
|
+
send_message(server, addr)
|
60
|
+
report_addr(addr, :success)
|
61
|
+
return
|
62
|
+
rescue => e
|
63
|
+
report_addr(addr, :error, e.message)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
# Opens a connection to an SMTP server and sends the message.
|
69
|
+
def send_message(server, addr)
|
70
|
+
Net::SMTP.start(
|
71
|
+
server, nil, @opts[:helo], nil, nil, nil) do |smtp|
|
72
|
+
smtp.send_message @opts[:message].to_s, @opts[:from], addr
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
# Reports success or failure for the recipient.
|
77
|
+
def report_addr(addr, status, error = nil)
|
78
|
+
@mutex.synchronize do
|
79
|
+
case status
|
80
|
+
when :success:
|
81
|
+
puts "Sent mail to #{addr}"
|
82
|
+
File.open('sent.bulkmail', 'a') {|f| f.puts "#{addr}"}
|
83
|
+
when :error:
|
84
|
+
puts "Failed to send to #{addr}: #{error}"
|
85
|
+
File.open('failed.bulkmail', 'a') {|f| f.puts "#{addr}: #{error}"}
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
@@ -0,0 +1,113 @@
|
|
1
|
+
require 'thread'
|
2
|
+
|
3
|
+
# This class implements a pool of threads. The pool hands out blocks to be
|
4
|
+
# processed to any available worker thread. If no worker thread is available,
|
5
|
+
# the pool blocks until any of the workers have become available. The pool
|
6
|
+
# size can be specified when constructing the pool. For exmaple:
|
7
|
+
#
|
8
|
+
# pool = ThreadPool.new(10)
|
9
|
+
# 10.times {pool.process {sleep 3}}
|
10
|
+
# 10.times {pool.process {sleep 3}} # this will block for about 3 seconds.
|
11
|
+
# pool.join # this will block for about 3 more seconds.
|
12
|
+
class ThreadPool
|
13
|
+
# The Worker class starts a thread for performing work. A worker thread
|
14
|
+
# sleeps until it receives a block for processing, at which time it is
|
15
|
+
# considered busy. Once the block has been processed, the worker is
|
16
|
+
# considered available again.
|
17
|
+
class Worker
|
18
|
+
# Starts the worker thread.
|
19
|
+
def initialize
|
20
|
+
@mutex = Mutex.new
|
21
|
+
@thread = Thread.new do
|
22
|
+
while true
|
23
|
+
sleep 0.001
|
24
|
+
block = get_block
|
25
|
+
if block
|
26
|
+
block.call
|
27
|
+
reset_block
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
# Returns the block to be processed, if any.
|
34
|
+
def get_block
|
35
|
+
@mutex.synchronize {@block}
|
36
|
+
end
|
37
|
+
|
38
|
+
# Sets the block to be processed.
|
39
|
+
def set_block(block)
|
40
|
+
@mutex.synchronize {@block = block}
|
41
|
+
end
|
42
|
+
|
43
|
+
# Resets the block instance variable to signify that the worker
|
44
|
+
# is available.
|
45
|
+
def reset_block
|
46
|
+
@mutex.synchronize {@block = nil}
|
47
|
+
end
|
48
|
+
|
49
|
+
# Returns true if the worker is busy processing a block.
|
50
|
+
def busy?
|
51
|
+
@mutex.synchronize {!@block.nil?}
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
attr_accessor :max_size
|
56
|
+
attr_reader :workers
|
57
|
+
|
58
|
+
# Creates a new pool with a default maximum size of 10.
|
59
|
+
def initialize(max_size = 10)
|
60
|
+
@max_size = max_size
|
61
|
+
@workers = []
|
62
|
+
@mutex = Mutex.new
|
63
|
+
end
|
64
|
+
|
65
|
+
# Returns the number of workers in the pool.
|
66
|
+
def size
|
67
|
+
@mutex.synchronize {@workers.size}
|
68
|
+
end
|
69
|
+
|
70
|
+
# Returns true if any of the workers in the pool are busy.
|
71
|
+
def busy?
|
72
|
+
@mutex.synchronize {@workers.any? {|w| w.busy?}}
|
73
|
+
end
|
74
|
+
|
75
|
+
# Blocks until all workers have become available.
|
76
|
+
def join
|
77
|
+
sleep 0.01 while busy?
|
78
|
+
end
|
79
|
+
|
80
|
+
# Hands the block to an available worker. If no workers are available, this
|
81
|
+
# method will block until one becomes available.
|
82
|
+
def process(&block)
|
83
|
+
wait_for_worker.set_block(block)
|
84
|
+
end
|
85
|
+
|
86
|
+
# Waits for a worker to become available.
|
87
|
+
def wait_for_worker
|
88
|
+
while true
|
89
|
+
worker = find_available_worker
|
90
|
+
return worker if worker
|
91
|
+
sleep 0.01
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
# Returns an available worker or a new worker if the maximum pool size
|
96
|
+
# has not been reached.
|
97
|
+
def find_available_worker
|
98
|
+
@mutex.synchronize {free_worker || create_worker}
|
99
|
+
end
|
100
|
+
|
101
|
+
# Returns the first available worker.
|
102
|
+
def free_worker
|
103
|
+
@workers.each {|w| return w unless w.busy?}; nil
|
104
|
+
end
|
105
|
+
|
106
|
+
# Creates a worker if the maximum pool size has not been reached.
|
107
|
+
def create_worker
|
108
|
+
return nil if @workers.size >= @max_size
|
109
|
+
worker = Worker.new
|
110
|
+
@workers << worker
|
111
|
+
worker
|
112
|
+
end
|
113
|
+
end
|
metadata
CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.9.0
|
|
3
3
|
specification_version: 1
|
4
4
|
name: bulkmail
|
5
5
|
version: !ruby/object:Gem::Version
|
6
|
-
version:
|
7
|
-
date:
|
6
|
+
version: 0.3.0
|
7
|
+
date: 2007-01-12 00:00:00 +02:00
|
8
8
|
summary: Ruby bulk-mailer.
|
9
9
|
require_paths:
|
10
10
|
- lib
|
@@ -34,24 +34,13 @@ files:
|
|
34
34
|
- Rakefile
|
35
35
|
- bin/bulkmail
|
36
36
|
- doc/rdoc
|
37
|
-
- doc/rdoc/classes
|
38
37
|
- doc/rdoc/created.rid
|
39
|
-
-
|
40
|
-
- doc/rdoc/fr_class_index.html
|
41
|
-
- doc/rdoc/fr_file_index.html
|
42
|
-
- doc/rdoc/fr_method_index.html
|
43
|
-
- doc/rdoc/index.html
|
44
|
-
- doc/rdoc/rdoc-style.css
|
45
|
-
- doc/rdoc/classes/Array.html
|
46
|
-
- doc/rdoc/classes/BulkMail.html
|
47
|
-
- doc/rdoc/classes/String.html
|
48
|
-
- doc/rdoc/classes/Symbol.html
|
49
|
-
- doc/rdoc/files/CHANGELOG.html
|
50
|
-
- doc/rdoc/files/COPYING.html
|
51
|
-
- doc/rdoc/files/lib
|
52
|
-
- doc/rdoc/files/README.html
|
53
|
-
- doc/rdoc/files/lib/bulkmail_rb.html
|
38
|
+
- lib/bulkmail
|
54
39
|
- lib/bulkmail.rb
|
40
|
+
- lib/bulkmail/dns_mx.rb
|
41
|
+
- lib/bulkmail/message.rb
|
42
|
+
- lib/bulkmail/sender.rb
|
43
|
+
- lib/bulkmail/thread_pool.rb
|
55
44
|
- CHANGELOG
|
56
45
|
test_files: []
|
57
46
|
|
@@ -79,5 +68,13 @@ extensions: []
|
|
79
68
|
|
80
69
|
requirements: []
|
81
70
|
|
82
|
-
dependencies:
|
83
|
-
|
71
|
+
dependencies:
|
72
|
+
- !ruby/object:Gem::Dependency
|
73
|
+
name: pNet-DNS
|
74
|
+
version_requirement:
|
75
|
+
version_requirements: !ruby/object:Gem::Version::Requirement
|
76
|
+
requirements:
|
77
|
+
- - ">"
|
78
|
+
- !ruby/object:Gem::Version
|
79
|
+
version: 0.0.0
|
80
|
+
version:
|
data/doc/rdoc/classes/Array.html
DELETED
@@ -1,155 +0,0 @@
|
|
1
|
-
<?xml version="1.0" encoding="iso-8859-1"?>
|
2
|
-
<!DOCTYPE html
|
3
|
-
PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
4
|
-
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
5
|
-
|
6
|
-
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
7
|
-
<head>
|
8
|
-
<title>Class: Array</title>
|
9
|
-
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
|
10
|
-
<meta http-equiv="Content-Script-Type" content="text/javascript" />
|
11
|
-
<link rel="stylesheet" href=".././rdoc-style.css" type="text/css" media="screen" />
|
12
|
-
<script type="text/javascript">
|
13
|
-
// <![CDATA[
|
14
|
-
|
15
|
-
function popupCode( url ) {
|
16
|
-
window.open(url, "Code", "resizable=yes,scrollbars=yes,toolbar=no,status=no,height=150,width=400")
|
17
|
-
}
|
18
|
-
|
19
|
-
function toggleCode( id ) {
|
20
|
-
if ( document.getElementById )
|
21
|
-
elem = document.getElementById( id );
|
22
|
-
else if ( document.all )
|
23
|
-
elem = eval( "document.all." + id );
|
24
|
-
else
|
25
|
-
return false;
|
26
|
-
|
27
|
-
elemStyle = elem.style;
|
28
|
-
|
29
|
-
if ( elemStyle.display != "block" ) {
|
30
|
-
elemStyle.display = "block"
|
31
|
-
} else {
|
32
|
-
elemStyle.display = "none"
|
33
|
-
}
|
34
|
-
|
35
|
-
return true;
|
36
|
-
}
|
37
|
-
|
38
|
-
// Make codeblocks hidden by default
|
39
|
-
document.writeln( "<style type=\"text/css\">div.method-source-code { display: none }</style>" )
|
40
|
-
|
41
|
-
// ]]>
|
42
|
-
</script>
|
43
|
-
|
44
|
-
</head>
|
45
|
-
<body>
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
<div id="classHeader">
|
50
|
-
<table class="header-table">
|
51
|
-
<tr class="top-aligned-row">
|
52
|
-
<td><strong>Class</strong></td>
|
53
|
-
<td class="class-name-in-header">Array</td>
|
54
|
-
</tr>
|
55
|
-
<tr class="top-aligned-row">
|
56
|
-
<td><strong>In:</strong></td>
|
57
|
-
<td>
|
58
|
-
<a href="../files/lib/bulkmail_rb.html">
|
59
|
-
lib/bulkmail.rb
|
60
|
-
</a>
|
61
|
-
<br />
|
62
|
-
</td>
|
63
|
-
</tr>
|
64
|
-
|
65
|
-
<tr class="top-aligned-row">
|
66
|
-
<td><strong>Parent:</strong></td>
|
67
|
-
<td>
|
68
|
-
Object
|
69
|
-
</td>
|
70
|
-
</tr>
|
71
|
-
</table>
|
72
|
-
</div>
|
73
|
-
<!-- banner header -->
|
74
|
-
|
75
|
-
<div id="bodyContent">
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
<div id="contextContent">
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
</div>
|
84
|
-
|
85
|
-
<div id="method-list">
|
86
|
-
<h3 class="section-bar">Methods</h3>
|
87
|
-
|
88
|
-
<div class="name-list">
|
89
|
-
<a href="#M000007">split</a>
|
90
|
-
</div>
|
91
|
-
</div>
|
92
|
-
|
93
|
-
</div>
|
94
|
-
|
95
|
-
|
96
|
-
<!-- if includes -->
|
97
|
-
|
98
|
-
<div id="section">
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
<!-- if method_list -->
|
108
|
-
<div id="methods">
|
109
|
-
<h3 class="section-bar">Public Instance methods</h3>
|
110
|
-
|
111
|
-
<div id="method-M000007" class="method-detail">
|
112
|
-
<a name="M000007"></a>
|
113
|
-
|
114
|
-
<div class="method-heading">
|
115
|
-
<a href="#M000007" class="method-signature">
|
116
|
-
<span class="method-name">split</span><span class="method-args">(batch)</span>
|
117
|
-
</a>
|
118
|
-
</div>
|
119
|
-
|
120
|
-
<div class="method-description">
|
121
|
-
<p>
|
122
|
-
Splits the array into smaller arrays of fixed size
|
123
|
-
</p>
|
124
|
-
<p><a class="source-toggle" href="#"
|
125
|
-
onclick="toggleCode('M000007-source');return false;">[Source]</a></p>
|
126
|
-
<div class="method-source-code" id="M000007-source">
|
127
|
-
<pre>
|
128
|
-
<span class="ruby-comment cmt"># File lib/bulkmail.rb, line 27</span>
|
129
|
-
27: <span class="ruby-keyword kw">def</span> <span class="ruby-identifier">split</span>(<span class="ruby-identifier">batch</span>)
|
130
|
-
28: <span class="ruby-identifier">result</span> = []
|
131
|
-
29: <span class="ruby-identifier">idx</span> = <span class="ruby-value">0</span>
|
132
|
-
30: <span class="ruby-keyword kw">while</span> <span class="ruby-identifier">idx</span> <span class="ruby-operator"><</span> <span class="ruby-identifier">size</span>
|
133
|
-
31: <span class="ruby-identifier">result</span> <span class="ruby-operator"><<</span> <span class="ruby-identifier">slice</span>(<span class="ruby-identifier">idx</span>, <span class="ruby-identifier">batch</span>)
|
134
|
-
32: <span class="ruby-identifier">idx</span> <span class="ruby-operator">+=</span> <span class="ruby-identifier">batch</span>
|
135
|
-
33: <span class="ruby-keyword kw">end</span>
|
136
|
-
34: <span class="ruby-identifier">result</span>
|
137
|
-
35: <span class="ruby-keyword kw">end</span>
|
138
|
-
</pre>
|
139
|
-
</div>
|
140
|
-
</div>
|
141
|
-
</div>
|
142
|
-
|
143
|
-
|
144
|
-
</div>
|
145
|
-
|
146
|
-
|
147
|
-
</div>
|
148
|
-
|
149
|
-
|
150
|
-
<div id="validator-badges">
|
151
|
-
<p><small><a href="http://validator.w3.org/check/referer">[Validate]</a></small></p>
|
152
|
-
</div>
|
153
|
-
|
154
|
-
</body>
|
155
|
-
</html>
|
@@ -1,310 +0,0 @@
|
|
1
|
-
<?xml version="1.0" encoding="iso-8859-1"?>
|
2
|
-
<!DOCTYPE html
|
3
|
-
PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
4
|
-
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
5
|
-
|
6
|
-
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
7
|
-
<head>
|
8
|
-
<title>Class: BulkMail</title>
|
9
|
-
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
|
10
|
-
<meta http-equiv="Content-Script-Type" content="text/javascript" />
|
11
|
-
<link rel="stylesheet" href=".././rdoc-style.css" type="text/css" media="screen" />
|
12
|
-
<script type="text/javascript">
|
13
|
-
// <![CDATA[
|
14
|
-
|
15
|
-
function popupCode( url ) {
|
16
|
-
window.open(url, "Code", "resizable=yes,scrollbars=yes,toolbar=no,status=no,height=150,width=400")
|
17
|
-
}
|
18
|
-
|
19
|
-
function toggleCode( id ) {
|
20
|
-
if ( document.getElementById )
|
21
|
-
elem = document.getElementById( id );
|
22
|
-
else if ( document.all )
|
23
|
-
elem = eval( "document.all." + id );
|
24
|
-
else
|
25
|
-
return false;
|
26
|
-
|
27
|
-
elemStyle = elem.style;
|
28
|
-
|
29
|
-
if ( elemStyle.display != "block" ) {
|
30
|
-
elemStyle.display = "block"
|
31
|
-
} else {
|
32
|
-
elemStyle.display = "none"
|
33
|
-
}
|
34
|
-
|
35
|
-
return true;
|
36
|
-
}
|
37
|
-
|
38
|
-
// Make codeblocks hidden by default
|
39
|
-
document.writeln( "<style type=\"text/css\">div.method-source-code { display: none }</style>" )
|
40
|
-
|
41
|
-
// ]]>
|
42
|
-
</script>
|
43
|
-
|
44
|
-
</head>
|
45
|
-
<body>
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
<div id="classHeader">
|
50
|
-
<table class="header-table">
|
51
|
-
<tr class="top-aligned-row">
|
52
|
-
<td><strong>Class</strong></td>
|
53
|
-
<td class="class-name-in-header">BulkMail</td>
|
54
|
-
</tr>
|
55
|
-
<tr class="top-aligned-row">
|
56
|
-
<td><strong>In:</strong></td>
|
57
|
-
<td>
|
58
|
-
<a href="../files/lib/bulkmail_rb.html">
|
59
|
-
lib/bulkmail.rb
|
60
|
-
</a>
|
61
|
-
<br />
|
62
|
-
</td>
|
63
|
-
</tr>
|
64
|
-
|
65
|
-
<tr class="top-aligned-row">
|
66
|
-
<td><strong>Parent:</strong></td>
|
67
|
-
<td>
|
68
|
-
Object
|
69
|
-
</td>
|
70
|
-
</tr>
|
71
|
-
</table>
|
72
|
-
</div>
|
73
|
-
<!-- banner header -->
|
74
|
-
|
75
|
-
<div id="bodyContent">
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
<div id="contextContent">
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
</div>
|
84
|
-
|
85
|
-
<div id="method-list">
|
86
|
-
<h3 class="section-bar">Methods</h3>
|
87
|
-
|
88
|
-
<div class="name-list">
|
89
|
-
<a href="#M000002">format_headers</a>
|
90
|
-
<a href="#M000005">send_bulk</a>
|
91
|
-
<a href="#M000004">send_message</a>
|
92
|
-
<a href="#M000001">server_settings</a>
|
93
|
-
<a href="#M000003">smtp</a>
|
94
|
-
</div>
|
95
|
-
</div>
|
96
|
-
|
97
|
-
</div>
|
98
|
-
|
99
|
-
|
100
|
-
<!-- if includes -->
|
101
|
-
|
102
|
-
<div id="section">
|
103
|
-
|
104
|
-
|
105
|
-
<div id="constants-list">
|
106
|
-
<h3 class="section-bar">Constants</h3>
|
107
|
-
|
108
|
-
<div class="name-list">
|
109
|
-
<table summary="Constants">
|
110
|
-
<tr class="top-aligned-row context-row">
|
111
|
-
<td class="context-item-name">LINE_BREAK</td>
|
112
|
-
<td>=</td>
|
113
|
-
<td class="context-item-value">"\r\n"</td>
|
114
|
-
</tr>
|
115
|
-
<tr class="top-aligned-row context-row">
|
116
|
-
<td class="context-item-name">HEADER_FMT</td>
|
117
|
-
<td>=</td>
|
118
|
-
<td class="context-item-value">"%s: %s\r\n".freeze</td>
|
119
|
-
</tr>
|
120
|
-
</table>
|
121
|
-
</div>
|
122
|
-
</div>
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
<!-- if method_list -->
|
130
|
-
<div id="methods">
|
131
|
-
<h3 class="section-bar">Public Class methods</h3>
|
132
|
-
|
133
|
-
<div id="method-M000002" class="method-detail">
|
134
|
-
<a name="M000002"></a>
|
135
|
-
|
136
|
-
<div class="method-heading">
|
137
|
-
<a href="#M000002" class="method-signature">
|
138
|
-
<span class="method-name">format_headers</span><span class="method-args">(headers)</span>
|
139
|
-
</a>
|
140
|
-
</div>
|
141
|
-
|
142
|
-
<div class="method-description">
|
143
|
-
<p>
|
144
|
-
Returns the message headers formatted
|
145
|
-
</p>
|
146
|
-
<p><a class="source-toggle" href="#"
|
147
|
-
onclick="toggleCode('M000002-source');return false;">[Source]</a></p>
|
148
|
-
<div class="method-source-code" id="M000002-source">
|
149
|
-
<pre>
|
150
|
-
<span class="ruby-comment cmt"># File lib/bulkmail.rb, line 57</span>
|
151
|
-
57: <span class="ruby-keyword kw">def</span> <span class="ruby-keyword kw">self</span>.<span class="ruby-identifier">format_headers</span>(<span class="ruby-identifier">headers</span>)
|
152
|
-
58: <span class="ruby-identifier">headers</span>.<span class="ruby-identifier">inject</span>(<span class="ruby-value str">''</span>) <span class="ruby-keyword kw">do</span> <span class="ruby-operator">|</span><span class="ruby-identifier">m</span>, <span class="ruby-identifier">kv</span><span class="ruby-operator">|</span>
|
153
|
-
59: <span class="ruby-identifier">m</span> <span class="ruby-operator"><<</span> (<span class="ruby-constant">HEADER_FMT</span> <span class="ruby-operator">%</span> [<span class="ruby-identifier">kv</span>[<span class="ruby-value">0</span>].<span class="ruby-identifier">to_header</span>, <span class="ruby-identifier">kv</span>[<span class="ruby-value">1</span>]])
|
154
|
-
60: <span class="ruby-keyword kw">end</span>
|
155
|
-
61: <span class="ruby-keyword kw">end</span>
|
156
|
-
</pre>
|
157
|
-
</div>
|
158
|
-
</div>
|
159
|
-
</div>
|
160
|
-
|
161
|
-
<div id="method-M000005" class="method-detail">
|
162
|
-
<a name="M000005"></a>
|
163
|
-
|
164
|
-
<div class="method-heading">
|
165
|
-
<a href="#M000005" class="method-signature">
|
166
|
-
<span class="method-name">send_bulk</span><span class="method-args">(sender, recipients, body, headers)</span>
|
167
|
-
</a>
|
168
|
-
</div>
|
169
|
-
|
170
|
-
<div class="method-description">
|
171
|
-
<p>
|
172
|
-
Sends bulk mail to a large number of recipients.
|
173
|
-
</p>
|
174
|
-
<p><a class="source-toggle" href="#"
|
175
|
-
onclick="toggleCode('M000005-source');return false;">[Source]</a></p>
|
176
|
-
<div class="method-source-code" id="M000005-source">
|
177
|
-
<pre>
|
178
|
-
<span class="ruby-comment cmt"># File lib/bulkmail.rb, line 89</span>
|
179
|
-
89: <span class="ruby-keyword kw">def</span> <span class="ruby-keyword kw">self</span>.<span class="ruby-identifier">send_bulk</span>(<span class="ruby-identifier">sender</span>, <span class="ruby-identifier">recipients</span>, <span class="ruby-identifier">body</span>, <span class="ruby-identifier">headers</span>)
|
180
|
-
90: <span class="ruby-identifier">failed</span> = []
|
181
|
-
91: <span class="ruby-identifier">succeeded</span> = []
|
182
|
-
92: <span class="ruby-identifier">headers</span>[<span class="ruby-identifier">:from</span>] = <span class="ruby-identifier">headers</span>[<span class="ruby-identifier">:to</span>] = <span class="ruby-identifier">sender</span>
|
183
|
-
93: <span class="ruby-identifier">recipients</span> = <span class="ruby-identifier">recipients</span>.<span class="ruby-identifier">map</span> {<span class="ruby-operator">|</span><span class="ruby-identifier">r</span><span class="ruby-operator">|</span> <span class="ruby-identifier">r</span>.<span class="ruby-identifier">email_addr</span>}.<span class="ruby-identifier">compact</span>
|
184
|
-
94: <span class="ruby-identifier">recipients</span>.<span class="ruby-identifier">split</span>(<span class="ruby-value">10</span>).<span class="ruby-identifier">each</span> <span class="ruby-keyword kw">do</span> <span class="ruby-operator">|</span><span class="ruby-identifier">list</span><span class="ruby-operator">|</span>
|
185
|
-
95: <span class="ruby-keyword kw">begin</span>
|
186
|
-
96: <span class="ruby-identifier">smtp</span> {<span class="ruby-operator">|</span><span class="ruby-identifier">s</span><span class="ruby-operator">|</span> <span class="ruby-identifier">send_message</span>(<span class="ruby-identifier">s</span>, <span class="ruby-identifier">sender</span>.<span class="ruby-identifier">email_addr</span>, <span class="ruby-identifier">list</span>, <span class="ruby-identifier">body</span>, <span class="ruby-identifier">headers</span>)}
|
187
|
-
97: <span class="ruby-identifier">succeeded</span>.<span class="ruby-identifier">concat</span> <span class="ruby-identifier">list</span>
|
188
|
-
98: <span class="ruby-identifier">puts</span> <span class="ruby-node">"Sent message to #{list.join(', ')}"</span>
|
189
|
-
99: <span class="ruby-keyword kw">rescue</span> =<span class="ruby-operator">></span> <span class="ruby-identifier">e</span>
|
190
|
-
100: <span class="ruby-identifier">failed</span>.<span class="ruby-identifier">concat</span> <span class="ruby-identifier">list</span>
|
191
|
-
101: <span class="ruby-identifier">puts</span> <span class="ruby-node">"Failed to send to #{list.join(', ')}: #{e.message}\r\n#{e.backtrace.first}"</span>
|
192
|
-
102: <span class="ruby-keyword kw">end</span>
|
193
|
-
103: <span class="ruby-keyword kw">end</span>
|
194
|
-
104: <span class="ruby-comment cmt"># log failed addresses</span>
|
195
|
-
105: <span class="ruby-keyword kw">unless</span> <span class="ruby-identifier">failed</span>.<span class="ruby-identifier">empty?</span>
|
196
|
-
106: <span class="ruby-constant">File</span>.<span class="ruby-identifier">open</span>(<span class="ruby-value str">'failed.bulkmail'</span>, <span class="ruby-value str">'w'</span>) {<span class="ruby-operator">|</span><span class="ruby-identifier">f</span><span class="ruby-operator">|</span> <span class="ruby-identifier">failed</span>.<span class="ruby-identifier">each</span> {<span class="ruby-operator">|</span><span class="ruby-identifier">l</span><span class="ruby-operator">|</span><span class="ruby-identifier">f</span>.<span class="ruby-identifier">puts</span> <span class="ruby-identifier">l</span>}}
|
197
|
-
107: <span class="ruby-keyword kw">end</span>
|
198
|
-
108: <span class="ruby-identifier">puts</span> <span class="ruby-node">"Message to sent to #{succeeded.size} of #{recipients.size} recipients"</span>
|
199
|
-
109: <span class="ruby-keyword kw">end</span>
|
200
|
-
</pre>
|
201
|
-
</div>
|
202
|
-
</div>
|
203
|
-
</div>
|
204
|
-
|
205
|
-
<div id="method-M000004" class="method-detail">
|
206
|
-
<a name="M000004"></a>
|
207
|
-
|
208
|
-
<div class="method-heading">
|
209
|
-
<a href="#M000004" class="method-signature">
|
210
|
-
<span class="method-name">send_message</span><span class="method-args">(smtp, from, to, body, headers = nil)</span>
|
211
|
-
</a>
|
212
|
-
</div>
|
213
|
-
|
214
|
-
<div class="method-description">
|
215
|
-
<p>
|
216
|
-
Sends an email
|
217
|
-
</p>
|
218
|
-
<p><a class="source-toggle" href="#"
|
219
|
-
onclick="toggleCode('M000004-source');return false;">[Source]</a></p>
|
220
|
-
<div class="method-source-code" id="M000004-source">
|
221
|
-
<pre>
|
222
|
-
<span class="ruby-comment cmt"># File lib/bulkmail.rb, line 77</span>
|
223
|
-
77: <span class="ruby-keyword kw">def</span> <span class="ruby-keyword kw">self</span>.<span class="ruby-identifier">send_message</span>(<span class="ruby-identifier">smtp</span>, <span class="ruby-identifier">from</span>, <span class="ruby-identifier">to</span>, <span class="ruby-identifier">body</span>, <span class="ruby-identifier">headers</span> = <span class="ruby-keyword kw">nil</span>)
|
224
|
-
78: <span class="ruby-keyword kw">if</span> <span class="ruby-identifier">headers</span> <span class="ruby-operator">&&</span> <span class="ruby-operator">!</span><span class="ruby-identifier">headers</span>.<span class="ruby-identifier">empty?</span>
|
225
|
-
79: <span class="ruby-identifier">msg</span> = <span class="ruby-identifier">format_headers</span>(<span class="ruby-identifier">headers</span>)
|
226
|
-
80: <span class="ruby-keyword kw">else</span>
|
227
|
-
81: <span class="ruby-identifier">msg</span> = <span class="ruby-constant">LINE_BREAK</span>
|
228
|
-
82: <span class="ruby-keyword kw">end</span>
|
229
|
-
83: <span class="ruby-identifier">msg</span> <span class="ruby-operator"><<</span> <span class="ruby-constant">LINE_BREAK</span>
|
230
|
-
84: <span class="ruby-identifier">msg</span> <span class="ruby-operator"><<</span> <span class="ruby-identifier">body</span>
|
231
|
-
85: <span class="ruby-identifier">smtp</span>.<span class="ruby-identifier">send_message</span> <span class="ruby-identifier">msg</span>, <span class="ruby-identifier">from</span>, <span class="ruby-identifier">to</span>
|
232
|
-
86: <span class="ruby-keyword kw">end</span>
|
233
|
-
</pre>
|
234
|
-
</div>
|
235
|
-
</div>
|
236
|
-
</div>
|
237
|
-
|
238
|
-
<div id="method-M000001" class="method-detail">
|
239
|
-
<a name="M000001"></a>
|
240
|
-
|
241
|
-
<div class="method-heading">
|
242
|
-
<a href="#M000001" class="method-signature">
|
243
|
-
<span class="method-name">server_settings</span><span class="method-args">()</span>
|
244
|
-
</a>
|
245
|
-
</div>
|
246
|
-
|
247
|
-
<div class="method-description">
|
248
|
-
<p>
|
249
|
-
Returns the <a href="BulkMail.html#M000001">server_settings</a> hash
|
250
|
-
</p>
|
251
|
-
<p><a class="source-toggle" href="#"
|
252
|
-
onclick="toggleCode('M000001-source');return false;">[Source]</a></p>
|
253
|
-
<div class="method-source-code" id="M000001-source">
|
254
|
-
<pre>
|
255
|
-
<span class="ruby-comment cmt"># File lib/bulkmail.rb, line 49</span>
|
256
|
-
49: <span class="ruby-keyword kw">def</span> <span class="ruby-keyword kw">self</span>.<span class="ruby-identifier">server_settings</span>
|
257
|
-
50: <span class="ruby-ivar">@@server_settings</span>
|
258
|
-
51: <span class="ruby-keyword kw">end</span>
|
259
|
-
</pre>
|
260
|
-
</div>
|
261
|
-
</div>
|
262
|
-
</div>
|
263
|
-
|
264
|
-
<div id="method-M000003" class="method-detail">
|
265
|
-
<a name="M000003"></a>
|
266
|
-
|
267
|
-
<div class="method-heading">
|
268
|
-
<a href="#M000003" class="method-signature">
|
269
|
-
<span class="method-name">smtp</span><span class="method-args">() {|smtp| ...}</span>
|
270
|
-
</a>
|
271
|
-
</div>
|
272
|
-
|
273
|
-
<div class="method-description">
|
274
|
-
<p>
|
275
|
-
Starts an SMTP session and yields
|
276
|
-
</p>
|
277
|
-
<p><a class="source-toggle" href="#"
|
278
|
-
onclick="toggleCode('M000003-source');return false;">[Source]</a></p>
|
279
|
-
<div class="method-source-code" id="M000003-source">
|
280
|
-
<pre>
|
281
|
-
<span class="ruby-comment cmt"># File lib/bulkmail.rb, line 64</span>
|
282
|
-
64: <span class="ruby-keyword kw">def</span> <span class="ruby-keyword kw">self</span>.<span class="ruby-identifier">smtp</span>
|
283
|
-
65: <span class="ruby-constant">Net</span><span class="ruby-operator">::</span><span class="ruby-constant">SMTP</span>.<span class="ruby-identifier">start</span>(
|
284
|
-
66: <span class="ruby-ivar">@@server_settings</span>[<span class="ruby-identifier">:host</span>],
|
285
|
-
67: <span class="ruby-ivar">@@server_settings</span>[<span class="ruby-identifier">:port</span>],
|
286
|
-
68: <span class="ruby-ivar">@@server_settings</span>[<span class="ruby-identifier">:helo_domain</span>] <span class="ruby-operator">||</span> <span class="ruby-ivar">@@server_settings</span>[<span class="ruby-identifier">:host</span>],
|
287
|
-
69: <span class="ruby-ivar">@@server_settings</span>[<span class="ruby-identifier">:user</span>],
|
288
|
-
70: <span class="ruby-ivar">@@server_settings</span>[<span class="ruby-identifier">:password</span>],
|
289
|
-
71: <span class="ruby-ivar">@@server_settings</span>[<span class="ruby-identifier">:auth</span>]) <span class="ruby-keyword kw">do</span> <span class="ruby-operator">|</span><span class="ruby-identifier">smtp</span><span class="ruby-operator">|</span>
|
290
|
-
72: <span class="ruby-keyword kw">yield</span> <span class="ruby-identifier">smtp</span>
|
291
|
-
73: <span class="ruby-keyword kw">end</span>
|
292
|
-
74: <span class="ruby-keyword kw">end</span>
|
293
|
-
</pre>
|
294
|
-
</div>
|
295
|
-
</div>
|
296
|
-
</div>
|
297
|
-
|
298
|
-
|
299
|
-
</div>
|
300
|
-
|
301
|
-
|
302
|
-
</div>
|
303
|
-
|
304
|
-
|
305
|
-
<div id="validator-badges">
|
306
|
-
<p><small><a href="http://validator.w3.org/check/referer">[Validate]</a></small></p>
|
307
|
-
</div>
|
308
|
-
|
309
|
-
</body>
|
310
|
-
</html>
|