Skip to content

Instantly share code, notes, and snippets.

@bricker
Created June 21, 2012 23:43
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save bricker/2969291 to your computer and use it in GitHub Desktop.
Save bricker/2969291 to your computer and use it in GitHub Desktop.
Ruby + Lyris HQ (EmailLabs) - A basic Ruby wrapper for the Email Labs API
# Ruby + Lyris HQ (EmailLabs) - A basic Ruby wrapper for the Email Labs API
# Example usage.
# Message is an imaginary object that you'll have to setup
@message = Message.new(email_subject: "Welcome to My Website!", body: "Welcome to My Website! You can browse blog entries, and watch videos, and much more! Thanks for joining! -The Management" email_sent: false>
lyris = Lyris.new(@message)
if lyris.add_message and lyris.send_message
@message.update_column(:email_sent, true)
puts "Set email_sent=true for #{@message}."
end
# Ruby + Lyris HQ (EmailLabs) - A basic Ruby wrapper for the Email Labs API
# This only handles a few basic functions of the API, but could
# easily be expanded to handle any of the Email Labs API's functions.
# This is adapted from my own application, so please excuse any mistakes.
# Some of these values would not need to be hardcoded if you had richer
# API integration.
LYRIS_API = {
api_host: "www.elabs7.com",
api_path: "/API/mailing_list.html",
site_id: "99999",
password: "xxxxx",
mlid: "123",
from_email: "webmaster@yoursite.com",
from_name: "Your Website",
category: "Newsletter" # Note this must be the name of an existing category
}
class Lyris
require 'builder'
API_ENDPOINT = "https://#{LYRIS_API["api_host"]}#{LYRIS_API["api_path"]}"
# -------------------
def initialize(message)
@site_id = LYRIS_API["site_id"]
@password = LYRIS_API["password"]
@mlid = LYRIS_API["mlid"]
@message = message
end
# -------------------
def add_message
input = generate_input do |body|
body.DATA LYRIS_API["from_email"], type: "from-email"
body.DATA LYRIS_API["from_name"], type: "from-name"
body.DATA 'HTML', type: "message-format"
body.DATA render_message("html"), type: "message-html"
body.DATA render_message("text"), type: "message-text"
body.DATA @message.email_subject, type: "subject"
body.DATA "UTF-8", type: "charset"
body.DATA LYRIS_API["category"], type: "category"
end
# Add a message and get its ID
@message_id = send_request('message', 'add', input)
end
# -------------------
def render_message(format)
# If you're not using Rails, you can just return a string version of the message.
# For Rails, you can setup HTML and Text templates and pass the e-mail content to them,
# and then this method will take the whole message and turn it into a string.
view = ActionView::Base.new(ActionController::Base.view_paths, {})
# If you want to use helpers inside of the e-mail template...
class << view
include ApplicationHelper
include Rails.application.routes.url_helpers
end
view.render(template: "/email/template", formats: [format.to_sym], locals: { message: @message }).to_str
end
# -------------------
def send_message
# Schedule the message. Without any times specified, it send immediately.
# If you want to schedule it for the future,
# add delivery-year, delivery-month, delivery-day, and delivery-hour.
# See Lyris documentation for more information on that.
input = generate_input do |body|
body.MID @message_id
body.DATA 'schedule', type: "action"
body.DATA LYRIS_API["segment_id"], type: "rule"
end
send_request('message', 'schedule', input)
end
# -------------------
def generate_input
# This method sets up the information that needs to be sent to Lyris on
# every request, and then yields to other XML passed in.
input = ''
xml = Builder::XmlMarkup.new(target: input)
xml.instruct!
xml.DATASET do
xml.SITE_ID @site_id
xml.MLID @mlid
xml.DATA @password, type: 'extra', id: 'password'
if block_given?
yield xml
end
end
return input
end
# -------------------
def send_request(type, activity, input)
# Sends off the actual request and returns either
# `false` if there was an error, or
# the success message on success.
response = connection.start do |http|
req = Net::HTTP::Post.new(LYRIS_API["api_path"])
req.set_form_data("activity" => activity, "type" => type, "input" => input)
http.request(req).body
end
if response =~ /<TYPE>error<\/TYPE><DATA>(.+?)<\/DATA>/
return false
elsif response =~ /<TYPE>success<\/TYPE><DATA>(.+?)<\/DATA>/
return $~[1]
end
end
# -------------------
def connection
if !@connection
@connection = Net::HTTP.new(LYRIS_API["api_host"], 443)
@connection.use_ssl = true
@connection.verify_mode = OpenSSL::SSL::VERIFY_NONE
end
@connection
end
end
# Ruby + Lyris HQ (EmailLabs) - A basic Ruby wrapper for the Email Labs API
# Specs
require "fakeweb"
describe Lyris do
describe "#generate_input" do
before :each do
@message = create :message
@lyris = Lyris.new(@message)
end
it "returns a string" do
@lyris.generate_input.should be_a String
end
it "accepts a block and passes that into the XML" do
@lyris.generate_input do |body|
body.DATA "hello"
end.should match /<DATA>hello<\/DATA>/
end
it "always includes the @site_id" do
@lyris.generate_input.should match %r{#{Lyris::LYRIS_API["site_id"]}}
end
it "always includes the @mlid" do
@lyris.generate_input.should match %r{#{Lyris::LYRIS_API["mlid"]}}
end
it "always includes the @password" do
@lyris.generate_input.should match %r{#{Lyris::LYRIS_API["password"]}}
end
end
describe "#add_message" do
before :each do
@message = create :message
@lyris = Lyris.new(@message)
end
it "sets @message_id to the message id on success" do
FakeWeb.register_uri(:post, Lyris::API_ENDPOINT, body: xml_response("success", "12345"))
@lyris.add_message
@lyris.instance_variable_get(:@message_id).should eq "12345"
end
it "sets @message_id to the message id on success" do
FakeWeb.register_uri(:post, Lyris::API_ENDPOINT, body: xml_response("error", "missing something"))
@lyris.add_message
@lyris.instance_variable_get(:@message_id).should be_false
end
it "returns the value of @message_id" do
FakeWeb.register_uri(:post, Lyris::API_ENDPOINT, body: xml_response("success", "12345"))
@lyris.add_message.should eq "12345"
end
end
describe "#render_message" do
before :each do
@message = create :message
@lyris = Lyris.new(@message)
end
it "returns a string" do
@lyris.render_message("html").should be_a String
end
it "raises an exception if the template is not found for that format" do
lambda { @lyris.render_message("json") }.should raise_error
end
it "renders the correct template" do
@lyris.render_message("html").should match /<html /
@lyris.render_message("text").should_not match /<html /
end
end
describe "#send_message" do
before :each do
@message = create :message
@lyris = Lyris.new(@message)
end
it "returns false if an error is returned" do
FakeWeb.register_uri(:post, Lyris::API_ENDPOINT, body: xml_response("error", "missing something"))
@lyris.send_message.should be_false
end
it "returns the message status if success" do
FakeWeb.register_uri(:post, Lyris::API_ENDPOINT, body: xml_response("success", "scheduled"))
@lyris.send_message.should match /scheduled/
end
end
describe "#send_request" do
before :each do
@message = create :message
@lyris = Lyris.new(@message)
@input = @lyris.generate_input
end
it "returns the response data on success" do
FakeWeb.register_uri(:post, Lyris::API_ENDPOINT, body: xml_response("success", "12345"))
@lyris.send_request("message", "add", @input).should eq "12345"
end
it "returns false on error" do
FakeWeb.register_uri(:post, Lyris::API_ENDPOINT, body: xml_response("error", "missing something"))
@lyris.send_request("message", "wrong_action", @input).should be_false
end
end
describe "#connection" do
before :each do
@message = create :message
@lyris = Lyris.new(@message)
end
it "uses the connection if it already exists" do
@lyris.instance_variable_set(:@connection, "hello")
@lyris.connection.should eq "hello"
end
it "instantiates a new connection if one isn't set" do
@lyris.connection.class.should eq Net::HTTP
end
end
end
# Ruby + Lyris HQ (EmailLabs) - A basic Ruby wrapper for the Email Labs API
# A quick method for stubbing the response from Lyris
module LyrisXMLResponse
require 'builder'
def xml_response(response, data)
input = ''
xml = Builder::XmlMarkup.new(target: input)
xml.DATASET do
xml.TYPE response
xml.DATA data
end
xml
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment