email_sender 1.0.2 → 1.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.
- data/README.rdoc +12 -11
- data/VERSION +1 -1
- data/lib/email_sender.rb +152 -136
- metadata +8 -6
data/README.rdoc
CHANGED
@@ -1,11 +1,12 @@
|
|
1
1
|
= EmailSender Library
|
2
2
|
|
3
|
-
EmailSender is an easy to use library to send email
|
3
|
+
EmailSender is an easy to use library to send email based on Net::SMTP.
|
4
|
+
It supports the well-known encryption and authentication methods, and you can use it very easily with Gmail account.
|
4
5
|
|
5
6
|
require 'email_sender'
|
6
7
|
|
7
8
|
mailer = EmailSender.new(server: "smtp.mail.com", from: "sender@mail.com")
|
8
|
-
mailer.send(to: "receiver@mail.com", subject: "Test mail
|
9
|
+
mailer.send(to: "receiver@mail.com", subject: "Test mail", content: "This is a test mail.")
|
9
10
|
|
10
11
|
== Usage
|
11
12
|
|
@@ -15,7 +16,7 @@ You need specified the connection parameters to SMTP server on initialization:
|
|
15
16
|
mailer = EmailSender.new(server: "smtp.mail.com", from: "Sender Name <sender@mail.com>")
|
16
17
|
|
17
18
|
# encripted and authenticated connection
|
18
|
-
mailer = EmailSender.new(server: "smtp.mail.com",
|
19
|
+
mailer = EmailSender.new(server: "smtp.mail.com", from: "Sender Name <sender@mail.com>",
|
19
20
|
enctype: :ssl_tls, authtype: :plain, username: "user.name", password: "secret")
|
20
21
|
|
21
22
|
Easier way to using Gmail account:
|
@@ -27,7 +28,7 @@ Easier way to using Gmail account:
|
|
27
28
|
# with full sender name
|
28
29
|
mailer = EmailSender.new_gmail(from: "Sender Name <user.name@gmail.com>", password: "secret")
|
29
30
|
|
30
|
-
# with another sender email address and another domain (
|
31
|
+
# with another sender email address and another domain (not gmail.com) account
|
31
32
|
mailer = EmailSender.new_gmail(from: "Sender Name <sender@othermail.com>",
|
32
33
|
username: "user.name@company.com", password: "secret")
|
33
34
|
|
@@ -43,8 +44,8 @@ You can modify easily the parameters of mailer object:
|
|
43
44
|
|
44
45
|
Send the mail to the +:to+, +:cc+ and +:bcc+ addresses with attachment:
|
45
46
|
|
46
|
-
mailer.send(to: "Receiver Name <receiver@mail.com>", subject: "Test mail
|
47
|
-
content: "This is a test mail
|
47
|
+
mailer.send(to: "Receiver Name <receiver@mail.com>", subject: "Test mail",
|
48
|
+
content: "This is a test mail.", attachment: "/path/to/file")
|
48
49
|
|
49
50
|
The +:to+, +:cc+ and +:bcc+ keys accept an email address array so you can send the message to many receivers.
|
50
51
|
And the +:attachment+ key accepts also file path array so you can attach more file:
|
@@ -52,7 +53,7 @@ And the +:attachment+ key accepts also file path array so you can attach more fi
|
|
52
53
|
mailer.send(to: ["Receiver Name 1 <receiver1@mail.com>", "Receiver Name 2 <receiver2@mail.com>"],
|
53
54
|
cc: ["Receiver Name 3 <receiver3@mail.com>", "Receiver Name 4 <receiver4@mail.com>"],
|
54
55
|
bcc: [receiver5@mail.com, "receiver6@mail.com", "receiver7@mail.com"],
|
55
|
-
subject: "Test mail
|
56
|
+
subject: "Test mail", content: "This is a test mail.",
|
56
57
|
attachment: ["/path/to/file1", "/path/to/file2", "/path/to/file3"])
|
57
58
|
|
58
59
|
If there are not specified the +:to+, +:cc+ and +:bcc+ addresses on sending use the initialized default addresses:
|
@@ -63,7 +64,7 @@ If there are not specified the +:to+, +:cc+ and +:bcc+ addresses on sending use
|
|
63
64
|
cc: ["Receiver Name 2 <receiver2@mail.com>", "Receiver Name 3 <receiver3@mail.com>"])
|
64
65
|
|
65
66
|
# send email to the default addresses
|
66
|
-
mailer.send(subject: "Test mail
|
67
|
+
mailer.send(subject: "Test mail", content: "This is a test mail.")
|
67
68
|
|
68
69
|
You can specify the content type which is +'text/plain'+ by default:
|
69
70
|
|
@@ -71,15 +72,15 @@ You can specify the content type which is +'text/plain'+ by default:
|
|
71
72
|
content: "<img src='http://upload.wikimedia.org/wikipedia/commons/7/73/Ruby_logo.svg'/>",
|
72
73
|
conttype: "text/html")
|
73
74
|
|
74
|
-
The library has implemented threadsafe and support the character encoded
|
75
|
+
The library has implemented threadsafe and support the character encoded messages.
|
75
76
|
|
76
77
|
== Installation
|
77
78
|
|
78
|
-
|
79
|
+
gem install email_sender
|
79
80
|
|
80
81
|
== Requirements
|
81
82
|
|
82
|
-
ruby1.9.1
|
83
|
+
ruby1.9.1 or greater
|
83
84
|
|
84
85
|
== License
|
85
86
|
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
1.0
|
1
|
+
1.1.0
|
data/lib/email_sender.rb
CHANGED
@@ -15,10 +15,8 @@
|
|
15
15
|
# <http://www.gnu.org/licenses/>.
|
16
16
|
|
17
17
|
|
18
|
-
require 'openssl'
|
19
18
|
require 'net/smtp'
|
20
19
|
|
21
|
-
|
22
20
|
# == Usage
|
23
21
|
# mailer = EmailSender.new(server: "smtp.mail.com", from: "sender@mail.com")
|
24
22
|
# mailer = EmailSender.new(server: "smtp.mail.com", port: 465, from: Sender Name <"sender@mail.com">,
|
@@ -27,17 +25,17 @@ require 'net/smtp'
|
|
27
25
|
# mailer = EmailSender.new_gmail(username: "user.name", password: "secret")
|
28
26
|
# mailer = EmailSender.new_gmail(from: "Sender Name <user.name@gmail.com>", password: "secret")
|
29
27
|
#
|
30
|
-
# mailer.send(to: "receiver@mail.com", subject: "Test mail
|
28
|
+
# mailer.send(to: "receiver@mail.com", subject: "Test mail", content: "This is a test mail.")
|
31
29
|
# mailer.send(to: "Receiver Name 1 <receiver1@mail.com>", cc: "Receiver Name 2 <receiver2@mail.com>",
|
32
|
-
# subject: "Test mail
|
30
|
+
# subject: "Test mail", content: "This is a test mail.", attachment: "/path/to/file")
|
33
31
|
# See the README for more useful examples!
|
34
32
|
class EmailSender
|
35
33
|
# Major version number
|
36
34
|
VERSION_MAJOR = 1
|
37
35
|
# Minor version number
|
38
|
-
VERSION_MINOR =
|
36
|
+
VERSION_MINOR = 1
|
39
37
|
# Tiny version number
|
40
|
-
VERSION_TINY =
|
38
|
+
VERSION_TINY = 0
|
41
39
|
# Version number
|
42
40
|
VERSION_CODE = (VERSION_MAJOR << 16) | (VERSION_MINOR << 8) | VERSION_TINY
|
43
41
|
# Version string
|
@@ -48,7 +46,7 @@ class EmailSender
|
|
48
46
|
Settings = Struct.new(:server, :port, :domain, :esmtp, :enctype, :authtype,
|
49
47
|
:username, :password, :from_addr, :to_addrs, :cc_addrs, :bcc_addrs) #:nodoc:
|
50
48
|
|
51
|
-
# Create a new
|
49
|
+
# Create a new object and initialize connection parameters.
|
52
50
|
# +-----------------------------------------------------------------------------------+
|
53
51
|
# | Initialization Parameters |
|
54
52
|
# +------------+-------------------------------------------+--------------------------+
|
@@ -67,39 +65,44 @@ class EmailSender
|
|
67
65
|
# |:cc |<string>, <array of string> |[] |
|
68
66
|
# |:bcc |<string>, <array of string> |[] |
|
69
67
|
# +------------+-------------------------------------------+--------------------------+
|
70
|
-
|
68
|
+
# If you do not give any parameters, the instance does not initialize, and the #send() method will do nothing
|
69
|
+
# and return with a nil. You can set and modify the parameters later with the #renew() or #renew_gmail() methods.
|
70
|
+
def initialize(params={})
|
71
71
|
renew(params)
|
72
72
|
end
|
73
73
|
|
74
|
-
# Update the connection parameters
|
75
|
-
# See the ::new method for initialization parameters.
|
76
|
-
def renew(params)
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
74
|
+
# Update the connection parameters.
|
75
|
+
# See the ::new() method for initialization parameters.
|
76
|
+
def renew(params={})
|
77
|
+
server, from = params[:server], params[:from]
|
78
|
+
if server and from
|
79
|
+
settings = Settings.new
|
80
|
+
settings.from_addr = parse_addr(from)
|
81
|
+
settings.to_addrs = parse_addrs(*params[:to])
|
82
|
+
settings.cc_addrs = parse_addrs(*params[:cc])
|
83
|
+
settings.bcc_addrs = parse_addrs(*params[:bcc])
|
84
|
+
settings.domain = params[:domain] || settings.from_addr.first.split('@').last
|
85
|
+
settings.esmtp = params[:esmtp] != :disabled and params[:esmtp] != false
|
86
|
+
settings.enctype = params[:enctype]
|
87
|
+
authtype, username, password = params[:authtype], params[:username], params[:password]
|
88
|
+
if password and username and authtype and authtype != :none
|
89
|
+
settings.authtype = authtype
|
90
|
+
settings.username = username.encode(Encoding::UTF_8)
|
91
|
+
settings.password = password.encode(Encoding::UTF_8)
|
92
|
+
end
|
93
|
+
settings.server = server.encode(Encoding::UTF_8)
|
94
|
+
settings.port = params[:port] || case settings.enctype
|
95
|
+
when :starttls then Net::SMTP.default_submission_port
|
96
|
+
when :ssl_tls then Net::SMTP.default_tls_port
|
97
|
+
else Net::SMTP.default_port
|
98
|
+
end
|
99
|
+
@settings = settings
|
100
|
+
else
|
101
|
+
@settings = nil
|
98
102
|
end
|
99
|
-
@settings = settings
|
100
103
|
end
|
101
104
|
|
102
|
-
# Create a new
|
105
|
+
# Create a new object and initialize connection parameters to Gmail server.
|
103
106
|
# +-----------------------------------------------------------------------------------+
|
104
107
|
# | Gmail Initialization Parameters |
|
105
108
|
# +------------+-------------------------------------------+--------------------------+
|
@@ -112,38 +115,43 @@ class EmailSender
|
|
112
115
|
# |:cc |<string>, <array of string> |[] |
|
113
116
|
# |:bcc |<string>, <array of string> |[] |
|
114
117
|
# +------------+-------------------------------------------+--------------------------+
|
115
|
-
|
118
|
+
# If you do not give any parameters, the instance does not initialize, and the #send() method will do nothing
|
119
|
+
# and return with a nil. You can set and modify the parameters later with the #renew() or #renew_gmail() methods.
|
120
|
+
def self.new_gmail(params={})
|
116
121
|
instance = allocate()
|
117
122
|
instance.renew_gmail(params)
|
118
123
|
instance
|
119
124
|
end
|
120
125
|
|
121
126
|
# Update the connection parameters to Gmail server.
|
122
|
-
# See the ::new_gmail method for Gmail initialization parameters.
|
123
|
-
def renew_gmail(params)
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
end
|
138
|
-
if from
|
139
|
-
from_name, from_addr = parse_addr(from)
|
140
|
-
unless from_addr.include?('@')
|
141
|
-
from_addr << '@gmail.com'
|
142
|
-
params[:from] = from_name ? "#{from_name} <#{from_addr}>" : from_addr
|
127
|
+
# See the ::new_gmail() method for Gmail initialization parameters.
|
128
|
+
def renew_gmail(params={})
|
129
|
+
username, password, from = params[:username], params[:password], params[:from]
|
130
|
+
if password and (username or from)
|
131
|
+
params = params.dup
|
132
|
+
params[:server] = 'smtp.gmail.com'
|
133
|
+
params[:port] = 465
|
134
|
+
params[:domain] = 'gmail.com'
|
135
|
+
params[:esmtp] = :enabled
|
136
|
+
params[:enctype] = :ssl_tls
|
137
|
+
params[:authtype] = :plain
|
138
|
+
if username
|
139
|
+
username = username.encode(Encoding::UTF_8)
|
140
|
+
params[:username] = username << '@gmail.com' unless username.include?('@')
|
141
|
+
params[:from] = username unless from
|
143
142
|
end
|
144
|
-
|
143
|
+
if from
|
144
|
+
from_addr, from_name = parse_addr(from)
|
145
|
+
unless from_addr.include?('@')
|
146
|
+
from_addr << '@gmail.com'
|
147
|
+
params[:from] = from_name ? "#{from_name} <#{from_addr}>" : from_addr
|
148
|
+
end
|
149
|
+
params[:username] = from_addr unless username
|
150
|
+
end
|
151
|
+
renew(params)
|
152
|
+
else
|
153
|
+
renew()
|
145
154
|
end
|
146
|
-
renew(params)
|
147
155
|
end
|
148
156
|
|
149
157
|
# Send an email with the specified parameters.
|
@@ -160,103 +168,111 @@ class EmailSender
|
|
160
168
|
# |:conttype |<string> |'text/plain' |
|
161
169
|
# |:attachment |<string>, <array of string> |[] |
|
162
170
|
# +------------+-------------------------------------------+--------------------------+
|
171
|
+
# After a successful email sending it returns with a truth value (not nil and not false).
|
172
|
+
# If there is not any valid recipient email address or the object is not initialized, then it does nothing
|
173
|
+
# and returns with a nil. Anyway if any error occured during the sending, the Net::SMTP library throw an exception.
|
174
|
+
#
|
163
175
|
# See the README for more information!
|
164
176
|
def send(params={})
|
165
177
|
settings = @settings
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
unless to_addrs.empty?
|
183
|
-
subject = subject.encode(Encoding::UTF_8)
|
184
|
-
content = content.encode(Encoding::UTF_8)
|
185
|
-
smtp = Net::SMTP.new(settings.server, settings.port)
|
186
|
-
smtp.disable_starttls
|
187
|
-
smtp.disable_tls
|
188
|
-
case settings.enctype
|
189
|
-
when :starttls_auto then smtp.enable_starttls_auto
|
190
|
-
when :starttls then smtp.enable_starttls
|
191
|
-
when :ssl_tls then smtp.enable_tls
|
178
|
+
if settings
|
179
|
+
subject = params[:subject] || ''
|
180
|
+
content = params[:content] || subject
|
181
|
+
conttype = params[:conttype] || 'text/plain'
|
182
|
+
attachment = *params[:attachment]
|
183
|
+
to = *params[:to]
|
184
|
+
cc = *params[:cc]
|
185
|
+
bcc = *params[:bcc]
|
186
|
+
if to.empty? and cc.empty? and bcc.empty?
|
187
|
+
to_addrs = settings.to_addrs
|
188
|
+
cc_addrs = settings.cc_addrs
|
189
|
+
bcc_addrs = settings.bcc_addrs
|
190
|
+
else
|
191
|
+
to_addrs = parse_addrs(*to)
|
192
|
+
cc_addrs = parse_addrs(*cc)
|
193
|
+
bcc_addrs = parse_addrs(*bcc)
|
192
194
|
end
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
smtp.
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
to_addrs.
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
stream.puts
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
attachment.
|
233
|
-
|
234
|
-
basename = File.basename(file)
|
235
|
-
filename = basename.ascii_only? ? basename : "=?utf-8?B?#{[basename].pack('m0')}?="
|
236
|
-
stream.puts("--#{boundary}")
|
237
|
-
stream.puts("Content-Type: application/octet-stream; name=\"#{filename}\"")
|
238
|
-
stream.puts("Content-Transfer-Encoding: base64")
|
239
|
-
stream.puts("Content-Disposition: attachment; filename=\"#{filename}\"")
|
195
|
+
unless to_addrs.empty? and cc_addrs.empty? and bcc_addrs.empty?
|
196
|
+
subject = subject.encode(Encoding::UTF_8)
|
197
|
+
content = content.encode(Encoding::UTF_8)
|
198
|
+
smtp = Net::SMTP.new(settings.server, settings.port)
|
199
|
+
smtp.disable_starttls
|
200
|
+
smtp.disable_tls
|
201
|
+
case settings.enctype
|
202
|
+
when :starttls_auto then smtp.enable_starttls_auto
|
203
|
+
when :starttls then smtp.enable_starttls
|
204
|
+
when :ssl_tls then smtp.enable_tls
|
205
|
+
end
|
206
|
+
smtp.esmtp = settings.esmtp
|
207
|
+
message_id = nil
|
208
|
+
smtp.start(settings.domain, settings.username, settings.password, settings.authtype) do
|
209
|
+
from_addr, from_name = settings.from_addr
|
210
|
+
smtp.open_message_stream(from_addr, *to_addrs.keys, *cc_addrs.keys, *bcc_addrs.keys) do |stream|
|
211
|
+
now = Time.now
|
212
|
+
random_id = '%04x%04x.%08x.%08x.%08x' % [Process.pid & 0xFFFF, Thread.current.object_id & 0xFFFF,
|
213
|
+
now.tv_sec & 0xFFFF_FFFF, now.tv_nsec, rand(0x1_0000_0000)]
|
214
|
+
message_id = "#{random_id}@#{settings.domain}"
|
215
|
+
boundary = "boundary0_#{random_id}"
|
216
|
+
stream.puts("Message-ID: <#{message_id}>")
|
217
|
+
stream.puts(now.strftime('Date: %a, %d %b %Y %H:%M:%S %z'))
|
218
|
+
stream.puts("From: " << (from_name ? (from_name.ascii_only? ? "#{from_name} <#{from_addr}>" :
|
219
|
+
"=?utf-8?B?#{[from_name].pack('m0')}?= <#{from_addr}>") : from_addr))
|
220
|
+
to_str = ''
|
221
|
+
to_addrs.each do |addr, name|
|
222
|
+
to = name ? "#{name.ascii_only? ? name : "=?utf-8?B?#{[name].pack('m0')}?="} <#{addr}>" : addr
|
223
|
+
to_str << (to_str.empty? ? "To: #{to}" : ",\n\t#{to}")
|
224
|
+
end
|
225
|
+
stream.puts(to_str) unless to_str.empty?
|
226
|
+
cc_str = ''
|
227
|
+
cc_addrs.each do |addr, name|
|
228
|
+
cc = name ? "#{name.ascii_only? ? name : "=?utf-8?B?#{[name].pack('m0')}?="} <#{addr}>" : addr
|
229
|
+
cc_str << (cc_str.empty? ? "CC: #{cc}" : ",\n\t#{cc}")
|
230
|
+
end
|
231
|
+
stream.puts(cc_str) unless cc_str.empty?
|
232
|
+
stream.puts("Subject: " << (subject.ascii_only? ? subject : "=?utf-8?B?#{[subject].pack('m0')}?="))
|
233
|
+
stream.puts("MIME-Version: 1.0")
|
234
|
+
unless attachment.empty?
|
235
|
+
stream.puts("Content-Type: multipart/mixed; boundary=\"#{boundary}\"")
|
240
236
|
stream.puts
|
241
|
-
|
237
|
+
stream.puts("This is a multi-part message in MIME format.")
|
238
|
+
stream.puts("--#{boundary}")
|
239
|
+
end
|
240
|
+
stream.puts("Content-Type: #{conttype}; charset=#{content.ascii_only? ? 'us-ascii' : 'utf-8'}")
|
241
|
+
stream.puts("Content-Transfer-Encoding: base64")
|
242
|
+
stream.puts
|
243
|
+
stream.print([content].pack('m57'))
|
244
|
+
unless attachment.empty?
|
245
|
+
attachment.each do |file|
|
246
|
+
file = file.encode(Encoding::UTF_8)
|
247
|
+
basename = File.basename(file)
|
248
|
+
filename = basename.ascii_only? ? basename : "=?utf-8?B?#{[basename].pack('m0')}?="
|
249
|
+
stream.puts("--#{boundary}")
|
250
|
+
stream.puts("Content-Type: application/octet-stream; name=\"#{filename}\"")
|
251
|
+
stream.puts("Content-Transfer-Encoding: base64")
|
252
|
+
stream.puts("Content-Disposition: attachment; filename=\"#{filename}\"")
|
253
|
+
stream.puts
|
254
|
+
File.open(file) { |io| stream.print([io.read(ATTACHMENT_READ_CACHE)].pack('m57')) until io.eof? }
|
255
|
+
end
|
256
|
+
stream.puts("--#{boundary}--")
|
242
257
|
end
|
243
|
-
stream.puts("--#{boundary}--")
|
244
258
|
end
|
245
259
|
end
|
260
|
+
message_id
|
246
261
|
end
|
247
|
-
message_id
|
248
262
|
end
|
249
263
|
end
|
250
264
|
|
251
265
|
private
|
252
266
|
def parse_addr(str)
|
253
267
|
str = str.encode(Encoding::UTF_8)
|
254
|
-
str.
|
268
|
+
str.strip!
|
269
|
+
addr = str.scan(/\A(.*?)\s*<([^<]*?)>\z/).first
|
270
|
+
addr ? addr.reverse! : [str, nil]
|
255
271
|
end
|
256
272
|
def parse_addrs(*strs)
|
257
273
|
addrs = {}
|
258
274
|
strs.each do |str|
|
259
|
-
|
275
|
+
addr, name = parse_addr(str)
|
260
276
|
addrs[addr] = name
|
261
277
|
end
|
262
278
|
addrs
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: email_sender
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0
|
4
|
+
version: 1.1.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,10 +9,12 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-
|
12
|
+
date: 2012-12-27 00:00:00.000000000 Z
|
13
13
|
dependencies: []
|
14
|
-
description: EmailSender is
|
15
|
-
|
14
|
+
description: ! 'EmailSender is an easy to use library to send email based on Net::SMTP.
|
15
|
+
|
16
|
+
It supports the well-known encryption and authentication methods, and you can use
|
17
|
+
it very easily with GMail account.'
|
16
18
|
email: bakonyi.peter@gmail.com
|
17
19
|
executables: []
|
18
20
|
extensions: []
|
@@ -44,8 +46,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
44
46
|
version: '0'
|
45
47
|
requirements: []
|
46
48
|
rubyforge_project:
|
47
|
-
rubygems_version: 1.8.
|
49
|
+
rubygems_version: 1.8.23
|
48
50
|
signing_key:
|
49
51
|
specification_version: 3
|
50
|
-
summary:
|
52
|
+
summary: EmailSender is an easy to use library to send email.
|
51
53
|
test_files: []
|