pony-express 0.6.1 → 0.6.5
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 +54 -0
- data/VERSION +1 -1
- data/ext/mimetic.cxx +78 -21
- data/lib/pony-express/test.rb +19 -0
- metadata +5 -4
- data/README +0 -43
data/README.rdoc
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
= Pony Express
|
2
|
+
|
3
|
+
A fast and lightweight ruby mailer based on http://github.com/benprew/pony. For a more
|
4
|
+
historical perspective read http://en.wikipedia.org/wiki/Pony_Express.
|
5
|
+
|
6
|
+
== Installation
|
7
|
+
|
8
|
+
sudo apt-get install libmimetic-dev
|
9
|
+
sudo apt-get install libpcre++-dev
|
10
|
+
sudo gem install pony-express
|
11
|
+
|
12
|
+
=== Dependencies
|
13
|
+
|
14
|
+
* Ruby >= 1.9.1
|
15
|
+
* rubygems >= 1.3.5
|
16
|
+
* ruby development libraries (debian: ruby1.9.1-dev)
|
17
|
+
* mimetic >= 0.9.6 development libraries (debian: libmimetic-dev)
|
18
|
+
* pcre++ development libraries (debian: libpcre++-dev)
|
19
|
+
|
20
|
+
== Usage
|
21
|
+
|
22
|
+
require "pony-express"
|
23
|
+
mail = PonyExpress::Mail.new to: "burns@plant.local", from: "homer@home.local", via: "sendmail"
|
24
|
+
mail.add subject: "Hello Mr.Burns", text: "Can I have more donuts ?", html: "<strong>More Dooooonuuuuts!</strong>"
|
25
|
+
mail.add attachments: [ "/home/homer/donuts.png" ]
|
26
|
+
mail.dispatch
|
27
|
+
|
28
|
+
Don't want to create new mail objects ? Just pass in all options to PonyExpress.mail
|
29
|
+
|
30
|
+
PonyExpress.mail to: "burns@plant.local", from: "homer@home.local", ...
|
31
|
+
|
32
|
+
== Testing
|
33
|
+
|
34
|
+
require "pony-express"
|
35
|
+
require "pony-express/test"
|
36
|
+
mail = PonyExpress::Mail.new to: "burns@plant.local", from: "homer@home.local", via: "sendmail"
|
37
|
+
mail.add subject: "Hello Mr.Burns", text: "Can I have more donuts ?"
|
38
|
+
mail.dispatch
|
39
|
+
assert_equal 1, PonyExpress::Test.mailbox.length
|
40
|
+
|
41
|
+
== TODO
|
42
|
+
|
43
|
+
* Build a rainbow machine and rope in some unicorns.
|
44
|
+
|
45
|
+
== Won't Do
|
46
|
+
|
47
|
+
* Support for Ruby 1.8 or Rubinius or JRuby
|
48
|
+
* MIME parsing. If you need a full blown mail library have a look at the mail gem.
|
49
|
+
|
50
|
+
== License
|
51
|
+
|
52
|
+
GNU GPLv3, so its free and comes with no guarantees. If it brings down your website or burns down your house, I will
|
53
|
+
not be held responsible. Use it at your own risk. You can read all about GNU here: http://www.gnu.org and
|
54
|
+
GNU GPLv3 here: http://www.gnu.org/licenses/gpl.txt.
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.6.
|
1
|
+
0.6.5
|
data/ext/mimetic.cxx
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
#include <ruby.h>
|
2
|
-
|
2
|
+
extern "C" {
|
3
|
+
#include <ruby/encoding.h>
|
4
|
+
}
|
3
5
|
#include <iostream>
|
4
6
|
#include <unistd.h>
|
5
7
|
#include <sstream>
|
@@ -10,36 +12,57 @@
|
|
10
12
|
|
11
13
|
#define ID_CONST_GET rb_intern("const_get")
|
12
14
|
#define CONST_GET(scope, constant) (rb_funcall(scope, ID_CONST_GET, 1, rb_str_new2(constant)))
|
15
|
+
#define RUBY_ENCODING(str) string(rb_enc_get(str)->name)
|
16
|
+
#define VALUEFUNC(f) ((VALUE (*)(ANYARGS)) f)
|
17
|
+
#define FORCE_ENCODING(str,enc) rb_enc_associate(str, rb_to_encoding(enc)); ENC_CODERANGE_CLEAR(str);
|
13
18
|
|
14
19
|
static VALUE rb_mMimetic;
|
15
20
|
static VALUE eRuntimeError;
|
16
21
|
static VALUE eArgumentError;
|
22
|
+
static VALUE rb_UTF8, rb_ASCII;
|
17
23
|
|
18
24
|
using namespace std;
|
19
25
|
using namespace mimetic;
|
20
26
|
using namespace pcrepp;
|
21
27
|
|
22
|
-
#define VALUEFUNC(f) ((VALUE (*)(ANYARGS)) f)
|
23
|
-
|
24
28
|
map<string, string> MimeTypes;
|
25
29
|
|
26
30
|
/* RFC References
|
27
31
|
|
28
32
|
http://www.ietf.org/rfc/rfc2822.txt Internet Message Format.
|
29
|
-
http://www.ietf.org/rfc/
|
33
|
+
http://www.ietf.org/rfc/rfc2045.txt MIME Extensions - Multipart related (Part One).
|
34
|
+
http://www.ietf.org/rfc/rfc2046.txt MIME Extensions - Multipart related (Part Deux).
|
30
35
|
http://www.ietf.org/rfc/rfc2392.txt Content-ID and Message-ID.
|
31
36
|
|
32
37
|
*/
|
33
38
|
|
34
|
-
// TODO
|
39
|
+
// TODO
|
40
|
+
// angle brackets enclosing content and message ids should be part of libmimetic.
|
41
|
+
string content_id() {
|
42
|
+
string cid = ContentId().str();
|
43
|
+
return cid[0] == '<' ? cid : "<" + cid + ">";
|
44
|
+
}
|
45
|
+
|
46
|
+
string message_id(int n) {
|
47
|
+
string mid = MessageId(n).str();
|
48
|
+
return mid[0] == '<' ? mid : "<" + mid + ">";
|
49
|
+
}
|
50
|
+
|
51
|
+
string file_mime_type(string file) {
|
52
|
+
Pcre regex("\\.");
|
53
|
+
string extn = regex.split(file).back();
|
54
|
+
transform(extn.begin(), extn.end(), extn.begin(), ::tolower);
|
55
|
+
string mime = MimeTypes[extn];
|
56
|
+
return mime.length() > 0 ? mime : "application/octet-stream";
|
57
|
+
}
|
35
58
|
|
36
|
-
bool mimetic_attach_file(MimeEntity *m, char* filename
|
59
|
+
bool mimetic_attach_file(MimeEntity *m, char* filename) {
|
37
60
|
filebuf ifile;
|
38
61
|
ostringstream encoded;
|
39
62
|
ifile.open(filename, ios::in);
|
40
63
|
if (ifile.is_open()) {
|
41
64
|
istream is(&ifile);
|
42
|
-
Attachment *at = new Attachment(filename, ContentType(
|
65
|
+
Attachment *at = new Attachment(filename, ContentType(file_mime_type(filename)));
|
43
66
|
Base64::Encoder b64;
|
44
67
|
ostreambuf_iterator<char> oi(encoded);
|
45
68
|
istreambuf_iterator<char> ibegin(is), iend;
|
@@ -55,14 +78,36 @@ bool mimetic_attach_file(MimeEntity *m, char* filename, const char *mimetype) {
|
|
55
78
|
return false;
|
56
79
|
}
|
57
80
|
|
58
|
-
string
|
59
|
-
Pcre
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
81
|
+
string safe_rfc2047(string v) {
|
82
|
+
Pcre re1("\\?");
|
83
|
+
Pcre re2("_");
|
84
|
+
Pcre re3(" ");
|
85
|
+
v = re1.replace(v, "=3F");
|
86
|
+
v = re2.replace(v, "=5F");
|
87
|
+
v = re3.replace(v, "_");
|
88
|
+
return v;
|
64
89
|
}
|
65
90
|
|
91
|
+
string quoted_printable(VALUE str) {
|
92
|
+
VALUE ascii = rb_str_new2(RSTRING_PTR(str));
|
93
|
+
FORCE_ENCODING(ascii, rb_ASCII);
|
94
|
+
if (rb_str_cmp(ascii, str) != 0) {
|
95
|
+
string raw = RSTRING_PTR(str);
|
96
|
+
QP::Encoder qp;
|
97
|
+
istringstream is(raw);
|
98
|
+
ostringstream encoded;
|
99
|
+
istreambuf_iterator<char> ibeg(is), iend;
|
100
|
+
ostreambuf_iterator<char> oi(encoded);
|
101
|
+
encode(ibeg, iend, qp, oi);
|
102
|
+
return "=?" + RUBY_ENCODING(str) + "?Q?" + safe_rfc2047(encoded.str()) + "?=";
|
103
|
+
}
|
104
|
+
else {
|
105
|
+
return string(RSTRING_PTR(str));
|
106
|
+
}
|
107
|
+
}
|
108
|
+
|
109
|
+
// Exposed API
|
110
|
+
|
66
111
|
void rb_load_mime_types(VALUE self, VALUE filename) {
|
67
112
|
char buffer[4096];
|
68
113
|
vector<string> data;
|
@@ -96,6 +141,7 @@ VALUE rb_mimetic_build(VALUE self, VALUE options) {
|
|
96
141
|
if (subject == Qnil) rb_raise(eArgumentError, "Mimetic.build called without :subject");
|
97
142
|
|
98
143
|
// optional fields
|
144
|
+
VALUE mid = rb_hash_aref(options, ID2SYM(rb_intern("message_id")));
|
99
145
|
VALUE html = rb_hash_aref(options, ID2SYM(rb_intern("html")));
|
100
146
|
VALUE tcid = rb_hash_aref(options, ID2SYM(rb_intern("text_content_id")));
|
101
147
|
VALUE hcid = rb_hash_aref(options, ID2SYM(rb_intern("html_content_id")));
|
@@ -104,6 +150,15 @@ VALUE rb_mimetic_build(VALUE self, VALUE options) {
|
|
104
150
|
VALUE bcc = rb_hash_aref(options, ID2SYM(rb_intern("bcc")));
|
105
151
|
VALUE files = rb_hash_aref(options, ID2SYM(rb_intern("attachments")));
|
106
152
|
|
153
|
+
if (mid != Qnil && TYPE(mid) != T_STRING)
|
154
|
+
rb_raise(eArgumentError, "Mimetic.build expects :message_id to be a string");
|
155
|
+
|
156
|
+
if (tcid != Qnil && TYPE(tcid) != T_STRING)
|
157
|
+
rb_raise(eArgumentError, "Mimetic.build expects :text_content_id to be a string");
|
158
|
+
|
159
|
+
if (hcid != Qnil && TYPE(hcid) != T_STRING)
|
160
|
+
rb_raise(eArgumentError, "Mimetic.build expects :html_content_id to be a string");
|
161
|
+
|
107
162
|
if (files != Qnil && TYPE(files) != T_ARRAY)
|
108
163
|
rb_raise(eArgumentError, "Mimetic.build expects :attachments to be an array");
|
109
164
|
|
@@ -122,20 +177,20 @@ VALUE rb_mimetic_build(VALUE self, VALUE options) {
|
|
122
177
|
text_part = new MimeEntity;
|
123
178
|
message->body().parts().push_back(text_part);
|
124
179
|
message->body().parts().push_back(html_part);
|
125
|
-
text_part->header().contentType("text/plain; charset=
|
180
|
+
text_part->header().contentType("text/plain; charset=" + RUBY_ENCODING(text));
|
126
181
|
text_part->header().contentTransferEncoding("8bit");
|
127
|
-
text_part->header().contentId(tcid == Qnil ?
|
182
|
+
text_part->header().contentId(tcid == Qnil ? content_id() + ">" : ContentId(RSTRING_PTR(tcid)));
|
128
183
|
text_part->header().mimeVersion(v1);
|
129
184
|
text_part->body().assign(RSTRING_PTR(text));
|
130
|
-
html_part->header().contentType("text/html; charset=
|
185
|
+
html_part->header().contentType("text/html; charset=" + RUBY_ENCODING(html));
|
131
186
|
html_part->header().contentTransferEncoding("7bit");
|
132
|
-
html_part->header().contentId(hcid == Qnil ?
|
187
|
+
html_part->header().contentId(hcid == Qnil ? content_id() + ">" : ContentId(RSTRING_PTR(hcid)));
|
133
188
|
html_part->header().mimeVersion(v1);
|
134
189
|
html_part->body().assign(RSTRING_PTR(html));
|
135
190
|
}
|
136
191
|
else {
|
137
192
|
message->body().assign(RSTRING_PTR(text));
|
138
|
-
message->header().contentType("text/plain; charset=
|
193
|
+
message->header().contentType("text/plain; charset=" + RUBY_ENCODING(text));
|
139
194
|
message->header().contentTransferEncoding("8bit");
|
140
195
|
message->header().mimeVersion(v1);
|
141
196
|
}
|
@@ -148,14 +203,14 @@ VALUE rb_mimetic_build(VALUE self, VALUE options) {
|
|
148
203
|
for (long i = 0; i < RARRAY_LEN(files); i++) {
|
149
204
|
attachment = rb_ary_entry(files, i);
|
150
205
|
if (attachment != Qnil && TYPE(attachment) == T_STRING)
|
151
|
-
mimetic_attach_file(message, RSTRING_PTR(attachment)
|
206
|
+
mimetic_attach_file(message, RSTRING_PTR(attachment));
|
152
207
|
}
|
153
208
|
}
|
154
209
|
|
155
210
|
message->header().from(RSTRING_PTR(from));
|
156
211
|
message->header().to(RSTRING_PTR(to));
|
157
|
-
message->header().subject(
|
158
|
-
message->header().messageid(1);
|
212
|
+
message->header().subject(quoted_printable(subject));
|
213
|
+
message->header().messageid(mid != Qnil ? RSTRING_PTR(mid) : message_id(1));
|
159
214
|
|
160
215
|
if (replyto != Qnil) message->header().replyto(RSTRING_PTR(replyto));
|
161
216
|
if (cc != Qnil) message->header().cc(RSTRING_PTR(cc));
|
@@ -184,5 +239,7 @@ extern "C" {
|
|
184
239
|
rb_mMimetic = rb_define_module("Mimetic");
|
185
240
|
rb_define_module_function(rb_mMimetic, "build", VALUEFUNC(rb_mimetic_build), 1);
|
186
241
|
rb_define_module_function(rb_mMimetic, "load_mime_types", VALUEFUNC(rb_load_mime_types), 1);
|
242
|
+
rb_UTF8 = rb_str_new2("UTF-8");
|
243
|
+
rb_ASCII = rb_str_new2("US-ASCII");
|
187
244
|
}
|
188
245
|
}
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module PonyExpress
|
2
|
+
module Test
|
3
|
+
def mailbox
|
4
|
+
PonyExpress::Test.mailbox
|
5
|
+
end
|
6
|
+
|
7
|
+
def self.mailbox
|
8
|
+
@@mailbox ||= []
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.transport_via_sendmail content, *rest
|
13
|
+
PonyExpress::Test.mailbox << content
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.transport_via_smtp content, *rest
|
17
|
+
PonyExpress::Test.mailbox << content
|
18
|
+
end
|
19
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pony-express
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.6.
|
4
|
+
version: 0.6.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Bharanee Rathna
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2010-06-
|
12
|
+
date: 2010-06-08 00:00:00 +10:00
|
13
13
|
default_executable:
|
14
14
|
dependencies: []
|
15
15
|
|
@@ -21,14 +21,15 @@ extensions:
|
|
21
21
|
- ext/extconf.rb
|
22
22
|
extra_rdoc_files:
|
23
23
|
- LICENSE
|
24
|
-
- README
|
24
|
+
- README.rdoc
|
25
25
|
files:
|
26
26
|
- LICENSE
|
27
|
-
- README
|
28
27
|
- VERSION
|
29
28
|
- ext/mimetic.cxx
|
30
29
|
- lib/pony-express.rb
|
30
|
+
- lib/pony-express/test.rb
|
31
31
|
- mime.types
|
32
|
+
- README.rdoc
|
32
33
|
has_rdoc: true
|
33
34
|
homepage: http://github.com/deepfryed/pony-express
|
34
35
|
licenses: []
|
data/README
DELETED
@@ -1,43 +0,0 @@
|
|
1
|
-
A fast and lightweight ruby mailer based on http://github.com/benprew/pony. For a more
|
2
|
-
historical perspective read http://en.wikipedia.org/wiki/Pony_Express.
|
3
|
-
|
4
|
-
INSTALL:
|
5
|
-
|
6
|
-
sudo apt-get install libmimetic-dev
|
7
|
-
sudo gem install pony-express
|
8
|
-
|
9
|
-
REQUIREMENT:
|
10
|
-
|
11
|
-
* Ruby >= 1.9.1
|
12
|
-
* rubygems >= 1.3.5
|
13
|
-
* ruby development libraries (debian: ruby1.9.1-dev)
|
14
|
-
* mimetic >= 0.9.6 development libraries (debian: libmimetic-dev)
|
15
|
-
* pcre++ development libraries (debian: libpcre++-dev)
|
16
|
-
|
17
|
-
USAGE:
|
18
|
-
|
19
|
-
>> require "pony-express"
|
20
|
-
>> mail = PonyExpress::Mail.new to: "burns@plant.local", from: "homer@home.local", via: "sendmail"
|
21
|
-
>> mail.add subject: "Hello Mr.Burns", text: "Can I have more donuts", html: "<strong>More Dooooonuuuuts!</strong>"
|
22
|
-
>> mail.add attachments: [ "/home/homer/donuts.png" ]
|
23
|
-
>> mail.dispatch
|
24
|
-
|
25
|
-
Don't want to create new mail objects ? Just pass in all options to PonyExpress.mail
|
26
|
-
|
27
|
-
>> PonyExpress.mail to: "burns@plant.local", from: "homer@home.local", ...
|
28
|
-
|
29
|
-
TODO:
|
30
|
-
|
31
|
-
* Check for Memory Leaks, build a Rainbow machine and rope in some Unicorns.
|
32
|
-
|
33
|
-
DON'T ASK:
|
34
|
-
|
35
|
-
* Support for Ruby 1.8 or Rubinius or JRuby
|
36
|
-
* MIME parsing. If you need a full blown mail library have a look at the mail gem.
|
37
|
-
|
38
|
-
|
39
|
-
LICENSE:
|
40
|
-
|
41
|
-
GNU GPLv3, so its free and comes with no guarantees. If it brings down your website or burns down your house, I will
|
42
|
-
not be held responsible. Use it at your own risk. You can read all about GNU here: http://www.gnu.org and
|
43
|
-
GNU GPLv3 here: http://www.gnu.org/licenses/gpl.txt.
|