bulkmail 0.2 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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: "0.2"
7
- date: 2006-10-27 00:00:00 +02:00
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
- - doc/rdoc/files
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:
@@ -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>&nbsp;&nbsp;
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">&lt;</span> <span class="ruby-identifier">size</span>
133
- 31: <span class="ruby-identifier">result</span> <span class="ruby-operator">&lt;&lt;</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>&nbsp;&nbsp;
90
- <a href="#M000005">send_bulk</a>&nbsp;&nbsp;
91
- <a href="#M000004">send_message</a>&nbsp;&nbsp;
92
- <a href="#M000001">server_settings</a>&nbsp;&nbsp;
93
- <a href="#M000003">smtp</a>&nbsp;&nbsp;
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">&quot;\r\n&quot;</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">&quot;%s: %s\r\n&quot;.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">&lt;&lt;</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">&quot;Sent message to #{list.join(', ')}&quot;</span>
189
- 99: <span class="ruby-keyword kw">rescue</span> =<span class="ruby-operator">&gt;</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">&quot;Failed to send to #{list.join(', ')}: #{e.message}\r\n#{e.backtrace.first}&quot;</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">&quot;Message to sent to #{succeeded.size} of #{recipients.size} recipients&quot;</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">&amp;&amp;</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">&lt;&lt;</span> <span class="ruby-constant">LINE_BREAK</span>
230
- 84: <span class="ruby-identifier">msg</span> <span class="ruby-operator">&lt;&lt;</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>