gmail-oauth 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +5 -0
- data/.gitignore +21 -0
- data/LICENSE +20 -0
- data/README.markdown +40 -0
- data/Rakefile +39 -0
- data/VERSION +1 -0
- data/examples/three_legged_imap.rb +26 -0
- data/examples/three_legged_smtp.rb +38 -0
- data/lib/gmail-oauth.rb +32 -0
- data/lib/gmail-oauth/client.rb +38 -0
- data/lib/gmail-oauth/request.rb +48 -0
- data/spec/gmail-oauth_request_spec.rb +66 -0
- data/spec/spec_helper.rb +9 -0
- metadata +114 -0
data/.document
ADDED
data/.gitignore
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2010 Bob Potter
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.markdown
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
gmail-oauth
|
2
|
+
===========
|
3
|
+
|
4
|
+
Implements Gmail OAuth access methods for Net::IMAP and Net::SMTP
|
5
|
+
|
6
|
+
Fully working examples (including fetching the access_token) for smtp and imap are in examples/
|
7
|
+
|
8
|
+
IMAP Usage
|
9
|
+
----------
|
10
|
+
|
11
|
+
require 'gmail-oauth'
|
12
|
+
imap = Net::IMAP.new('imap.gmail.com',993,true)
|
13
|
+
|
14
|
+
# For 3legged oauth provide an OAuth::AcessToken
|
15
|
+
imap.authenticate('XOAUTH', "example@gmail.com", :access_token => access_token)
|
16
|
+
|
17
|
+
# For 2legged oauth just provide the OAuth::Consumer
|
18
|
+
#imap.authenticate('XOAUTH', "example@gmail.com", :consumer => consumer)
|
19
|
+
|
20
|
+
imap.list("*","*").each do |folder|
|
21
|
+
puts folder.name
|
22
|
+
end
|
23
|
+
|
24
|
+
SMTP Usage
|
25
|
+
----------
|
26
|
+
|
27
|
+
require 'gmail-oauth'
|
28
|
+
|
29
|
+
raw_email = generate_email()
|
30
|
+
|
31
|
+
smtp = Net::SMTP.new('smtp.gmail.com')
|
32
|
+
smtp.enable_starttls
|
33
|
+
smtp.start('gmail.com', "example@gmail.com", {:access_token => access_token}, :xoauth)
|
34
|
+
smtp.send_message raw_email, "example@gmail.com", "destination@gmail.com"
|
35
|
+
smtp.finish
|
36
|
+
|
37
|
+
Copyright
|
38
|
+
---------
|
39
|
+
|
40
|
+
Copyright (c) 2010 Bob Potter. See LICENSE for details.
|
data/Rakefile
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'jeweler'
|
6
|
+
Jeweler::Tasks.new do |gem|
|
7
|
+
gem.name = "gmail-oauth"
|
8
|
+
gem.summary = %Q{Implements Gmail OAuth access methods for Net::IMAP and Net::SMTP}
|
9
|
+
gem.description = %Q{Implements Gmail OAuth access methods for Net::IMAP and Net::SMTP}
|
10
|
+
gem.email = "bobby.potter@gmail.com"
|
11
|
+
gem.homepage = "http://github.com/bpot/gmail-oauth"
|
12
|
+
gem.authors = ["Bob Potter"]
|
13
|
+
gem.add_development_dependency "rspec", ">= 2.0.0.beta.16"
|
14
|
+
gem.add_dependency "oauth"
|
15
|
+
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
16
|
+
end
|
17
|
+
Jeweler::GemcutterTasks.new
|
18
|
+
rescue LoadError
|
19
|
+
puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
|
20
|
+
end
|
21
|
+
|
22
|
+
require 'rspec/core/rake_task'
|
23
|
+
RSpec::Core::RakeTask.new(:spec) do |c|
|
24
|
+
c.ruby_opts = "-rubygems"
|
25
|
+
end
|
26
|
+
|
27
|
+
task :spec => :check_dependencies
|
28
|
+
|
29
|
+
task :default => :spec
|
30
|
+
|
31
|
+
require 'rake/rdoctask'
|
32
|
+
Rake::RDocTask.new do |rdoc|
|
33
|
+
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
34
|
+
|
35
|
+
rdoc.rdoc_dir = 'rdoc'
|
36
|
+
rdoc.title = "gmail-oauth #{version}"
|
37
|
+
rdoc.rdoc_files.include('README*')
|
38
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
39
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.0.1
|
@@ -0,0 +1,26 @@
|
|
1
|
+
$LOAD_PATH.unshift File.dirname(__FILE__) + '/../lib'
|
2
|
+
require 'rubygems'
|
3
|
+
require 'gmail-oauth'
|
4
|
+
|
5
|
+
raise ArgumentError, "please provide email address (ruby examples/three_legged_imap.rb [email_address])" unless ARGV[0]
|
6
|
+
|
7
|
+
gmail_address = ARGV[0]
|
8
|
+
|
9
|
+
consumer = OAuth::Consumer.new("anonymous", "anonymous",
|
10
|
+
:site => "https://www.google.com",
|
11
|
+
:request_token_path => "/accounts/OAuthGetRequestToken",
|
12
|
+
:authorize_path => "/accounts/OAuthAuthorizeToken",
|
13
|
+
:access_token_path => "/accounts/OAuthGetAccessToken")
|
14
|
+
|
15
|
+
rt = consumer.get_request_token({:oauth_callback => "oob"}, {:scope => "https://mail.google.com/"})
|
16
|
+
print rt.authorize_url + "\n"
|
17
|
+
print "Enter verification code: "
|
18
|
+
code = $stdin.gets.chomp
|
19
|
+
access_token = rt.get_access_token(:oauth_verifier => code)
|
20
|
+
|
21
|
+
#Net::IMAP.debug = true
|
22
|
+
imap = Net::IMAP.new('imap.gmail.com',993,true)
|
23
|
+
imap.authenticate('XOAUTH', gmail_address, :access_token => access_token)
|
24
|
+
imap.list("*","*").each do |folder|
|
25
|
+
puts folder.name
|
26
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
$LOAD_PATH.unshift File.dirname(__FILE__) + '/../lib'
|
2
|
+
require 'rubygems'
|
3
|
+
require 'gmail-oauth'
|
4
|
+
|
5
|
+
raise ArgumentError, "please provide email address (ruby examples/three_legged_smtp.rb [email_address])" unless ARGV[0]
|
6
|
+
|
7
|
+
gmail_address = ARGV[0]
|
8
|
+
|
9
|
+
consumer = OAuth::Consumer.new("anonymous", "anonymous",
|
10
|
+
:site => "https://www.google.com",
|
11
|
+
:request_token_path => "/accounts/OAuthGetRequestToken",
|
12
|
+
:authorize_path => "/accounts/OAuthAuthorizeToken",
|
13
|
+
:access_token_path => "/accounts/OAuthGetAccessToken")
|
14
|
+
|
15
|
+
rt = consumer.get_request_token({:oauth_callback => "oob"}, {:scope => "https://mail.google.com/"})
|
16
|
+
print rt.authorize_url + "\n"
|
17
|
+
print "Enter verification code: "
|
18
|
+
code = $stdin.gets.chomp
|
19
|
+
access_token = rt.get_access_token(:oauth_verifier => code)
|
20
|
+
|
21
|
+
|
22
|
+
msgstr = <<END_OF_MESSAGE
|
23
|
+
From: Blah <#{gmail_address}>
|
24
|
+
To: Destination Address <#{gmail_address}>
|
25
|
+
Subject: test message
|
26
|
+
Date: Sat, 23 Jun 2001 16:26:43 +0900
|
27
|
+
Message-Id: <unique.message.id.string@example.com>
|
28
|
+
|
29
|
+
This is a test message.
|
30
|
+
END_OF_MESSAGE
|
31
|
+
|
32
|
+
smtp = Net::SMTP.new('smtp.gmail.com')
|
33
|
+
smtp.enable_starttls
|
34
|
+
smtp.debug_output = $stdout
|
35
|
+
#smtp.enable_tls
|
36
|
+
smtp.start('gmail.com', gmail_address, {:access_token => access_token}, :xoauth)
|
37
|
+
smtp.send_message msgstr, gmail_address, gmail_address
|
38
|
+
smtp.finish
|
data/lib/gmail-oauth.rb
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'gmail-oauth/request'
|
2
|
+
require 'gmail-oauth/client'
|
3
|
+
require 'net/imap'
|
4
|
+
require 'net/smtp'
|
5
|
+
require 'oauth'
|
6
|
+
require 'cgi'
|
7
|
+
|
8
|
+
class Net::IMAP
|
9
|
+
class XOAuthAuthenticator
|
10
|
+
def initialize(email_address, opts = {})
|
11
|
+
@email_address = email_address
|
12
|
+
@opts = opts
|
13
|
+
end
|
14
|
+
|
15
|
+
def process(s)
|
16
|
+
GmailOAuth::Client.new(@email_address, @opts).xoauth_string
|
17
|
+
end
|
18
|
+
end
|
19
|
+
add_authenticator 'XOAUTH', XOAuthAuthenticator
|
20
|
+
end
|
21
|
+
|
22
|
+
class Net::SMTP
|
23
|
+
def auth_xoauth(email_address, options)
|
24
|
+
auth_string = GmailOAuth::Client.new(email_address, options.merge(:service => :smtp)).xoauth_string
|
25
|
+
res = critical {
|
26
|
+
get_response('AUTH XOAUTH ' + base64_encode(auth_string))
|
27
|
+
}
|
28
|
+
check_auth_response res
|
29
|
+
res
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module GmailOAuth
|
2
|
+
# Client.new("user@gmail.com", :access_token => @access_token)
|
3
|
+
# Client.new("user@mywork.com", :consumer => @consumer)
|
4
|
+
class Client
|
5
|
+
def initialize(email_address, options = {})
|
6
|
+
raise ArgumentError, "Must provide either an access token (3legged oauth) or a consumer (2legged oauth)" if options[:access_token].nil? && options[:consumer].nil?
|
7
|
+
|
8
|
+
@email_address = email_address
|
9
|
+
@access_token = options[:access_token]
|
10
|
+
if @access_token
|
11
|
+
@consumer = @access_token.consumer
|
12
|
+
else
|
13
|
+
@consumer = options[:consumer]
|
14
|
+
end
|
15
|
+
@service = options[:service] || :imap
|
16
|
+
end
|
17
|
+
|
18
|
+
def xoauth_string
|
19
|
+
params = request["parameters"].merge("oauth_signature" => signature)
|
20
|
+
|
21
|
+
prefix = "GET #{request["uri"]} "
|
22
|
+
prefix + params.keys.sort.select { |k| k != "xoauth_requestor_id" }.collect { |k| "#{k}=\"#{CGI.escape(params[k])}\"" }.join(",")
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
def signature
|
27
|
+
OAuth::Signature.sign(request, :scheme => 'header') { [access_token_secret, @consumer.secret] }
|
28
|
+
end
|
29
|
+
|
30
|
+
def access_token_secret
|
31
|
+
@access_token ? @access_token.secret : nil
|
32
|
+
end
|
33
|
+
|
34
|
+
def request
|
35
|
+
@request ||= Request.new(@email_address, @access_token, @consumer, @service).request
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module GmailOAuth
|
2
|
+
class Request
|
3
|
+
def initialize(email_address, access_token, consumer, service = :imap)
|
4
|
+
@email_address = email_address
|
5
|
+
@consumer = consumer
|
6
|
+
@access_token = access_token
|
7
|
+
@service = service
|
8
|
+
end
|
9
|
+
|
10
|
+
def request
|
11
|
+
{
|
12
|
+
"uri" => request_uri,
|
13
|
+
"parameters" => parameters,
|
14
|
+
"method" => "GET"
|
15
|
+
}
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
def two_legged?
|
20
|
+
!@access_token
|
21
|
+
end
|
22
|
+
|
23
|
+
def request_uri
|
24
|
+
uri = "https://mail.google.com/mail/b/#{@email_address}/#{@service}/"
|
25
|
+
if two_legged?
|
26
|
+
uri += "?xoauth_requestor_id=#{CGI.escape(@email_address)}"
|
27
|
+
end
|
28
|
+
uri
|
29
|
+
end
|
30
|
+
|
31
|
+
def parameters
|
32
|
+
params = {
|
33
|
+
"oauth_signature_method" => "HMAC-SHA1",
|
34
|
+
"oauth_version" => "1.0",
|
35
|
+
"oauth_nonce" => OAuth::Helper.generate_nonce,
|
36
|
+
"oauth_timestamp" => OAuth::Helper.generate_timestamp,
|
37
|
+
"oauth_consumer_key" => @consumer.key
|
38
|
+
}
|
39
|
+
|
40
|
+
if two_legged?
|
41
|
+
params["xoauth_requestor_id"] = @email_address
|
42
|
+
else
|
43
|
+
params["oauth_token"] = @access_token.token
|
44
|
+
end
|
45
|
+
params
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
+
|
3
|
+
describe GmailOAuth::Request do
|
4
|
+
|
5
|
+
def consumer
|
6
|
+
OAuth::Consumer.new('consumer_key','secret')
|
7
|
+
end
|
8
|
+
|
9
|
+
def access_token
|
10
|
+
OAuth::AccessToken.new(consumer, 'access_token','secret')
|
11
|
+
end
|
12
|
+
|
13
|
+
context "2legged imap" do
|
14
|
+
before(:each) do
|
15
|
+
@request = GmailOAuth::Request.new("user@mywork.com", nil, consumer)
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should have the correct request uri" do
|
19
|
+
@request.request["uri"].should == "https://mail.google.com/mail/b/user@mywork.com/imap/?xoauth_requestor_id=user%40mywork.com"
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should have oauth_version of 1.0" do
|
23
|
+
@request.request["parameters"]["oauth_version"].should == "1.0"
|
24
|
+
end
|
25
|
+
|
26
|
+
it "should have oauth_signature_method of HMAC_SHA1" do
|
27
|
+
@request.request["parameters"]["oauth_signature_method"].should == "HMAC-SHA1"
|
28
|
+
end
|
29
|
+
|
30
|
+
it "should use access token's consumer's key" do
|
31
|
+
@request.request["parameters"]["oauth_consumer_key"].should == "consumer_key"
|
32
|
+
end
|
33
|
+
|
34
|
+
it "should have the email as the xoauth_requestor_id parameter" do
|
35
|
+
@request.request["parameters"]["xoauth_requestor_id"].should == "user@mywork.com"
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
context "3legged imap" do
|
40
|
+
before(:each) do
|
41
|
+
@request = GmailOAuth::Request.new("user@gmail.com", access_token, consumer)
|
42
|
+
end
|
43
|
+
|
44
|
+
it "should have the correct request uri" do
|
45
|
+
@request.request["uri"].should == "https://mail.google.com/mail/b/user@gmail.com/imap/"
|
46
|
+
end
|
47
|
+
|
48
|
+
it "should use access token's consumer's key" do
|
49
|
+
@request.request["parameters"]["oauth_consumer_key"].should == "consumer_key"
|
50
|
+
end
|
51
|
+
|
52
|
+
it "should have the access token as the oauth_token parameter" do
|
53
|
+
@request.request["parameters"]["oauth_token"].should == "access_token"
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
context "3legged smtp" do
|
58
|
+
before(:each) do
|
59
|
+
@request = GmailOAuth::Request.new("user@gmail.com", access_token, consumer, :smtp)
|
60
|
+
end
|
61
|
+
|
62
|
+
it "should have the correct request uri" do
|
63
|
+
@request.request["uri"].should == "https://mail.google.com/mail/b/user@gmail.com/smtp/"
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,114 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: gmail-oauth
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 29
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 0
|
9
|
+
- 1
|
10
|
+
version: 0.0.1
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Bob Potter
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2010-07-08 00:00:00 -05:00
|
19
|
+
default_executable:
|
20
|
+
dependencies:
|
21
|
+
- !ruby/object:Gem::Dependency
|
22
|
+
name: rspec
|
23
|
+
prerelease: false
|
24
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ">="
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
hash: 62196419
|
30
|
+
segments:
|
31
|
+
- 2
|
32
|
+
- 0
|
33
|
+
- 0
|
34
|
+
- beta
|
35
|
+
- 16
|
36
|
+
version: 2.0.0.beta.16
|
37
|
+
type: :development
|
38
|
+
version_requirements: *id001
|
39
|
+
- !ruby/object:Gem::Dependency
|
40
|
+
name: oauth
|
41
|
+
prerelease: false
|
42
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
43
|
+
none: false
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
hash: 3
|
48
|
+
segments:
|
49
|
+
- 0
|
50
|
+
version: "0"
|
51
|
+
type: :runtime
|
52
|
+
version_requirements: *id002
|
53
|
+
description: Implements Gmail OAuth access methods for Net::IMAP and Net::SMTP
|
54
|
+
email: bobby.potter@gmail.com
|
55
|
+
executables: []
|
56
|
+
|
57
|
+
extensions: []
|
58
|
+
|
59
|
+
extra_rdoc_files:
|
60
|
+
- LICENSE
|
61
|
+
- README.markdown
|
62
|
+
files:
|
63
|
+
- .document
|
64
|
+
- .gitignore
|
65
|
+
- LICENSE
|
66
|
+
- README.markdown
|
67
|
+
- Rakefile
|
68
|
+
- VERSION
|
69
|
+
- examples/three_legged_imap.rb
|
70
|
+
- examples/three_legged_smtp.rb
|
71
|
+
- lib/gmail-oauth.rb
|
72
|
+
- lib/gmail-oauth/client.rb
|
73
|
+
- lib/gmail-oauth/request.rb
|
74
|
+
- spec/gmail-oauth_request_spec.rb
|
75
|
+
- spec/spec_helper.rb
|
76
|
+
has_rdoc: true
|
77
|
+
homepage: http://github.com/bpot/gmail-oauth
|
78
|
+
licenses: []
|
79
|
+
|
80
|
+
post_install_message:
|
81
|
+
rdoc_options:
|
82
|
+
- --charset=UTF-8
|
83
|
+
require_paths:
|
84
|
+
- lib
|
85
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
86
|
+
none: false
|
87
|
+
requirements:
|
88
|
+
- - ">="
|
89
|
+
- !ruby/object:Gem::Version
|
90
|
+
hash: 3
|
91
|
+
segments:
|
92
|
+
- 0
|
93
|
+
version: "0"
|
94
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
95
|
+
none: false
|
96
|
+
requirements:
|
97
|
+
- - ">="
|
98
|
+
- !ruby/object:Gem::Version
|
99
|
+
hash: 3
|
100
|
+
segments:
|
101
|
+
- 0
|
102
|
+
version: "0"
|
103
|
+
requirements: []
|
104
|
+
|
105
|
+
rubyforge_project:
|
106
|
+
rubygems_version: 1.3.7
|
107
|
+
signing_key:
|
108
|
+
specification_version: 3
|
109
|
+
summary: Implements Gmail OAuth access methods for Net::IMAP and Net::SMTP
|
110
|
+
test_files:
|
111
|
+
- spec/gmail-oauth_request_spec.rb
|
112
|
+
- spec/spec_helper.rb
|
113
|
+
- examples/three_legged_smtp.rb
|
114
|
+
- examples/three_legged_imap.rb
|