powermta 0.1.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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 380695bb8cb1afe88b0a05c41c7014ea06080235
4
+ data.tar.gz: 056c48364f4e79cb90fe20971f2eca22379bb1a9
5
+ SHA512:
6
+ metadata.gz: 5a3fe948076523edcfb9c3d3ba66e483dfe33570858665cb1031d21b4f02f5e5e005373b84bf5ef361c4666547feda0bace17222b1bea2feacc687560a39f3cb
7
+ data.tar.gz: a5beb8839b817dbe111200e80be36baf2d550c573cdf51f98e338dda8ee5a06e44e3f33a3a7454389d0f5c6845a93c813743343d01a3728e54597a6a1a673272
data/.gitignore ADDED
@@ -0,0 +1,21 @@
1
+ ## MAC OS
2
+ .DS_Store
3
+
4
+ ## TEXTMATE
5
+ *.tmproj
6
+ tmtags
7
+
8
+ ## EMACS
9
+ *~
10
+ \#*
11
+ .\#*
12
+
13
+ ## VIM
14
+ *.swp
15
+
16
+ ## PROJECT::GENERAL
17
+ coverage
18
+ rdoc
19
+ pkg
20
+
21
+ ## PROJECT::SPECIFIC
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 Ian Warshak
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,66 @@
1
+ = powermta
2
+
3
+ This is an extension to Ruby's net/smtp library that lets you take advantage
4
+ of PowerMTA's (port25.com) native mailmerge and XACK features.
5
+
6
+ If you are doing any kind of mass mailing and you want the message to be unique
7
+ to each user, and not one email with 50000000 people bcc'ed on it, this
8
+ extension is for you.
9
+
10
+ I extracted this library from schoolsout.com, which literally sends hundreds of thousands of
11
+ time-sensitive emails a day.
12
+
13
+ Example usage:
14
+
15
+ require 'pmta_extension'
16
+
17
+ users = User.find(:all)
18
+
19
+ email_text =<<-EOF
20
+ From: "your friendly social network" <support@nosebook.com>
21
+ To: [*to]
22
+ Subject: Howdy [firstname]
23
+
24
+ Dear [firstname],
25
+
26
+ Did you know that you have [friend_count] friends? You must be one popular [gender]!!!
27
+
28
+ Sincerely,
29
+ Your friends at NoseBook
30
+ EOF
31
+
32
+ addresses = []
33
+ users.each do |user|
34
+ addresses << {:address => user.email,
35
+ :variables => {"firstname" => user.firstname, "friend_count" => user.friends.size, "gender" => user.gender == "m" ? 'dude' : 'gal'}}
36
+ end
37
+
38
+ Net::PowerMTA.start('your.powermta.mailserver.com', 25) do |smtp|
39
+ smtp.disable_xack # if you want to ignore ACK on RCPT TO and XDFN commands
40
+ smtp.send_merge_message(email_text, 'support@nosebook.com', true, addresses)
41
+ end
42
+
43
+ That's it. Now instead of having to compose and send User.size custom emails
44
+ (which can take forever), you can send 1 mailmerge message to the PowerMTA server
45
+ (the mail server) and have it do all of the merging for you.
46
+
47
+ Feel free to email me with any questions. Ian Warshak <iwarshak@stripey.net>
48
+
49
+ == Note on Patches/Pull Requests
50
+
51
+ * Fork the project.
52
+ * Make your feature addition or bug fix.
53
+ * Add tests for it. This is important so I don't break it in a
54
+ future version unintentionally.
55
+ * Commit, do not mess with rakefile, version, or history.
56
+ (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
57
+ * Send me a pull request. Bonus points for topic branches.
58
+
59
+ == Compatibility
60
+
61
+ Compatible for ruby >= 1.8.7 and <= 2.1.2
62
+
63
+ == Copyright
64
+
65
+ Copyright (c) 2010 Ian Warshak. See LICENSE for details.
66
+
data/Rakefile ADDED
@@ -0,0 +1,53 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gem|
7
+ gem.name = "powermta"
8
+ gem.summary = %Q{Do mail-merging with PowerMTA. Compatible with Ruby 1.8.7 & 1.9.X, but NOT 1.8.6}
9
+ gem.description = %Q{This is an extension to Ruby's net/smtp library that lets you take advantage
10
+ of PowerMTA's (port25.com) native mailmerge feature.}
11
+ gem.email = "iwarshak@stripey.net"
12
+ gem.homepage = "http://github.com/iwarshak/powermta"
13
+ gem.authors = ["Ian Warshak"]
14
+ # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
15
+ end
16
+ Jeweler::GemcutterTasks.new
17
+ rescue LoadError
18
+ puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
19
+ end
20
+
21
+ require 'rake/testtask'
22
+ Rake::TestTask.new(:test) do |test|
23
+ test.libs << 'lib' << 'test'
24
+ test.pattern = 'test/**/test_*.rb'
25
+ test.verbose = true
26
+ end
27
+
28
+ begin
29
+ require 'rcov/rcovtask'
30
+ Rcov::RcovTask.new do |test|
31
+ test.libs << 'test'
32
+ test.pattern = 'test/**/test_*.rb'
33
+ test.verbose = true
34
+ end
35
+ rescue LoadError
36
+ task :rcov do
37
+ abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
38
+ end
39
+ end
40
+
41
+ task :test => :check_dependencies
42
+
43
+ task :default => :test
44
+
45
+ require 'rake/rdoctask'
46
+ Rake::RDocTask.new do |rdoc|
47
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
48
+
49
+ rdoc.rdoc_dir = 'rdoc'
50
+ rdoc.title = "powermta #{version}"
51
+ rdoc.rdoc_files.include('README*')
52
+ rdoc.rdoc_files.include('lib/**/*.rb')
53
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.0
@@ -0,0 +1,101 @@
1
+ require 'net/smtp'
2
+
3
+ module Net
4
+ class PowerMTA < Net::SMTP
5
+ def initialize(address, port = nil)
6
+ super(address, port)
7
+ @xack = true
8
+ end
9
+
10
+ # only a merging 1 part
11
+ def send_merge_message( msgstr, from_addr, verp = true, to_addrs_with_variables = [])
12
+ raise IOError, 'closed session' unless @socket
13
+
14
+ xmrg_from from_addr, verp
15
+
16
+ to_addrs_with_variables.each do |addr|
17
+ xmrg_to addr[:address], addr[:variables]
18
+ end
19
+
20
+ # With mail merge, we don't send DATA command, we send XPRT command
21
+ res = critical {
22
+ check_continue get_response('XPRT 1 LAST')
23
+ @socket.write_message msgstr
24
+ recv_response()
25
+ }
26
+ check_response res
27
+ res
28
+ end
29
+
30
+ # Enable/Disable XACK to ignore ACKs from SMTP Server on multiple RCPT TO calls
31
+ def enable_xack
32
+ getok('XACK ON')
33
+ @xack = true
34
+ end
35
+
36
+ def disable_xack
37
+ getok('XACK OFF')
38
+ @xack = false
39
+ end
40
+
41
+ private
42
+
43
+ def expect_ack?(command)
44
+ @xack || !command.match(/^(RCPT TO:|XDFN)/)
45
+ end
46
+
47
+ def xmrg_from(fromaddr, verp)
48
+ if $SAFE > 0
49
+ raise SecurityError, 'tainted from_addr' if from_addr.tainted?
50
+ end
51
+ if verp
52
+ getok("XMRG FROM:<#{fromaddr}> VERP")
53
+ else
54
+ getok("XMRG FROM:<#{fromaddr}>")
55
+ end
56
+ end
57
+
58
+ def xmrg_to(to_addr, variables = {})
59
+ return unless to_addr
60
+ variables ||= {}
61
+ variables.merge!("*parts" => "1") unless variables["*parts"]
62
+ variables.each do |key,value|
63
+ getok("XDFN #{key.to_s}=\"#{value.to_s}\"")
64
+ end
65
+ begin
66
+ rcptto(to_addr)
67
+ rescue
68
+ #puts "Bad address: #{to}. #{$!}"
69
+ end
70
+ end
71
+
72
+ def getok(reqline)
73
+ logging "<< #{reqline}"
74
+ res = critical {
75
+ @socket.writeline reqline
76
+ recv_response() if expect_ack?( reqline )
77
+ }
78
+
79
+ return nil unless expect_ack?( reqline )
80
+ check_response res
81
+ res
82
+ end
83
+
84
+ def recv_response
85
+ buf = ''
86
+ while true
87
+ line = @socket.readline
88
+ buf << line << "\n"
89
+ break unless line[3,1] == '-' # "210-PIPELINING"
90
+ end
91
+ logging ">> #{buf}"
92
+ Response.parse(buf)
93
+ end
94
+
95
+ def get_response(reqline)
96
+ logging "<< #{reqline}"
97
+ @socket.writeline reqline
98
+ recv_response()
99
+ end
100
+ end
101
+ end
data/lib/powermta.rb ADDED
@@ -0,0 +1 @@
1
+ require 'pmta_extension'
data/powermta.gemspec ADDED
@@ -0,0 +1,52 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{powermta}
8
+ s.version = "0.1.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Ian Warshak"]
12
+ s.date = %q{2010-08-06}
13
+ s.description = %q{This is an extension to Ruby's net/smtp library that lets you take advantage
14
+ of PowerMTA's (port25.com) native mailmerge feature.}
15
+ s.email = %q{iwarshak@stripey.net}
16
+ s.extra_rdoc_files = [
17
+ "LICENSE",
18
+ "README.rdoc"
19
+ ]
20
+ s.files = [
21
+ ".gitignore",
22
+ "LICENSE",
23
+ "README.rdoc",
24
+ "Rakefile",
25
+ "VERSION",
26
+ "lib/pmta_extension.rb",
27
+ "lib/powermta.rb",
28
+ "powermta.gemspec",
29
+ "test/helper.rb",
30
+ "test/test_powermta.rb"
31
+ ]
32
+ s.homepage = %q{http://github.com/iwarshak/powermta}
33
+ s.rdoc_options = ["--charset=UTF-8"]
34
+ s.require_paths = ["lib"]
35
+ s.rubygems_version = %q{1.3.5}
36
+ s.summary = %q{Do mail-merging with PowerMTA. Compatible with Ruby 1.8.7 & 1.9.X, but NOT 1.8.6}
37
+ s.test_files = [
38
+ "test/helper.rb",
39
+ "test/test_powermta.rb"
40
+ ]
41
+
42
+ if s.respond_to? :specification_version then
43
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
44
+ s.specification_version = 3
45
+
46
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
47
+ else
48
+ end
49
+ else
50
+ end
51
+ end
52
+
data/test/helper.rb ADDED
@@ -0,0 +1,9 @@
1
+ require 'rubygems'
2
+ require 'test/unit'
3
+
4
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
5
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
6
+ require 'powermta'
7
+
8
+ class Test::Unit::TestCase
9
+ end
@@ -0,0 +1,7 @@
1
+ require 'helper'
2
+
3
+ class TestPowermta < Test::Unit::TestCase
4
+ def test_something_for_real
5
+ flunk "hey buddy, you should probably rename this file and start testing for real"
6
+ end
7
+ end
metadata ADDED
@@ -0,0 +1,60 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: powermta
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Ian Warshak
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2010-08-06 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: |-
14
+ This is an extension to Ruby's net/smtp library that lets you take advantage
15
+ of PowerMTA's (port25.com) native mailmerge feature.
16
+ email: iwarshak@stripey.net
17
+ executables: []
18
+ extensions: []
19
+ extra_rdoc_files:
20
+ - LICENSE
21
+ - README.rdoc
22
+ files:
23
+ - .gitignore
24
+ - LICENSE
25
+ - README.rdoc
26
+ - Rakefile
27
+ - VERSION
28
+ - lib/pmta_extension.rb
29
+ - lib/powermta.rb
30
+ - powermta.gemspec
31
+ - test/helper.rb
32
+ - test/test_powermta.rb
33
+ homepage: http://github.com/iwarshak/powermta
34
+ licenses: []
35
+ metadata: {}
36
+ post_install_message:
37
+ rdoc_options:
38
+ - --charset=UTF-8
39
+ require_paths:
40
+ - lib
41
+ required_ruby_version: !ruby/object:Gem::Requirement
42
+ requirements:
43
+ - - '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ required_rubygems_version: !ruby/object:Gem::Requirement
47
+ requirements:
48
+ - - '>='
49
+ - !ruby/object:Gem::Version
50
+ version: '0'
51
+ requirements: []
52
+ rubyforge_project:
53
+ rubygems_version: 2.0.14
54
+ signing_key:
55
+ specification_version: 3
56
+ summary: Do mail-merging with PowerMTA. Compatible with Ruby 1.8.7 & 1.9.X, but NOT
57
+ 1.8.6
58
+ test_files:
59
+ - test/helper.rb
60
+ - test/test_powermta.rb