bulkmail 0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (7) hide show
  1. data/CHANGELOG +25 -0
  2. data/COPYING +18 -0
  3. data/README +42 -0
  4. data/Rakefile +83 -0
  5. data/bin/bulkmail +91 -0
  6. data/lib/bulkmail.rb +75 -0
  7. metadata +73 -0
@@ -0,0 +1,25 @@
1
+ *0.1*
2
+
3
+ * Add INT trap.
4
+
5
+ * Changed reporting of success/error.
6
+
7
+ * Tweaks to binary script.
8
+
9
+ * Basically functional.
10
+
11
+ * Rewrote everything.
12
+
13
+ * Wrote preliminary bulkmail.rb.
14
+
15
+ * Wrote preliminary spec.
16
+
17
+ * Fixed Rakefile for spec to work.
18
+
19
+ * Created lib and spec directories.
20
+
21
+ * Wrote Rakefile.
22
+
23
+ * Preliminary content.
24
+
25
+ * Created basic project structure.
data/COPYING ADDED
@@ -0,0 +1,18 @@
1
+ Copyright (c) 2006 Sharon Rosner
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to
5
+ deal in the Software without restriction, including without limitation the
6
+ rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
7
+ sell copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in
11
+ all copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
16
+ THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
17
+ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
18
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README ADDED
@@ -0,0 +1,42 @@
1
+ = about bulkmail
2
+
3
+ Bulkmail is a simple bulk mailing utility in Ruby. It takes a content file and a recipients file, and sends the content to each address listed in the recipients file. I wrote it to be as simple as possible, and as a basic alternative to commercial bulk-mailers. The free ones suck.
4
+
5
+ == Usage
6
+
7
+ === From the Command Line
8
+
9
+ bulkmail <options>
10
+
11
+ where the options are:
12
+ [--recipients, -r] recipients file name
13
+ [--content, -c] content file name
14
+ [--subject, -s] subject
15
+ [--from, -f] from
16
+ [--host, -h] smtp hostname (if none is specified localhost is presumed)
17
+ [--user, -u] user name (if authentication is needed)
18
+ [--password, -p] password (if authentication is needed)
19
+ [--auth, -a] authentication type
20
+ [--mime, -m] message mime type.
21
+
22
+ You can also include headers in the content file, provided they are followed by a blank line. For example:
23
+
24
+ Subject: Baroque Concert this Thursday
25
+
26
+ Hello Baroque Lovers,
27
+ A special concert is about to take place this Thursday at...
28
+
29
+ === From Ruby
30
+
31
+ BulkMail.send(options)
32
+
33
+ Valid options are:
34
+ [:recipients_file] recipients file name
35
+ [:content_file] content file name
36
+ [:subject] subject
37
+ [:from] from
38
+ [:additional_headers] additional headers
39
+
40
+ You can set server settings in the same fashion as ActionMailer by using the convenience method:
41
+
42
+ BulkMail.server_settings[:address] = 'mail.example.com'
@@ -0,0 +1,83 @@
1
+ require 'rake'
2
+ require 'rake/clean'
3
+ require 'rake/gempackagetask'
4
+ require 'rake/rdoctask'
5
+ require 'rake/testtask'
6
+ require 'fileutils'
7
+ include FileUtils
8
+
9
+ NAME = "bulkmail"
10
+ VERS = "0.1"
11
+ CLEAN.include ['**/.*.sw?', '*.gem', '.config']
12
+ RDOC_OPTS = ['--quiet', '--title', "Bulkmail Documentation",
13
+ "--opname", "index.html",
14
+ "--line-numbers",
15
+ "--main", "README",
16
+ "--inline-source"]
17
+
18
+ desc "Packages up bulkmail."
19
+ task :default => [:package]
20
+ task :package => [:clean]
21
+
22
+ task :doc => [:rdoc]
23
+
24
+ Rake::RDocTask.new do |rdoc|
25
+ rdoc.rdoc_dir = 'doc/rdoc'
26
+ rdoc.options += RDOC_OPTS
27
+ rdoc.main = "README"
28
+ rdoc.title = "Bulkmail Documentation"
29
+ rdoc.rdoc_files.add ['README', 'CHANGELOG', 'COPYING', 'lib/*.rb']
30
+ end
31
+
32
+ spec = Gem::Specification.new do |s|
33
+ s.name = NAME
34
+ s.version = VERS
35
+ s.platform = Gem::Platform::RUBY
36
+ s.has_rdoc = true
37
+ s.extra_rdoc_files = ["README", "CHANGELOG", "COPYING"]
38
+ s.rdoc_options += RDOC_OPTS +
39
+ ['--exclude', '^(examples|extras)\/', '--exclude', 'lib/*.rb']
40
+ s.summary = "Ruby bulk-mailer."
41
+ s.description = s.summary
42
+ s.author = "Sharon Rosner"
43
+ s.email = 'ciconia@gmail.com'
44
+ s.homepage = 'http://code.google.com/p/bulkmail/'
45
+ s.executables = ['bulkmail']
46
+
47
+ s.add_dependency('actionmailer')
48
+ s.required_ruby_version = '>= 1.8.2'
49
+
50
+ s.files = %w(COPYING README Rakefile) + Dir.glob("{bin,doc,lib}/**/*")
51
+
52
+ s.require_path = "lib"
53
+ s.bindir = "bin"
54
+ end
55
+
56
+ Rake::GemPackageTask.new(spec) do |p|
57
+ p.need_tar = true
58
+ p.gem_spec = spec
59
+ end
60
+
61
+ task :install do
62
+ sh %{rake package}
63
+ sh %{sudo gem install pkg/#{NAME}-#{VERS}}
64
+ end
65
+
66
+ task :uninstall => [:clean] do
67
+ sh %{sudo gem uninstall #{NAME}}
68
+ end
69
+
70
+ task :doc_rforge do
71
+ sh %{rake doc}
72
+ sh %{scp -r doc/rdoc/* ciconia@rubyforge.org:/var/www/gforge-projects/bulkmail}
73
+ end
74
+
75
+ ##############################################################################
76
+ # SVN
77
+ ##############################################################################
78
+
79
+ desc "Add new files to subversion"
80
+ task :svn_add do
81
+ system "svn status | grep '^\?' | sed -e 's/? *//' | sed -e 's/ /\ /g' | xargs svn add"
82
+ end
83
+
@@ -0,0 +1,91 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'rubygems'
4
+ require 'optparse'
5
+
6
+ config = {
7
+ }
8
+
9
+ opts = OptionParser.new do |opts|
10
+ opts.banner = "Usage: bulkmail <options>"
11
+ opts.define_head "Simple bulk-mailer."
12
+ opts.separator ""
13
+ opts.separator "Options:"
14
+
15
+ opts.on("-h", "--host HOSTNAME", "SMPT host name. Default is localhost.") do |v|
16
+ config[:host] = v
17
+ end
18
+
19
+ opts.on("-r", "--recipients filename", "Recipients file name") do |v|
20
+ config[:recipients_file] = v
21
+ end
22
+
23
+ opts.on("-c", "--content filename", "Content file name") do |v|
24
+ config[:content_file] = v
25
+ end
26
+
27
+ opts.on("-s", "--subject subject", "Subject line") do |v|
28
+ config[:subject] = v
29
+ end
30
+
31
+ opts.on("-f", "--from from", "From address") do |v|
32
+ config[:from] = v
33
+ end
34
+
35
+ opts.on("-u", "--user username", "User name (for authentication)") do |v|
36
+ config[:user] = v
37
+ end
38
+
39
+ opts.on("-p", "--password password", "Password (for authentication)") do |v|
40
+ config[:password] = v
41
+ end
42
+
43
+ opts.on("-a", "--authentication type", "Authentication type") do |v|
44
+ config[:authentication] = v
45
+ end
46
+
47
+ opts.on("-m", "--mime type", "MIME type") do |v|
48
+ config[:content_type] = v
49
+ end
50
+
51
+ # No argument, shows at tail. This will print an options summary.
52
+ # Try it and see!
53
+ opts.on_tail("-?", "--help", "Show this message") do
54
+ puts opts
55
+ exit
56
+ end
57
+
58
+ # Another typical switch to print the version.
59
+ opts.on_tail("-v", "--version", "Show version") do
60
+ class << Gem; attr_accessor :loaded_specs; end
61
+ specs = Gem.loaded_specs['bulkmail']
62
+ puts "bulkmail #{specs.version} (#{specs.date.strftime '%Y-%m-%d'})"
63
+ exit
64
+ end
65
+ end
66
+
67
+ begin
68
+ opts.parse! ARGV
69
+ rescue => e
70
+ puts e.message
71
+ exit
72
+ end
73
+
74
+ unless config[:recipients_file] && config[:content_file]
75
+ puts opts
76
+ exit
77
+ end
78
+
79
+ require 'bulkmail'
80
+
81
+ BulkMail.server_settings[:address] = config[:host] if config[:host]
82
+ BulkMail.server_settings[:user_name] = config[:user] if config[:user]
83
+ BulkMail.server_settings[:password] = config[:password] if config[:password]
84
+ BulkMail.server_settings[:authentication] = config[:authentication].to_sym if config[:authentication]
85
+
86
+ p BulkMail.server_settings
87
+
88
+ job = BulkMail.send(config)
89
+ trap('INT') {job.thread.exit;}
90
+ job.thread.join
91
+ puts "Message sent to #{job.delivered} of #{job.total} recipients."
@@ -0,0 +1,75 @@
1
+ require 'action_mailer'
2
+
3
+ # The BulkMail module contains the Job class, which does the actual
4
+ # bulk-mailing, and a convenience method to start a job.
5
+ module BulkMail
6
+ class Mailer < ActionMailer::Base #:nodoc
7
+ def msg(addr, sub, content, from_addr, c_type, additional_headers)
8
+ recipients addr
9
+ subject sub if sub
10
+ body content
11
+ from from_addr if from_addr
12
+ content_type c_type if c_type
13
+ headers additional_headers if additional_headers
14
+ end
15
+ end
16
+
17
+ # The Job class performs the bulk-mailing work. Each instance starts a thread
18
+ # That goes over the list of recipients and sends each one an email. A job
19
+ # can also be queried for its progress, returning a number between 0 and 1.
20
+ class Job
21
+ attr_accessor :progress, :errors, :thread, :delivered, :total
22
+
23
+ def initialize(opts)
24
+ @recipients = IO.readlines(opts[:recipients_file])
25
+ @subject = opts[:subject]
26
+ @from = opts[:from]
27
+ @content_type = opts[:content_type]
28
+ @content = load_content(opts[:content_file])
29
+ @progress = 0
30
+ @delivered = 0
31
+ @total = @recipients.size
32
+ @errors = []
33
+ @thread = Thread.new {process}
34
+ end
35
+
36
+ def load_content(fn)
37
+ content = IO.readlines(fn)
38
+ while line = content.shift
39
+ break if line.empty?
40
+ if line =~ /^(.+):\s?(.*)$/
41
+ @headers ||= {}
42
+ @headers[$1] = $2
43
+ else
44
+ content.unshift(line)
45
+ break
46
+ end
47
+ end
48
+ content.join
49
+ end
50
+
51
+ def process
52
+ @recipients.each_with_index do |addr, idx|
53
+ begin
54
+ Mailer.deliver_msg(addr, @subject, @content, @from, @content_type, @headers)
55
+ @progress = idx / @recipients.size
56
+ @delivered += 1
57
+ puts "Sent email to #{addr}"
58
+ rescue => e
59
+ puts e.message
60
+ @errors << e
61
+ end
62
+ end
63
+ @progress = 1
64
+ end
65
+ end
66
+
67
+ def self.send(opts)
68
+ Job.new(opts)
69
+ end
70
+
71
+ def self.server_settings
72
+ ActionMailer::Base.server_settings
73
+ end
74
+ end
75
+
metadata ADDED
@@ -0,0 +1,73 @@
1
+ --- !ruby/object:Gem::Specification
2
+ rubygems_version: 0.9.0
3
+ specification_version: 1
4
+ name: bulkmail
5
+ version: !ruby/object:Gem::Version
6
+ version: "0.1"
7
+ date: 2006-10-18 00:00:00 +02:00
8
+ summary: Ruby bulk-mailer.
9
+ require_paths:
10
+ - lib
11
+ email: ciconia@gmail.com
12
+ homepage: http://code.google.com/p/bulkmail/
13
+ rubyforge_project:
14
+ description: Ruby bulk-mailer.
15
+ autorequire:
16
+ default_executable:
17
+ bindir: bin
18
+ has_rdoc: true
19
+ required_ruby_version: !ruby/object:Gem::Version::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: 1.8.2
24
+ version:
25
+ platform: ruby
26
+ signing_key:
27
+ cert_chain:
28
+ post_install_message:
29
+ authors:
30
+ - Sharon Rosner
31
+ files:
32
+ - COPYING
33
+ - README
34
+ - Rakefile
35
+ - bin/bulkmail
36
+ - lib/bulkmail.rb
37
+ - CHANGELOG
38
+ test_files: []
39
+
40
+ rdoc_options:
41
+ - --quiet
42
+ - --title
43
+ - Bulkmail Documentation
44
+ - --opname
45
+ - index.html
46
+ - --line-numbers
47
+ - --main
48
+ - README
49
+ - --inline-source
50
+ - --exclude
51
+ - ^(examples|extras)\/
52
+ - --exclude
53
+ - lib/*.rb
54
+ extra_rdoc_files:
55
+ - README
56
+ - CHANGELOG
57
+ - COPYING
58
+ executables:
59
+ - bulkmail
60
+ extensions: []
61
+
62
+ requirements: []
63
+
64
+ dependencies:
65
+ - !ruby/object:Gem::Dependency
66
+ name: actionmailer
67
+ version_requirement:
68
+ version_requirements: !ruby/object:Gem::Version::Requirement
69
+ requirements:
70
+ - - ">"
71
+ - !ruby/object:Gem::Version
72
+ version: 0.0.0
73
+ version: