gmail-oauth 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|