pony-express 0.6.1 → 0.6.5

Sign up to get free protection for your applications and to get access to all the features.
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
1
+ 0.6.5
data/ext/mimetic.cxx CHANGED
@@ -1,5 +1,7 @@
1
1
  #include <ruby.h>
2
- #include <ruby/encoding.h>
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/rfc1341.txt MIME Extensions - Multipart related.
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: CHECK FOR MEMORY LEAKS - not sure if mimetic releases mime parts.
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, const char *mimetype) {
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(mimetype));
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 get_mime_type(string file) {
59
- Pcre regex("\\.");
60
- string extn = regex.split(file).back();
61
- transform(extn.begin(), extn.end(), extn.begin(), ::tolower);
62
- string mime = MimeTypes[extn];
63
- return mime.length() > 0 ? mime : MimeTypes["bin"];
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=UTF-8");
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 ? ContentId() : ContentId(RSTRING_PTR(tcid)));
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=UTF-8");
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 ? ContentId() : ContentId(RSTRING_PTR(hcid)));
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=UTF-8");
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), get_mime_type(RSTRING_PTR(attachment)).c_str());
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(RSTRING_PTR(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.1
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-03 00:00:00 +10:00
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.