cannikin-postal 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,171 @@
1
+ module Postal
2
+ class Mailing < Postal::Base
3
+
4
+ class << self
5
+
6
+ end
7
+
8
+
9
+ DEFAULT_ATTRIBUTES = {:additional_headers => nil,
10
+ :attachments => nil,
11
+ :bypass_moderation => nil,
12
+ :campaign => nil,
13
+ :char_set_id => nil,
14
+ :detect_html => nil,
15
+ :dont_attempt_after_date => nil,
16
+ :enable_recovery => nil,
17
+ :from => nil,
18
+ :html_message => nil,
19
+ :html_section_encoding => nil,
20
+ :is_html_section_encoded => nil,
21
+ :is_text_section_encoded => nil,
22
+ :list_name => nil,
23
+ :recency_number_of_mailings => nil,
24
+ :recency_which => nil,
25
+ :reply_to => nil,
26
+ :resend_after_days => nil,
27
+ :sample_size => nil,
28
+ :scheduled_mailing_date => nil,
29
+ :subject => nil,
30
+ :text_message => nil,
31
+ :text_section_encoding => nil,
32
+ :title => nil,
33
+ :to => nil,
34
+ :track_opens => nil,
35
+ :rewrite_date_when_sent => nil }
36
+
37
+ attr_accessor :additional_headers,
38
+ :attachments,
39
+ :bypass_moderation,
40
+ :campaign,
41
+ :char_set_id,
42
+ :detect_html,
43
+ :dont_attempt_after_date,
44
+ :enable_recovery,
45
+ :from,
46
+ :html_message,
47
+ :html_section_encoding,
48
+ :is_html_section_encoded,
49
+ :is_text_section_encoded,
50
+ :list_name,
51
+ :recency_number_of_mailings,
52
+ :recency_which,
53
+ :reply_to,
54
+ :resend_after_days,
55
+ :sample_size,
56
+ :scheduled_mailing_date,
57
+ :subject,
58
+ :text_message,
59
+ :text_section_encoding,
60
+ :title,
61
+ :to,
62
+ :track_opens,
63
+ :rewrite_date_when_sent
64
+
65
+ # Create a new mailing ready to send
66
+ def initialize(args={})
67
+ args = DEFAULT_ATTRIBUTES.merge(args)
68
+ @to = args[:to]
69
+ @additional_headers = args[:additional_headers]
70
+ @attachments = args[:attachments]
71
+ @bypass_moderation = args[:bypass_moderation]
72
+ @campaign = args[:campaign]
73
+ @char_set_id = args[:char_set_id]
74
+ @detect_html = args[:detect_html]
75
+ @dont_attempt_after_date = args[:dont_attempt_after_date]
76
+ @enable_recovery = args[:enable_recovery]
77
+ @from = args[:from]
78
+ @html_message = args[:html_message]
79
+ @html_section_encoding = args[:html_section_encoding]
80
+ @is_html_section_encoded = args[:is_html_section_encoded]
81
+ @is_text_section_encoded = args[:is_text_section_encoded]
82
+ @list_name = args[:list_name]
83
+ @recency_number_of_mailings = args[:recency_number_of_mailings]
84
+ @recency_which = args[:recency_which]
85
+ @reply_to = args[:reply_to]
86
+ @resend_after_days = args[:resend_after_days]
87
+ @sample_size = args[:sample_size]
88
+ @scheduled_mailing_date = args[:scheduled_mailing_date]
89
+ @subject = args[:subject]
90
+ @text_message = args[:text_message]
91
+ @text_section_encoding = args[:text_section_encoding]
92
+ @title = args[:title]
93
+ @to = args[:to]
94
+ @track_opens = args[:track_opens]
95
+ @rewrite_date_when_sent = args[:rewrite_date_when_sent]
96
+ end
97
+
98
+
99
+ # Send the mailing
100
+ def send
101
+ if valid?
102
+ mail = Postal::Lmapi::MailingStruct.new(:additionalHeaders => @additional_headers,
103
+ :attachments => @attachments,
104
+ :bypassModeration => @bypass_moderation,
105
+ :campaign => @campaign,
106
+ :charSetID => @char_set_id,
107
+ :detectHtml => @detect_html,
108
+ :dontAttemptAfterDate => @dont_attempt_after_date,
109
+ :enableRecovery => @enable_recovery,
110
+ :from => @from,
111
+ :htmlMessage => @html_message,
112
+ :htmlSectionEncoding => @html_section_encoding,
113
+ :isHtmlSectionEncoded => @is_html_section_encoded,
114
+ :isTextSectionEncoded => @is_text_section_encoded,
115
+ :listName => @list_name,
116
+ :recencyNumberOfMailings => @recency_number_of_mailings,
117
+ :recencyWhich => @recency_which,
118
+ :replyTo => @reply_to,
119
+ :resendAfterDays => @resend_after_days,
120
+ :sampleSize => @sample_size,
121
+ :scheduledMailingDate => @scheduled_mailing_date,
122
+ :subject => @subject,
123
+ :textMessage => @text_message,
124
+ :textSectionEncoding => @text_section_encoding,
125
+ :title => @title,
126
+ :trackOpens => @track_opens,
127
+ :rewriteDateWhenSent => @rewrite_date_when_sent )
128
+
129
+ # are we sending to a list of email addresses or member ids
130
+ case @to.to_a.first
131
+ when ::String
132
+ emails = @to.to_a
133
+ member_ids = []
134
+ when ::Fixnum
135
+ emails = []
136
+ member_ids = @to.to_a
137
+ end
138
+
139
+ return Postal.driver.sendMailingDirect(emails,member_ids,mail)
140
+ else
141
+ return false
142
+ end
143
+ end
144
+
145
+
146
+ # same as send() but throws an error instead of just returning false
147
+ def send!
148
+ if id = send
149
+ return id
150
+ else
151
+ raise Postal::CouldNotSendMailing, 'Your mail was invalid and could not be sent.'
152
+ end
153
+ end
154
+
155
+ alias_method :save, :send
156
+ alias_method :save!, :send!
157
+
158
+
159
+ # Determines whether the email is valid to send
160
+ def valid?
161
+ return validate
162
+ end
163
+
164
+
165
+ # Determines whether we have everything we need to send an email
166
+ def validate
167
+ return (@list_name && @to && @subject) ? true : false
168
+ end
169
+
170
+ end
171
+ end
@@ -0,0 +1,115 @@
1
+ module Postal
2
+ class Member < Postal::Base
3
+
4
+ class << self
5
+
6
+ def find_by_filter(args)
7
+ return Postal.driver.selectMembers(args)
8
+ end
9
+
10
+
11
+ # Will NOT let you delete the entire list's members (only pass a ListName) Returns the number of members that were deleted, or nil if none were
12
+ def destroy(args)
13
+ raise Postal::WouldDeleteAllMembers, 'Not passing any parameters (other than ListName) to this method will delete ALL members of a list. If you really want to delete all members of this list, use destroy! instead.' if args.to_a.size == 1 && args.to_a.first.match(/ListName/)
14
+ return Postal.driver.deleteMembers(args)
15
+ end
16
+
17
+
18
+ # WILL let you delete an entire list's members (only pass a ListName). Returns the number of members that were deleted, or nil if none were
19
+ def destroy!(args)
20
+ return Postal.driver.deleteMembers(args)
21
+ end
22
+
23
+
24
+ protected
25
+
26
+ def find_by_email(args,options)
27
+ list_name = args.last
28
+ member_id = 0
29
+ email = args.first
30
+ begin
31
+ return Postal.driver.getMemberID(Postal::Lmapi::SimpleMemberStruct.new(list_name,member_id,email))
32
+ rescue SOAP::FaultError
33
+ return nil
34
+ end
35
+ end
36
+
37
+
38
+ def find_by_id(args,options)
39
+ member_id = args.first
40
+ return Postal.driver.getEmailFromMemberID(member_id)
41
+ end
42
+
43
+
44
+ # Find one or more members by name
45
+ def find_some(args,options={})
46
+ case args.first
47
+ when ::String
48
+ find_by_email(args,options)
49
+ when ::Fixnum
50
+ find_by_id(args,options)
51
+ when nil
52
+ find_by_struct(options)
53
+ end
54
+ end
55
+
56
+ end
57
+
58
+ DEFAULT_ATTRIBUTES = { :id => nil, :email => nil, :name => nil, :list_name => nil, :demographics => nil }
59
+
60
+ attr_accessor :id, :email, :name, :list_name, :demographics
61
+
62
+ # Create a new member instance
63
+ def initialize(email,name,list_name,demographics={})
64
+ @id = nil
65
+ @email = email
66
+ @name = name
67
+ @list_name = list_name
68
+ @demographics = demographics
69
+ end
70
+
71
+
72
+ # Save the member to Lyris and returns the member ID that was created. Returns `false` if the save fails.
73
+ def save
74
+ # if @list is a list Object then get the name out (all Lyris wants is the name)
75
+ list_name = @list_name
76
+ begin
77
+ @id = Postal.driver.createSingleMember(@email, @name, list_name)
78
+ update_attributes(@demographics) unless @demographics.empty?
79
+ return @id
80
+ rescue SOAP::FaultError
81
+ return false
82
+ end
83
+ end
84
+
85
+
86
+ # Saves the member to Lyris and returns the member ID that was created. Throws an error if the save fails.
87
+ def save!
88
+ if id = save
89
+ return id
90
+ else
91
+ raise Postal::CouldNotCreateMember, 'Could not create a new member. The most likely cause is that the specified list already contains this email address.'
92
+ end
93
+ end
94
+
95
+
96
+ # Update the demographics for a user
97
+ def update_attributes(attributes={})
98
+ list_name = @list_name
99
+ demos = attributes.collect { |key,value| Postal::Lmapi::KeyValueType.new(value,key.to_s) }
100
+ member = Postal::Lmapi::SimpleMemberStruct.new(list_name, @id, @email)
101
+ return Postal.driver.updateMemberDemographics(member,demos)
102
+ end
103
+
104
+
105
+ # Throw an error if demographics couldn't be saved
106
+ def update_attributes!(attributes={})
107
+ if update_attributes(attributes)
108
+ return true
109
+ else
110
+ raise Postal::CouldNotUpdateMember, 'Could not update the member. The most likely cause is that your demographics are invalid.'
111
+ end
112
+ end
113
+
114
+ end
115
+ end
data/lib/postal.rb ADDED
@@ -0,0 +1,47 @@
1
+ $:.unshift File.dirname(__FILE__) # for use/testing when no gem is installed
2
+
3
+ # external
4
+ require 'logger'
5
+
6
+ # internal
7
+ require 'postal/lmapi/lmapi.rb'
8
+ require 'postal/lmapi/lmapi_driver.rb'
9
+ require 'postal/lmapi/lmapi_mapping_registry.rb'
10
+ require 'postal/base'
11
+ require 'postal/list'
12
+ require 'postal/member'
13
+ require 'postal/mailing'
14
+
15
+ module Postal
16
+
17
+ # error classes
18
+ class CouldNotCreateMember < StandardError; end;
19
+ class CouldNotUpdateMember < StandardError; end;
20
+ class CouldNotSendMailing < StandardError; end;
21
+ class WouldDeleteAllMembers < StandardError; end;
22
+
23
+ VERSION = '0.1.0'
24
+ LOGGER = Logger.new(STDOUT)
25
+
26
+ DEFAULT_OPTIONS = { :debug => false }
27
+
28
+ @options = { :wsdl => nil,
29
+ :username => nil,
30
+ :password => nil }
31
+ @driver = nil
32
+
33
+ attr_accessor :options
34
+
35
+ # Make a driver instance available at Postal.driver
36
+ def driver
37
+ unless @driver
38
+ @driver = Postal::Lmapi::Soap.new
39
+ @driver.options['protocol.http.basic_auth'] << [@options[:wsdl], @options[:username], @options[:password]]
40
+ end
41
+ return @driver
42
+ end
43
+
44
+ # make @options available so it can be set externally when using the library
45
+ extend self
46
+
47
+ end
data/postal.gemspec ADDED
@@ -0,0 +1,63 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = %q{postal}
5
+ s.version = "0.1.0"
6
+
7
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
8
+ s.authors = ["Rob Cameron"]
9
+ s.date = %q{2009-08-28}
10
+ s.description = %q{Lyris is an enterprise email service. Postal makes it easy for Ruby to talk to Lyris's API.}
11
+ s.email = %q{cannikinn@gmail.com}
12
+ s.extra_rdoc_files = [
13
+ "LICENSE",
14
+ "README.rdoc"
15
+ ]
16
+ s.files = [
17
+ ".document",
18
+ ".gitignore",
19
+ "LICENSE",
20
+ "README.rdoc",
21
+ "Rakefile",
22
+ "VERSION",
23
+ "lib/postal.rb",
24
+ "lib/postal/base.rb",
25
+ "lib/postal/list.rb",
26
+ "lib/postal/lmapi/lmapi.rb",
27
+ "lib/postal/lmapi/lmapi_driver.rb",
28
+ "lib/postal/lmapi/lmapi_mapping_registry.rb",
29
+ "lib/postal/mailing.rb",
30
+ "lib/postal/member.rb",
31
+ "postal.gemspec",
32
+ "test/list_test.rb",
33
+ "test/lmapiClient.rb",
34
+ "test/lyris_sample.yml",
35
+ "test/mailing_test.rb",
36
+ "test/member_test.rb",
37
+ "test/postal_suite.rb",
38
+ "test/test_helper.rb"
39
+ ]
40
+ s.homepage = %q{http://github.com/cannikin/postal}
41
+ s.rdoc_options = ["--charset=UTF-8"]
42
+ s.require_paths = ["lib"]
43
+ s.rubygems_version = %q{1.3.4}
44
+ s.summary = %q{Gem for talking to the Lyris API}
45
+ s.test_files = [
46
+ "test/list_test.rb",
47
+ "test/lmapiClient.rb",
48
+ "test/mailing_test.rb",
49
+ "test/member_test.rb",
50
+ "test/postal_suite.rb",
51
+ "test/test_helper.rb"
52
+ ]
53
+
54
+ if s.respond_to? :specification_version then
55
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
56
+ s.specification_version = 3
57
+
58
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
59
+ else
60
+ end
61
+ else
62
+ end
63
+ end
data/test/list_test.rb ADDED
@@ -0,0 +1,20 @@
1
+ require 'test_helper'
2
+
3
+ class ListTest < Test::Unit::TestCase
4
+
5
+ @config = nil
6
+
7
+ def setup
8
+ load_config
9
+ end
10
+
11
+ # lists
12
+ def test_can_find_list_that_exists
13
+ assert Postal::List.find(@config['list_name'])
14
+ end
15
+
16
+ def test_returns_nil_if_list_not_found
17
+ assert_nil Postal::List.find('foo')
18
+ end
19
+
20
+ end