Skip to content

Commit

Permalink
Update to work with TMail and also the Mail gem.
Browse files Browse the repository at this point in the history
  • Loading branch information
r38y committed Aug 28, 2010
1 parent 32ab8e0 commit 5ef6aa6
Show file tree
Hide file tree
Showing 6 changed files with 229 additions and 46 deletions.
2 changes: 2 additions & 0 deletions .bundle/config
@@ -0,0 +1,2 @@
---
BUNDLE_WITHOUT: ""
18 changes: 18 additions & 0 deletions Gemfile
@@ -0,0 +1,18 @@
source :gemcutter

gem "rake"
gem "jeweler"
gem "tmail"
gem "mail"

group :test do
gem "rspec"
gem "cucumber"
gem "activesupport"
gem "json"
gem "ruby-debug"
gem "fakeweb"
gem "fakeweb-matcher"
gem "timecop"
gem "yajl-ruby"
end
67 changes: 59 additions & 8 deletions lib/postmark.rb
@@ -1,18 +1,18 @@
require 'net/http'
require 'net/https'
require 'rubygems'
require 'tmail'
require 'postmark/tmail_mail_extension'
require 'postmark/bounce'
require 'postmark/json'
require 'postmark/http_client'
require 'postmark/tmail_mail_extension'
require 'postmark/mail_message_extension'

module Postmark

class InvalidApiKeyError < StandardError; end
class UnknownError < StandardError; end
class InvalidMessageError < StandardError; end
class InternalServerError < StandardError; end
class UnknownMessageType < StandardError; end

module ResponseParsers
autoload :Json, 'postmark/response_parsers/json'
Expand Down Expand Up @@ -71,11 +71,11 @@ def sleep_between_retries
def configure
yield self
end

def send_through_postmark(message) #:nodoc:
@retries = 0
begin
HttpClient.post("email", Postmark::Json.encode(convert_tmail(message)))
HttpClient.post("email", Postmark::Json.encode(convert(message)))
rescue Exception => e
if @retries < max_retries
@retries += 1
Expand All @@ -85,17 +85,68 @@ def send_through_postmark(message) #:nodoc:
end
end
end


def convert(message)
if message.is_a?(TMail::Mail)
convert_tmail(message)
else
convert_mail(message)
end
end

def delivery_stats
HttpClient.get("deliverystats")
end

protected

def convert_mail(message)
options = { "From" => message.from.to_s, "Subject" => message.subject }

headers = extract_mail_headers(message)
options["Headers"] = headers unless headers.length == 0

options["To"] = message.to.join(", ")

options["Tag"] = message.tag.to_s unless message.tag.nil?

options["Cc"] = message.cc.join(", ").to_s unless message.cc.nil?

options["Bcc"] = message.bcc.join(", ").to_s unless message.bcc.nil?

if reply_to = message['reply-to']
options["ReplyTo"] = reply_to.to_s
end

html = message.body_html
text = message.body_text
if message.multipart?
options["HtmlBody"] = html
options["TextBody"] = text
elsif html
options["HtmlBody"] = html
else
options["TextBody"] = text
end
options
end

def extract_mail_headers(message)
headers = []
message.header.fields.each do |field|
key = field.name
value = field.value
next if bogus_headers.include? key.dup.downcase
name = key.split(/-/).map {|i| i.capitalize }.join('-')
headers << { "Name" => name, "Value" => value }
end
headers
end

def convert_tmail(message)
options = { "From" => message['from'].to_s, "To" => message['to'].to_s, "Subject" => message.subject }

headers = extract_headers(message)
headers = extract_tmail_headers(message)
options["Headers"] = headers unless headers.length == 0

options["Tag"] = message.tag.to_s unless message.tag.nil?
Expand All @@ -121,7 +172,7 @@ def convert_tmail(message)
options
end

def extract_headers(message)
def extract_tmail_headers(message)
headers = []
message.each_header do |key, value|
next if bogus_headers.include? key.dup.downcase
Expand Down
25 changes: 25 additions & 0 deletions lib/postmark/mail_message_extension.rb
@@ -0,0 +1,25 @@
module Mail
class Message
def tag
self["TAG"]
end

def tag=(value)
self["TAG"] = value
end

def body_html
unless html_part.nil?
html_part.body.to_s
end
end

def body_text
if text_part.nil?
body.to_s
else
text_part.body.to_s
end
end
end
end
161 changes: 123 additions & 38 deletions spec/postmark_spec.rb
Expand Up @@ -2,7 +2,7 @@

describe "Postmark" do

let :message do
let :tmail_message do
TMail::Mail.new.tap do |mail|
mail.from = "sheldon@bigbangtheory.com"
mail.to = "lenard@bigbangtheory.com"
Expand All @@ -11,7 +11,7 @@
end
end

let :html_message do
let :tmail_html_message do
TMail::Mail.new.tap do |mail|
mail.from = "sheldon@bigbangtheory.com"
mail.to = "lenard@bigbangtheory.com"
Expand All @@ -20,6 +20,40 @@
mail.content_type = "text/html"
end
end

let :mail_message do
Mail.new do
from "sheldon@bigbangtheory.com"
to "lenard@bigbangtheory.com"
subject "Hello!"
body "Hello Sheldon!"
end
end

let :mail_html_message do
mail = Mail.new do
from "sheldon@bigbangtheory.com"
to "lenard@bigbangtheory.com"
subject "Hello!"
html_part do
body "<b>Hello Sheldon!</b>"
end
end
end

let :mail_multipart_message do
mail = Mail.new do
from "sheldon@bigbangtheory.com"
to "lenard@bigbangtheory.com"
subject "Hello!"
text_part do
body "Hello Sheldon!"
end
html_part do
body "<b>Hello Sheldon!</b>"
end
end
end

context "service call" do

Expand All @@ -29,28 +63,28 @@

it "should send email successfully" do
FakeWeb.register_uri(:post, "http://api.postmarkapp.com/email", {})
Postmark.send_through_postmark(message)
Postmark.send_through_postmark(tmail_message)
FakeWeb.should have_requested(:post, "http://api.postmarkapp.com/email")
end

it "should warn when header is invalid" do
FakeWeb.register_uri(:post, "http://api.postmarkapp.com/email", {:status => [ "401", "Unauthorized" ], :body => "Missing API token"})
lambda { Postmark.send_through_postmark(message) }.should raise_error(Postmark::InvalidApiKeyError)
lambda { Postmark.send_through_postmark(tmail_message) }.should raise_error(Postmark::InvalidApiKeyError)
end

it "should warn when json is not ok" do
FakeWeb.register_uri(:post, "http://api.postmarkapp.com/email", {:status => [ "422", "Invalid" ], :body => "Invalid JSON"})
lambda { Postmark.send_through_postmark(message) }.should raise_error(Postmark::InvalidMessageError)
lambda { Postmark.send_through_postmark(tmail_message) }.should raise_error(Postmark::InvalidMessageError)
end

it "should warn when server fails" do
FakeWeb.register_uri(:post, "http://api.postmarkapp.com/email", {:status => [ "500", "Internal Server Error" ]})
lambda { Postmark.send_through_postmark(message) }.should raise_error(Postmark::InternalServerError)
lambda { Postmark.send_through_postmark(tmail_message) }.should raise_error(Postmark::InternalServerError)
end

it "should warn when unknown stuff fails" do
FakeWeb.register_uri(:post, "http://api.postmarkapp.com/email", {:status => [ "485", "Custom HTTP response status" ]})
lambda { Postmark.send_through_postmark(message) }.should raise_error(Postmark::UnknownError)
lambda { Postmark.send_through_postmark(tmail_message) }.should raise_error(Postmark::UnknownError)
end

it "should retry 3 times" do
Expand All @@ -59,7 +93,7 @@
{ :status => [ 500, "Internal Server Error" ] },
{ } ]
)
lambda { Postmark.send_through_postmark(message) }.should_not raise_error
lambda { Postmark.send_through_postmark(tmail_message) }.should_not raise_error
end
end

Expand All @@ -77,49 +111,100 @@
end

context "tmail parse" do
def be_serialized_to(json)
simple_matcher "be serialized to #{json}" do |message|
Postmark.send(:convert_tmail, tmail_message).should == JSON.parse(json)
end
end

it "should set text body for plain message" do
Postmark.send(:convert_tmail, message)['TextBody'].should_not be_nil
Postmark.send(:convert_tmail, tmail_message)['TextBody'].should_not be_nil
end

it "should set html body for html message" do
Postmark.send(:convert_tmail, html_message)['HtmlBody'].should_not be_nil
Postmark.send(:convert_tmail, tmail_html_message)['HtmlBody'].should_not be_nil
end
end

def be_serialized_to(json)
simple_matcher "be serialized to #{json}" do |message|
Postmark.send(:convert_tmail, message).should == JSON.parse(json)

it "should encode custom headers headers properly" do
tmail_message["CUSTOM-HEADER"] = "header"
tmail_message.should be_serialized_to %q[{"Subject":"Hello!", "From":"sheldon@bigbangtheory.com", "To":"lenard@bigbangtheory.com", "TextBody":"Hello Sheldon!", "Headers":[{"Name":"Custom-Header", "Value":"header"}]}]
end
end

it "should encode custom headers headers properly" do
message["CUSTOM-HEADER"] = "header"
message.should be_serialized_to %q[{"Subject":"Hello!", "From":"sheldon@bigbangtheory.com", "To":"lenard@bigbangtheory.com", "TextBody":"Hello Sheldon!", "Headers":[{"Name":"Custom-Header", "Value":"header"}]}]
end
it "should encode reply to" do
tmail_message.reply_to = ['a@a.com', 'b@b.com']
tmail_message.should be_serialized_to %q[{"Subject":"Hello!", "From":"sheldon@bigbangtheory.com", "ReplyTo":"a@a.com, b@b.com", "To":"lenard@bigbangtheory.com", "TextBody":"Hello Sheldon!"}]
end

it "should encode reply to" do
message.reply_to = ['a@a.com', 'b@b.com']
message.should be_serialized_to %q[{"Subject":"Hello!", "From":"sheldon@bigbangtheory.com", "ReplyTo":"a@a.com, b@b.com", "To":"lenard@bigbangtheory.com", "TextBody":"Hello Sheldon!"}]
end
it "should encode tag" do
tmail_message.tag = "invite"
tmail_message.should be_serialized_to %q[{"Subject":"Hello!", "From":"sheldon@bigbangtheory.com", "Tag":"invite", "To":"lenard@bigbangtheory.com", "TextBody":"Hello Sheldon!"}]
end

it "should encode tag" do
message.tag = "invite"
message.should be_serialized_to %q[{"Subject":"Hello!", "From":"sheldon@bigbangtheory.com", "Tag":"invite", "To":"lenard@bigbangtheory.com", "TextBody":"Hello Sheldon!"}]
end
it "should encode multiple recepients (TO)" do
tmail_message.to = ['a@a.com', 'b@b.com']
tmail_message.should be_serialized_to %q[{"Subject":"Hello!", "From":"sheldon@bigbangtheory.com", "To":"a@a.com, b@b.com", "TextBody":"Hello Sheldon!"}]
end

it "should encode multiple recepients (TO)" do
message.to = ['a@a.com', 'b@b.com']
message.should be_serialized_to %q[{"Subject":"Hello!", "From":"sheldon@bigbangtheory.com", "To":"a@a.com, b@b.com", "TextBody":"Hello Sheldon!"}]
end
it "should encode multiple recepients (CC)" do
tmail_message.cc = ['a@a.com', 'b@b.com']
tmail_message.should be_serialized_to %q[{"Cc":"a@a.com, b@b.com", "Subject":"Hello!", "From":"sheldon@bigbangtheory.com", "To":"lenard@bigbangtheory.com", "TextBody":"Hello Sheldon!"}]
end

it "should encode multiple recepients (CC)" do
message.cc = ['a@a.com', 'b@b.com']
message.should be_serialized_to %q[{"Cc":"a@a.com, b@b.com", "Subject":"Hello!", "From":"sheldon@bigbangtheory.com", "To":"lenard@bigbangtheory.com", "TextBody":"Hello Sheldon!"}]
it "should encode multiple recepients (BCC)" do
tmail_message.bcc = ['a@a.com', 'b@b.com']
tmail_message.should be_serialized_to %q[{"Bcc":"a@a.com, b@b.com", "Subject":"Hello!", "From":"sheldon@bigbangtheory.com", "To":"lenard@bigbangtheory.com", "TextBody":"Hello Sheldon!"}]
end
end

context "mail parse" do
def be_serialized_to(json)
simple_matcher "be serialized to #{json}" do |message|
Postmark.send(:convert_mail, mail_message).should == JSON.parse(json)
end
end

it "should set text body for plain message" do
Postmark.send(:convert_mail, mail_message)['TextBody'].should_not be_nil
end

it "should encode multiple recepients (BCC)" do
message.bcc = ['a@a.com', 'b@b.com']
message.should be_serialized_to %q[{"Bcc":"a@a.com, b@b.com", "Subject":"Hello!", "From":"sheldon@bigbangtheory.com", "To":"lenard@bigbangtheory.com", "TextBody":"Hello Sheldon!"}]
it "should set html body for html message" do
Postmark.send(:convert_mail, mail_html_message)['HtmlBody'].should_not be_nil
end

it "should set html and text body for multipart message" do
Postmark.send(:convert_mail, mail_multipart_message)['HtmlBody'].should_not be_nil
Postmark.send(:convert_mail, mail_multipart_message)['TextBody'].should_not be_nil
end

it "should encode custom headers properly" do
mail_message.header["CUSTOM-HEADER"] = "header"
mail_message.should be_serialized_to %q[{"Subject":"Hello!", "From":"sheldon@bigbangtheory.com", "To":"lenard@bigbangtheory.com", "TextBody":"Hello Sheldon!", "Headers":[{"Name":"Custom-Header", "Value":"header"}]}]
end

it "should encode reply to" do
mail_message.reply_to = ['a@a.com', 'b@b.com']
mail_message.should be_serialized_to %q[{"Subject":"Hello!", "From":"sheldon@bigbangtheory.com", "ReplyTo":"a@a.com, b@b.com", "To":"lenard@bigbangtheory.com", "TextBody":"Hello Sheldon!"}]
end

it "should encode tag" do
mail_message.tag = "invite"
mail_message.should be_serialized_to %q[{"Subject":"Hello!", "From":"sheldon@bigbangtheory.com", "Tag":"invite", "To":"lenard@bigbangtheory.com", "TextBody":"Hello Sheldon!"}]
end

it "should encode multiple recepients (TO)" do
mail_message.to = ['a@a.com', 'b@b.com']
mail_message.should be_serialized_to %q[{"Subject":"Hello!", "From":"sheldon@bigbangtheory.com", "To":"a@a.com, b@b.com", "TextBody":"Hello Sheldon!"}]
end

it "should encode multiple recepients (CC)" do
mail_message.cc = ['a@a.com', 'b@b.com']
mail_message.should be_serialized_to %q[{"Cc":"a@a.com, b@b.com", "Subject":"Hello!", "From":"sheldon@bigbangtheory.com", "To":"lenard@bigbangtheory.com", "TextBody":"Hello Sheldon!"}]
end

it "should encode multiple recepients (BCC)" do
mail_message.bcc = ['a@a.com', 'b@b.com']
mail_message.should be_serialized_to %q[{"Bcc":"a@a.com, b@b.com", "Subject":"Hello!", "From":"sheldon@bigbangtheory.com", "To":"lenard@bigbangtheory.com", "TextBody":"Hello Sheldon!"}]
end
end

context "JSON library support" do
Expand Down

0 comments on commit 5ef6aa6

Please sign in to comment.