How to retrieve the web site URL that provides the email service from an email string? - ruby

I am using Ruby on Rails v3.0.9 and I am finding the best way to retrieve the "last part" of a email string and the related web site URL (that is, the web site that provides the email service).
For example, if I have
sample_email_title#gmail.com
I would like to retrieve
gmail.com
and "transform" that so to have the following:
http://www.gmail.com
How can I accomplish that?

You could do something like this:
a = "my_email#gmail.com"
b = a.split("#").last
=> "gmail.com"
"http://www." + b
=> "http://www.gmail.com"
You could do it all in one line with:
"http://www." + "my_email#gmail.com".split('#').last
There may be better ways, but this is fairly simple.

The mail exchange server will often be on a different domain than the email address, so you will have to lookup the MX records using the DNS server to get that information:
require 'resolv'
def mx_host_of_domain(domain)
mx = nil
Resolv::DNS.open do |dns|
servers = dns.getresources(domain, Resolv::DNS::Resource::IN::MX)
if servers && !servers.empty?
mx = servers.sort_by(&:preference).first.exchange.to_s
end
end
mx
end
email = 'stackoverflow' + '#' + 'larshaugseth.com'
mxhost = mx_host_of_domain email.split('#').last
# => in1.smtp.messagingengine.com
url = "http://www.#{mxhost.split('.').last(2).join('.')}/"
# => http://www.messagingengine.com/
Note that there is no guarantee for a web server to be located at this address. In my case the real web address to the email service is https://www.fastmail.fm/, but luckily the one generated by using the above method will forward you there.

Related

FedEx API Tracking a package what is the XML url?

I am having trouble using the FedEx API, I have read through the documentation pertaining to tracking packages. I have gotten all of the numbers I need to fill into the URL (Test tracking number, Account Number, Account Key, Meter Number, User Name and password).
I was given the URL to use from FedEx, "The production server URL is “https://ws.fedex.com:443/web-services”, however, I am also told to replace the credentials with my actual information (Test tracking number, Account Number, Account Key, Meter Number, User Name and password).
I found this code on another StackOverflow post, and I saw that there was a user who had commented that this way of accessing the FedEx xml was outdated. Anyway I included the code posted by Harshal_m_joshi and edited by houbysoft here (original post Tracking API for Fedex and UPS).
xml_req =
"<TrackRequest xmlns='http://fedex.com/ws/track/v3'><WebAuthenticationDetail><UserCredential><Key>YOUR_ACC_KEY</Key>
<Password>YOUR_ACC_PASSWORD</Password></UserCredential></WebAuthenticationDetail><ClientDetail>
<AccountNumber>YOUR_ACC_NUMBER</AccountNumber><MeterNumber>YOUR_ACC_METER_NUMBER</MeterNumber></ClientDetail>
<TransactionDetail><CustomerTransactionId>ActiveShipping</CustomerTransactionId></TransactionDetail>
<Version><ServiceId>trck</ServiceId><Major>3</Major><Intermediate>0</Intermediate><Minor>0</Minor></Version>
<PackageIdentifier><Value>#{track_no}</Value><Type>TRACKING_NUMBER_OR_DOORTAG</Type></PackageIdentifier>
<IncludeDetailedScans>1</IncludeDetailedScans></TrackRequest>"
path = "https://gatewaybeta.fedex.com:443/xml"
#this url connects to the test server of fedex
# for live server url is:"https://gateway.fedex.com:443/xml"
url = URI.parse(path)
http = Net::HTTP.new(url.host,url.port)
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
response = http.post(url.path, xml_req)
response_body = response.body
res = response_body.gsub(/<(\/)?.*?\:(.*?)>/, '<\1\2>')
hash = Hash.from_xml(res.to_s)
and that's it you will get response in hash variable, I converted xml response in to Hash because we can easily use Hash object at our view to display response data.
I was wondering if anyone knew of the new way to do this, or could at least point me in the right direction. I am fairly new to API's only having worked with USPS and WUnderground, which were both easy as pi ;) Any help would be greatly appreciated.
You are going to POST the data to https://ws.fedex.com:443/web-services
Your POST data should look like this...
<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns=\"http://fedex.com/ws/track/v5\">
<soapenv:Header/>
<soapenv:Body>
<TrackRequest xmlns:ns=\"http://fedex.com/ws/track/v5\"
xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"
xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">
<WebAuthenticationDetail>
<UserCredential>
<Key>" .$CFG["fedex_key"] ."</Key>
<Password>" .$CFG["fedex_password"] ."</Password>
</UserCredential>
</WebAuthenticationDetail>
<ClientDetail>
<AccountNumber>" . $CFG["fedex_acct"] ."</AccountNumber>
<MeterNumber>" . $CFG["fedex_meter"] ."</MeterNumber>
" .$tracknum ."
trck
5
0
0
" .$tracknum ."
TRACKING_NUMBER_OR_DOORTAG
true

Reading Withings API ruby

I have been trying for days to pull down activity data from the Withings API using the OAuth Ruby gem. Regardless of what method I try I consistently get back a 503 error response (not enough params) even though I copied the example URI from the documentation, having of course swapped out the userid. Has anybody had any luck with this in the past. I hope it is just something stupid I am doing.
class Withings
API_KEY = 'REMOVED'
API_SECRET = 'REMOVED'
CONFIGURATION = { site: 'https://oauth.withings.com', request_token_path: '/account/request_token',
access_token_path: '/account/access_token', authorize_path: '/account/authorize' }
before do
#consumer = OAuth::Consumer.new API_KEY, API_SECRET, CONFIGURATION
#base_url ||= "#{request.env['rack.url_scheme']}://#{request.env['HTTP_HOST']}#{request.env['SCRIPT_NAME']}"
end
get '/' do
#request_token = #consumer.get_request_token oauth_callback: "#{#base_url}/access_token"
session[:token] = #request_token.token
session[:secret] = #request_token.secret
redirect #request_token.authorize_url
end
get '/access_token' do
#request_token = OAuth::RequestToken.new #consumer, session[:token], session[:secret]
#access_token = #request_token.get_access_token oauth_verifier: params[:oauth_verifier]
session[:token] = #access_token.token
session[:secret] = #access_token.secret
session[:userid] = params[:userid]
redirect "#{#base_url}/activity"
end
get '/activity' do
#access_token = OAuth::AccessToken.new #consumer, session[:token], session[:secret]
response = #access_token.get("http://wbsapi.withings.net/v2/measure?action=getactivity&userid=#{session[:userid]}&startdateymd=2014-01-01&enddateymd=2014-05-09")
JSON.parse(response.body)
end
end
For other API endpoints I get an error response of 247 - The userid provided is absent, or incorrect. This is really frustrating. Thanks
So I figured out the answer after copious amount of Googleing and grasping a better understanding of both the Withings API and the OAuth library I was using. Basically Withings uses query strings to pass in API parameters. I though I was going about passing these parameters correctly when I was making API calls, but apparently I needed to explicitly set the OAuth library to use the query string scheme, like so
http_method: :get, scheme: :query_string
This is appended to my OAuth consumer configuration and all worked fine immediately.

State object once and retrieve multiple attributes

Here is a snippet from a Sinatra app where users will be submitting urls. I must ensure that http:// is prepended to the url in order to route outside my application. How can I state site once and access it's attributes? (Line 3)
p.params= "www.ruby-lang.org/en/"
site = URI(p.params[:url])
site = "http://" + site.host + site.path + site.query
If you need to ensure the url begins with http://, why not use a regex?
p.params = "www.ruby-lang.org/en/"
site = p.params.gsub(/^(­?!http:\/\­/)/, "http­://")
# site = http://www.ruby-lang.org/en/
^(­?!http:\/\­/) matches only when the beginning of the string is not followed by http://

Generating Paypal Signature, 'X-PAYPAL-AUTHORIZATION' in Ruby

Is there any library in Ruby that generates the Signature, 'X-PAYPAL-AUTHORIZATION' header that is required to make calls on behalf of the account holder who has authorized us through the paypal Permissions API.
I am done with the permissions flow and get the required access token, tokenSecret. I feel I am generating the signature incorrectly as all my calls with the the generated 'X-PAYPAL-AUTHORIZATION' fail. They give the following errors:
For NVP call I get:
You do not have permissions to make this API call
And for the GetBasicPersonalData call I get:
Authentication failed. API credentials are incorrect.
Has anyone gone through this in Ruby? What is best way to generate signature. Paypal has just provided some SDK in Paypal, Java, but not the algorithm to generate signature.
Thanks,
Nilesh
Take a look at the PayPal Permissions gem.
https://github.com/moshbit/paypal_permissions
Specifically lib/paypal_permissions/x_pp_authorization.rb
require 'cgi'
require 'openssl'
require 'base64'
class Hash
def to_paypal_permissions_query
collect do |key, value|
"#{key}=#{value}"
end.sort * '&'
end
end
module ActiveMerchant #:nodoc:
module Billing #:nodoc:
module XPPAuthorization
public
def x_pp_authorization_header url, api_user_id, api_password, access_token, access_token_verifier
timestamp = Time.now.to_i.to_s
signature = x_pp_authorization_signature url, api_user_id, api_password, timestamp, access_token, access_token_verifier
{ 'X-PAYPAL-AUTHORIZATION' => "token=#{access_token},signature=#{signature},timestamp=#{timestamp}" }
end
public
def x_pp_authorization_signature url, api_user_id, api_password, timestamp, access_token, access_token_verifier
# no query params, but if there were, this is where they'd go
query_params = {}
key = [
paypal_encode(api_password),
paypal_encode(access_token_verifier),
].join("&")
params = query_params.dup.merge({
"oauth_consumer_key" => api_user_id,
"oauth_version" => "1.0",
"oauth_signature_method" => "HMAC-SHA1",
"oauth_token" => access_token,
"oauth_timestamp" => timestamp,
})
sorted_query_string = params.to_paypal_permissions_query
base = [
"POST",
paypal_encode(url),
paypal_encode(sorted_query_string)
].join("&")
base = base.gsub /%([0-9A-F])([0-9A-F])/ do
"%#{$1.downcase}#{$2.downcase}" # hack to match PayPal Java SDK bit for bit
end
digest = OpenSSL::HMAC.digest('sha1', key, base)
Base64.encode64(digest).chomp
end
# The PayPalURLEncoder java class percent encodes everything other than 'a-zA-Z0-9 _'.
# Then it converts ' ' to '+'.
# Ruby's CGI.encode takes care of the ' ' and '*' to satisfy PayPal
# (but beware, URI.encode percent encodes spaces, and does nothing with '*').
# Finally, CGI.encode does not encode '.-', which we need to do here.
def paypal_encode str
s = str.dup
CGI.escape(s).gsub('.', '%2E').gsub('-', '%2D')
end
end
end
end
Sample parameters:
url = 'https://svcs.sandbox.paypal.com/Permissions/GetBasicPersonalData'
api_user_id = 'caller_1234567890_biz_api1.yourdomain.com'
api_password = '1234567890'
access_token = 'YJGjMOmTUqVPlKOd1234567890-jdQV3eWCOLuCQOyDK1234567890'
access_token_verifier = 'PgUjnwsMhuuUuZlPU1234567890'
The X-PAYPAL-AUTHORIZATION header [is] generated with URL "https://svcs.paypal.com/Permissions/GetBasicPersonalData". (see page 23, and chapter 7, at the link)
NVP stating "You do not have permissions to make this API call" means your API credentials are correct, just that your account does not have permission for the particular API you are trying to call. Something between the two calls you are submitting is not using the same API credentials.
For NVP call I get:
What NVP call?
TransactionSearch (see comments below)
Also, if you haven't already done so, you will want to use the sandbox APP-ID for testing in the sandbox, and you will need to apply for an app-id with Developer Technical Services (DTS) at PayPal to get an App-ID for live.
EDIT:
To use the TransactionSearch API, all you should be submitting is below. You do not need to specify any extra headers.
USER=xxxxxxxxxxxxxxxxxx
PWD=xxxxxxxxxxxxxxxxxx
SIGNATURE=xxxxxxxxxxxxxxxxxx
METHOD=TransactionSearch
VERSION=86.0
STARTDATE=2009-10-11T00:00:00Z
TRANSACTIONID=1234567890
//And for submitting API calls on bob's behalf, if his PayPal email was bob#bob.com:
SUBJECT=bob#bob.com

Ruby: Dynamically defining classes based on user input

I'm creating a library in Ruby that allows the user to access an external API. That API can be accessed via either a SOAP or a REST API. I would like to support both.
I've started by defining the necessary objects in different modules. For example:
soap_connecton = Library::Soap::Connection.new(username, password)
response = soap_connection.create Library::Soap::LibraryObject.new(type, data, etc)
puts response.class # Library::Soap::Response
rest_connecton = Library::Rest::Connection.new(username, password)
response = rest_connection.create Library::Rest::LibraryObject.new(type, data, etc)
puts response.class # Library::Rest::Response
What I would like to do is allow the user to specify that they only wish to use one of the APIs, perhaps something like this:
Library::Modes.set_mode(Library::Modes::Rest)
rest_connection = Library::Connection.new(username, password)
response = rest_connection.create Library::LibraryObject.new(type, data, etc)
puts response.class # Library::Response
However, I have not yet discovered a way to dynamically set, for example, Library::Connection based on the input to Library::Modes.set_mode. What would be the best way to implement this functionality?
Murphy's law prevails; find an answer right after posting the question to Stack Overflow.
This code seems to have worked for me:
module Library
class Modes
Rest = 1
Soap = 2
def self.set_mode(mode)
case mode
when Rest
Library.const_set "Connection", Class.new(Library::Rest::Connection)
Library.const_set "LibraryObject", Class.new(Library::Rest::LibraryObject)
when Soap
Library.const_set "Connection", Class.new(Library::Soap::Connection)
Library.const_set "LibraryObject", Class.new(Library::Soap::LibraryObject)
else
throw "#{mode.to_s} is not a valid Library::Mode"
end
end
end
end
A quick test:
Library::Modes.set_mode(Library::Modes::Rest)
puts Library::Connection.class == Library::Rest::Connection.class # true
c = Library::Connection.new(username, password)

Resources