email_api 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +148 -0
- data/.travis.yml +5 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/Gemfile +6 -0
- data/Gemfile.lock +154 -0
- data/LICENSE.txt +21 -0
- data/README.md +195 -0
- data/Rakefile +7 -0
- data/bin/setup +6 -0
- data/config.ru +4 -0
- data/email_api.gemspec +44 -0
- data/lib/email_api.rb +47 -0
- data/lib/email_api/api/api_parser.rb +100 -0
- data/lib/email_api/email/client/email_client.rb +69 -0
- data/lib/email_api/email/client/mailgun_client.rb +123 -0
- data/lib/email_api/email/client/sendgrid_client.rb +115 -0
- data/lib/email_api/email/data/client_response.rb +40 -0
- data/lib/email_api/email/data/email_address.rb +21 -0
- data/lib/email_api/email/data/email_object.rb +43 -0
- metadata +274 -0
data/Rakefile
ADDED
data/bin/setup
ADDED
data/config.ru
ADDED
data/email_api.gemspec
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
lib = File.expand_path('../lib', __FILE__)
|
2
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
3
|
+
|
4
|
+
Gem::Specification.new do |spec|
|
5
|
+
spec.name = 'email_api'
|
6
|
+
spec.version = '1.0.0'
|
7
|
+
spec.authors = ['Vasili Moisiadis']
|
8
|
+
spec.email = ['vasili@moisiadis.com']
|
9
|
+
|
10
|
+
spec.summary = 'Email API'
|
11
|
+
spec.description = 'Backend Email API that accepts necessary information and sends emails using email service providers'
|
12
|
+
spec.homepage = 'https://github.com/VasiliMoisiadis/email-api'
|
13
|
+
spec.license = 'MIT'
|
14
|
+
|
15
|
+
# Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
|
16
|
+
# to allow pushing to a single host or delete this section to allow pushing to any host.
|
17
|
+
unless spec.respond_to?(:metadata)
|
18
|
+
raise 'RubyGems 2.0 or newer is required to protect against ' \
|
19
|
+
'public gem pushes.'
|
20
|
+
end
|
21
|
+
|
22
|
+
spec.files = `git ls-files -z`.split("\x0").reject do |f|
|
23
|
+
f.match(%r{^(tests|spec|features)/})
|
24
|
+
end
|
25
|
+
spec.bindir = 'exe'
|
26
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
27
|
+
spec.require_paths = ['lib']
|
28
|
+
|
29
|
+
spec.add_development_dependency 'bundler', '~> 1.16'
|
30
|
+
spec.add_development_dependency 'dotenv', '~> 2.2.1'
|
31
|
+
spec.add_development_dependency 'json', '~> 2.1.0'
|
32
|
+
spec.add_development_dependency 'minitest', '~> 5.11.3'
|
33
|
+
spec.add_development_dependency 'minitest-reporters', '~> 1.1.19'
|
34
|
+
spec.add_development_dependency 'mocha', '~> 1.4.0'
|
35
|
+
spec.add_development_dependency 'puma', '~> 3.11.3'
|
36
|
+
spec.add_development_dependency 'rack-test', '~> 0.8.3'
|
37
|
+
spec.add_development_dependency 'rake', '~> 10.0'
|
38
|
+
spec.add_development_dependency 'rest-client', '~> 2.0.2'
|
39
|
+
spec.add_development_dependency 'rspec', '~> 3.0'
|
40
|
+
spec.add_development_dependency 'rspec-rails', '~> 3.7.2'
|
41
|
+
spec.add_development_dependency 'simplecov', '~> 0.16.1'
|
42
|
+
spec.add_development_dependency 'sinatra', '~> 2.0.1'
|
43
|
+
spec.add_development_dependency 'thin', '~> 1.2.5'
|
44
|
+
end
|
data/lib/email_api.rb
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
require 'sinatra/base'
|
2
|
+
require 'json'
|
3
|
+
require 'date'
|
4
|
+
require './lib/email_api/api/api_parser'
|
5
|
+
require './lib/email_api/email/client/email_client'
|
6
|
+
require './lib/email_api/email/data/email_object'
|
7
|
+
|
8
|
+
# Main class of Email API Project
|
9
|
+
class EmailApi < Sinatra::Base
|
10
|
+
|
11
|
+
# Ping with current time
|
12
|
+
get '/ping' do
|
13
|
+
puts "Received new Ping Request from #{request.ip}"
|
14
|
+
{ time: Time.now.utc }.to_json
|
15
|
+
end
|
16
|
+
|
17
|
+
# Send Email (Supports calling through a web browser)
|
18
|
+
get '/send' do
|
19
|
+
puts "Received new Email Send GET Request from #{request.ip}"
|
20
|
+
handle_api(params).to_hash.to_json
|
21
|
+
end
|
22
|
+
|
23
|
+
# Send Email (Proper usage, as a POST request)
|
24
|
+
post '/send' do
|
25
|
+
puts "Received new Email Send POST Request from #{request.ip}"
|
26
|
+
handle_api(params).to_hash.to_json
|
27
|
+
end
|
28
|
+
|
29
|
+
# Handle request received through API
|
30
|
+
def handle_api(api_params)
|
31
|
+
return nil if !api_params.respond_to?(:[]) && !api_params.is_a?(Hash)
|
32
|
+
from = api_params['from']
|
33
|
+
to = api_params['to']
|
34
|
+
cc = api_params['cc']
|
35
|
+
bcc = api_params['bcc']
|
36
|
+
subject = api_params['subject']
|
37
|
+
content = api_params['content']
|
38
|
+
email_obj = ApiParser.parse_email(from, to, cc, bcc, subject, content)
|
39
|
+
EmailClient.send_email(email_obj)
|
40
|
+
rescue StandardError => e
|
41
|
+
puts "Error: #{e.class}: #{e.message}"
|
42
|
+
response = ClientResponse.new
|
43
|
+
response.set_internal_err
|
44
|
+
response
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
@@ -0,0 +1,100 @@
|
|
1
|
+
require './lib/email_api/email/data/email_object'
|
2
|
+
require './lib/email_api/email/data/email_address'
|
3
|
+
require 'json'
|
4
|
+
|
5
|
+
# Parser for Email API
|
6
|
+
class ApiParser
|
7
|
+
@email_delim ||= ','
|
8
|
+
|
9
|
+
# Accessor for the supported email delimiter
|
10
|
+
def self.email_delim
|
11
|
+
@email_delim
|
12
|
+
end
|
13
|
+
|
14
|
+
# Parses raw text into custom EmailAddress object
|
15
|
+
#
|
16
|
+
# @param [String] email_text Raw text denoting email
|
17
|
+
# @return [Email Address] email_address
|
18
|
+
def self.parse_email_text(email_text)
|
19
|
+
return nil if email_text.nil? || !email_text.is_a?(String)
|
20
|
+
|
21
|
+
restricted_chars = ',<>'
|
22
|
+
|
23
|
+
# Try to parse correct format: "DISPLAY NAME <EMAIL ADDRESS>"
|
24
|
+
name = nil
|
25
|
+
email = email_text[/.*<([^>]*)/, 1]
|
26
|
+
name = email_text.gsub(email, '') unless email.nil?
|
27
|
+
name = name.delete(restricted_chars).strip unless name.nil?
|
28
|
+
email = email.delete(restricted_chars).strip unless email.nil?
|
29
|
+
|
30
|
+
# If only one or the other found, assign value to both fields
|
31
|
+
name = email if (!email.nil? && !email.empty?) && (name.nil? || name.empty?)
|
32
|
+
email = name if (!name.nil? && !name.empty?) && (email.nil? || email.empty?)
|
33
|
+
|
34
|
+
# If neither found, take entire String as values
|
35
|
+
name = email = email_text.delete(restricted_chars).strip if name.nil? && email.nil?
|
36
|
+
|
37
|
+
EmailAddress.new(name, email)
|
38
|
+
end
|
39
|
+
|
40
|
+
# Parse a String[] and returns an EmailAddres[]
|
41
|
+
#
|
42
|
+
# @param [String[]] email_text_arr Array of text, each being an email address
|
43
|
+
# @return [EmailAddress[]] email_arr
|
44
|
+
def self.parse_email_text_arr(email_text_arr)
|
45
|
+
return nil if email_text_arr.nil? || !email_text_arr.is_a?(String)
|
46
|
+
|
47
|
+
email_arr = []
|
48
|
+
# Split on email delimiter, parse each email
|
49
|
+
split_arr = email_text_arr.split(/(?<=[#{email_delim}])/, -1)
|
50
|
+
|
51
|
+
# Push value on through even if empty -> handled further down
|
52
|
+
email_arr.push(parse_email_text(email_text_arr)) if split_arr.empty?
|
53
|
+
split_arr.each do |email_text|
|
54
|
+
email_arr.push(parse_email_text(email_text))
|
55
|
+
end
|
56
|
+
|
57
|
+
email_arr = nil if !email_arr.nil? && email_arr.empty?
|
58
|
+
email_arr
|
59
|
+
end
|
60
|
+
|
61
|
+
# Parses parameter inputs into an EmailObject using the supported notation
|
62
|
+
#
|
63
|
+
# @param [Splat] params Raw Email Attribute Values
|
64
|
+
# @return [EmailObject] email_object Parsed email object
|
65
|
+
def self.parse_email(*params)
|
66
|
+
email_object = EmailObject.new
|
67
|
+
|
68
|
+
return email_object if params.nil? || !params.is_a?(Array) || params.empty?
|
69
|
+
|
70
|
+
to = cc = bcc = subject = content = nil
|
71
|
+
from = params[0]
|
72
|
+
to = params[1] if params.count > 1
|
73
|
+
cc = params[2] if params.count > 2
|
74
|
+
bcc = params[3] if params.count > 3
|
75
|
+
subj_raw = params[4] if params.count > 4
|
76
|
+
cont_raw = params[5] if params.count > 5
|
77
|
+
|
78
|
+
subject = nil
|
79
|
+
if !subj_raw.nil? && (subj_raw.is_a?(String) || subj_raw.is_a?(Numeric))
|
80
|
+
subject = subj_raw
|
81
|
+
end
|
82
|
+
|
83
|
+
content = nil
|
84
|
+
if !cont_raw.nil? && (cont_raw.is_a?(String) || cont_raw.is_a?(Numeric))
|
85
|
+
content = cont_raw
|
86
|
+
end
|
87
|
+
|
88
|
+
# Parse and assign Message Attributes
|
89
|
+
email_object.from = parse_email_text(from)
|
90
|
+
email_object.to = parse_email_text_arr(to)
|
91
|
+
email_object.cc = parse_email_text_arr(cc)
|
92
|
+
email_object.bcc = parse_email_text_arr(bcc)
|
93
|
+
email_object.subject = (subject.nil? || subject.empty? ? nil : subject)
|
94
|
+
email_object.content = (content.nil? || content.empty? ? nil : content)
|
95
|
+
|
96
|
+
email_object
|
97
|
+
end
|
98
|
+
|
99
|
+
private_class_method :parse_email_text_arr, :parse_email_text
|
100
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
require './lib/email_api/email/client/mailgun_client'
|
2
|
+
require './lib/email_api/email/client/sendgrid_client'
|
3
|
+
require './lib/email_api/email/data/client_response'
|
4
|
+
require 'json'
|
5
|
+
|
6
|
+
# General client that sends email utilizing multiple service providers
|
7
|
+
class EmailClient
|
8
|
+
|
9
|
+
# Accessor for the OK Code
|
10
|
+
def self.ok_code
|
11
|
+
200
|
12
|
+
end
|
13
|
+
|
14
|
+
# Accessor for the Bad Request Code
|
15
|
+
def self.bad_req_code
|
16
|
+
400
|
17
|
+
end
|
18
|
+
|
19
|
+
# Accessor for the Internal Server Error Code
|
20
|
+
def self.internal_err_code
|
21
|
+
500
|
22
|
+
end
|
23
|
+
|
24
|
+
# Sends email utilizing multiple service providers
|
25
|
+
#
|
26
|
+
# @param [EmailObject] email_object
|
27
|
+
# @return [ClientResponse] response
|
28
|
+
def self.send_email(email_object)
|
29
|
+
return ClientResponse.new if email_object.nil? || !email_object.is_a?(EmailObject)
|
30
|
+
|
31
|
+
puts 'Attempting Email Sending via primary client: SENDGRID'
|
32
|
+
response = use_client_client SendgridClient, email_object
|
33
|
+
|
34
|
+
if response != ok_code
|
35
|
+
puts 'Primary client failed. Attempting secondary client: MAILGUN'
|
36
|
+
response = use_client_client MailgunClient, email_object
|
37
|
+
end
|
38
|
+
|
39
|
+
client_response = ClientResponse.new email_object
|
40
|
+
if response == ok_code
|
41
|
+
client_response.set_ok
|
42
|
+
elsif response == bad_req_code
|
43
|
+
client_response.set_bad_req
|
44
|
+
elsif response == internal_err_code
|
45
|
+
client_response.set_internal_err
|
46
|
+
end
|
47
|
+
|
48
|
+
client_response
|
49
|
+
end
|
50
|
+
|
51
|
+
# Sends email using a single email client
|
52
|
+
#
|
53
|
+
# @param [MailgunClient|SendgridClient] email_client
|
54
|
+
# @param [EmailObject] email_object
|
55
|
+
# @return [Integer] response_code
|
56
|
+
def self.use_client_client(email_client, email_object)
|
57
|
+
begin
|
58
|
+
response = email_client.send_email(email_object)
|
59
|
+
puts 'Successful attempt' if response == ok_code
|
60
|
+
puts 'Bad Request' if response == bad_req_code
|
61
|
+
puts 'Internal Server Error' if response == internal_err_code
|
62
|
+
rescue StandardError => e
|
63
|
+
# Log error and fail send
|
64
|
+
puts "Error: #{e.message}"
|
65
|
+
response = internal_err_code
|
66
|
+
end
|
67
|
+
response
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,123 @@
|
|
1
|
+
require './lib/email_api/email/data/email_address'
|
2
|
+
require './lib/email_api/email/data/email_object'
|
3
|
+
require 'rest-client'
|
4
|
+
require 'json'
|
5
|
+
|
6
|
+
# Client for sending email via Mailgun v3 API
|
7
|
+
class MailgunClient
|
8
|
+
@exp_msg ||= 'Queued. Thank you.'
|
9
|
+
@ok_code ||= 200
|
10
|
+
@bad_req_code ||= 400
|
11
|
+
@internal_err_code ||= 500
|
12
|
+
|
13
|
+
# Accessor for the expected success message
|
14
|
+
def self.exp_msg
|
15
|
+
@exp_msg
|
16
|
+
end
|
17
|
+
|
18
|
+
# Accessor for the OK Code
|
19
|
+
def self.ok_code
|
20
|
+
@ok_code
|
21
|
+
end
|
22
|
+
|
23
|
+
# Accessor for the Bad Request Code
|
24
|
+
def self.bad_req_code
|
25
|
+
@bad_req_code
|
26
|
+
end
|
27
|
+
|
28
|
+
# Accessor for the Internal Server Error Code
|
29
|
+
def self.internal_err_code
|
30
|
+
@internal_err_code
|
31
|
+
end
|
32
|
+
|
33
|
+
# Sends an email over HTTPS
|
34
|
+
#
|
35
|
+
# @param [EmailObject] email_object
|
36
|
+
# @return [Response] rest_client_response
|
37
|
+
def self.send_email(email_object)
|
38
|
+
|
39
|
+
# Build Mailgun-specific URL and POST data
|
40
|
+
api_key = ENV['MAILGUN_PRIVATE_KEY']
|
41
|
+
domain = ENV['MAILGUN_DOMAIN']
|
42
|
+
return internal_err_code if api_key.nil? || domain.nil?
|
43
|
+
|
44
|
+
post_data = parse_post_data(email_object, domain)
|
45
|
+
return bad_req_code if post_data.nil?
|
46
|
+
|
47
|
+
url = "https://api:#{api_key}@api.mailgun.net/v3/#{domain}/messages"
|
48
|
+
|
49
|
+
# Send Email, return response
|
50
|
+
begin
|
51
|
+
response = RestClient.post url, post_data
|
52
|
+
rescue StandardError => e
|
53
|
+
# Log error and fail send -> occurs when Code 400 due to implementation
|
54
|
+
puts "Error: #{e.message}"
|
55
|
+
return bad_req_code
|
56
|
+
end
|
57
|
+
|
58
|
+
puts "Secondary Client Response: #{response}"
|
59
|
+
|
60
|
+
# Handle expected output. Note that it is API specific.
|
61
|
+
return ok_code if JSON.parse(response)['message'] == exp_msg
|
62
|
+
|
63
|
+
bad_req_code
|
64
|
+
end
|
65
|
+
|
66
|
+
# Parses email address into proper, supported text format
|
67
|
+
#
|
68
|
+
# @param [EmailAddress] email_address
|
69
|
+
# @return [String] email_address_text
|
70
|
+
def self.parse_addr_text(email_address)
|
71
|
+
return nil if email_address.nil? || !email_address.is_a?(EmailAddress)
|
72
|
+
"#{email_address.name} <#{email_address.email}>"
|
73
|
+
end
|
74
|
+
|
75
|
+
# Parses array of email addresses into proper, supported text format
|
76
|
+
#
|
77
|
+
# @param [EmailAddress[]] email_address_arr
|
78
|
+
# @return [String] email_field
|
79
|
+
def self.parse_addr_arr(email_address_arr)
|
80
|
+
return '' if email_address_arr.nil? || !email_address_arr.is_a?(Array)
|
81
|
+
|
82
|
+
# Convert array of multiple email addresses to proper text format
|
83
|
+
email_field = ''
|
84
|
+
email_address_arr.each do |email_address|
|
85
|
+
addr_text = parse_addr_text(email_address)
|
86
|
+
unless addr_text.nil?
|
87
|
+
email_field += ', ' unless email_field.empty?
|
88
|
+
email_field += addr_text
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
email_field
|
93
|
+
end
|
94
|
+
|
95
|
+
# Parses an EmailObject into POST data for use in an API call
|
96
|
+
#
|
97
|
+
# @param [EmailObject] email_object
|
98
|
+
# @return [String] post_data
|
99
|
+
def self.parse_post_data(email_object, domain)
|
100
|
+
# Handle missing or unsupported input parameter
|
101
|
+
return nil if email_object.nil? || domain.nil? || !email_object.is_a?(EmailObject)
|
102
|
+
|
103
|
+
# Handle missing mandatory Email Attributes
|
104
|
+
return nil if email_object.from.nil? || email_object.to.nil? ||
|
105
|
+
email_object.subject.nil? || email_object.content.nil?
|
106
|
+
|
107
|
+
# Parse environment value and build Mailgun-specific FROM email
|
108
|
+
from_email = EmailAddress.new(email_object.from.name, "mailgun@#{domain}")
|
109
|
+
|
110
|
+
# Build Message Attributes
|
111
|
+
post_data = {}
|
112
|
+
post_data[:from] = parse_addr_text(from_email)
|
113
|
+
post_data[:to] = parse_addr_arr(email_object.to)
|
114
|
+
post_data[:cc] = parse_addr_arr(email_object.cc) unless email_object.cc.nil?
|
115
|
+
post_data[:bcc] = parse_addr_arr(email_object.bcc) unless email_object.bcc.nil?
|
116
|
+
post_data[:subject] = email_object.subject.to_s
|
117
|
+
post_data[:text] = email_object.content.to_s
|
118
|
+
|
119
|
+
post_data
|
120
|
+
end
|
121
|
+
|
122
|
+
private_class_method :parse_addr_text, :parse_addr_arr, :parse_post_data
|
123
|
+
end
|
@@ -0,0 +1,115 @@
|
|
1
|
+
require './lib/email_api/email/data/email_object'
|
2
|
+
require 'rest-client'
|
3
|
+
require 'json'
|
4
|
+
|
5
|
+
# Client for sending email via Sendgrid v2 API
|
6
|
+
class SendgridClient
|
7
|
+
@exp_msg ||= 'success'
|
8
|
+
@ok_code ||= 200
|
9
|
+
@bad_req_code ||= 400
|
10
|
+
@internal_err_code ||= 500
|
11
|
+
|
12
|
+
# Accessor for the expected success message
|
13
|
+
def self.exp_msg
|
14
|
+
@exp_msg
|
15
|
+
end
|
16
|
+
|
17
|
+
# Accessor for the OK Code
|
18
|
+
def self.ok_code
|
19
|
+
@ok_code
|
20
|
+
end
|
21
|
+
|
22
|
+
# Accessor for the Bad Request Code
|
23
|
+
def self.bad_req_code
|
24
|
+
@bad_req_code
|
25
|
+
end
|
26
|
+
|
27
|
+
# Accessor for the Internal Server Error Code
|
28
|
+
def self.internal_err_code
|
29
|
+
@internal_err_code
|
30
|
+
end
|
31
|
+
|
32
|
+
# Sends an email over HTTPS
|
33
|
+
#
|
34
|
+
# @param [EmailObject] email_object
|
35
|
+
# @return [int] status_code
|
36
|
+
def self.send_email(email_object)
|
37
|
+
|
38
|
+
# Parse Environment Values
|
39
|
+
api_user = ENV['SENDGRID_API_USER']
|
40
|
+
api_key = ENV['SENDGRID_API_KEY']
|
41
|
+
return internal_err_code if api_user.nil? || api_key.nil?
|
42
|
+
|
43
|
+
# Build Sendgrid-specific URL and POST data
|
44
|
+
url = 'https://api.sendgrid.com/api/mail.send.json'
|
45
|
+
post_data = parse_post_data(email_object, api_user, api_key)
|
46
|
+
return bad_req_code if post_data.nil?
|
47
|
+
|
48
|
+
# Send Email, return response
|
49
|
+
begin
|
50
|
+
response = RestClient.post url, post_data
|
51
|
+
rescue StandardError => e
|
52
|
+
# Log error and fail send -> occurs when Code 400 due to implementation
|
53
|
+
puts "Error: #{e.message}"
|
54
|
+
return bad_req_code
|
55
|
+
end
|
56
|
+
|
57
|
+
puts "Primary Client Response: #{response}"
|
58
|
+
|
59
|
+
return bad_req_code if response.nil? || !JSON.parse(response).respond_to?(:[])
|
60
|
+
|
61
|
+
# Handle expected output. Note that it is API specific.
|
62
|
+
json_response = JSON.parse(response)
|
63
|
+
if !json_response.key?('message').nil? && json_response['message'] == exp_msg
|
64
|
+
return ok_code
|
65
|
+
end
|
66
|
+
|
67
|
+
internal_err_code # Unhandled response
|
68
|
+
end
|
69
|
+
|
70
|
+
# Parses an EmailObject into POST data for use in an API call
|
71
|
+
#
|
72
|
+
# @param [EmailObject] email_object
|
73
|
+
# @return [String] post_data
|
74
|
+
def self.parse_post_data(email_object, api_user, api_key)
|
75
|
+
|
76
|
+
# Handle missing Environment Variables
|
77
|
+
return nil if api_user.nil? || api_key.nil?
|
78
|
+
|
79
|
+
# Handle missing or unsupported input parameter
|
80
|
+
return nil if email_object.nil? || !email_object.is_a?(EmailObject)
|
81
|
+
|
82
|
+
# Handle missing mandatory Email Attributes
|
83
|
+
return nil if email_object.from.nil? || email_object.to.nil? ||
|
84
|
+
email_object.subject.nil? || email_object.content.nil?
|
85
|
+
|
86
|
+
|
87
|
+
# Build Message Attributes
|
88
|
+
post_data = "api_user=#{api_user}"
|
89
|
+
post_data += "&api_key=#{api_key}"
|
90
|
+
post_data += "&subject=#{email_object.subject}"
|
91
|
+
post_data += "&text=#{email_object.content}"
|
92
|
+
post_data += "&from=#{email_object.from.email}"
|
93
|
+
post_data += "&fromname[]=#{email_object.from.name}"
|
94
|
+
email_object.to.each do |address|
|
95
|
+
post_data += "&to[]=#{address.email}"
|
96
|
+
post_data += "&toname[]=#{address.name}"
|
97
|
+
end
|
98
|
+
unless email_object.cc.nil?
|
99
|
+
email_object.cc.each do |address|
|
100
|
+
post_data += "&cc[]=#{address.email}"
|
101
|
+
post_data += "&ccname[]=#{address.name}"
|
102
|
+
end
|
103
|
+
end
|
104
|
+
unless email_object.bcc.nil?
|
105
|
+
email_object.bcc.each do |address|
|
106
|
+
post_data += "&bcc[]=#{address.email}"
|
107
|
+
post_data += "&bccname[]=#{address.name}"
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
post_data
|
112
|
+
end
|
113
|
+
|
114
|
+
private_class_method :parse_post_data
|
115
|
+
end
|