email-spy 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,21 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ coverage
6
+ InstalledFiles
7
+ lib/bundler/man
8
+ pkg
9
+ rdoc
10
+ spec/reports
11
+ test/tmp
12
+ test/version_tmp
13
+ tmp
14
+
15
+ # YARD artifacts
16
+ .yardoc
17
+ _yardoc
18
+ doc/
19
+
20
+ # 测试数据
21
+ spec/fixture
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --color
data/Gemfile ADDED
@@ -0,0 +1,2 @@
1
+ source "http://ruby.taobao.org"
2
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,49 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ email-spy (0.0.2)
5
+ gdata_19 (~> 1.1.5)
6
+ httpclient (~> 2.2.5)
7
+ mechanize (~> 2.5.1)
8
+ nokogiri (~> 1.5.0)
9
+
10
+ GEM
11
+ remote: http://ruby.taobao.org/
12
+ specs:
13
+ diff-lcs (1.1.3)
14
+ domain_name (0.5.3)
15
+ unf (~> 0.0.3)
16
+ gdata_19 (1.1.5)
17
+ httpclient (2.2.5)
18
+ mechanize (2.5.1)
19
+ domain_name (~> 0.5, >= 0.5.1)
20
+ mime-types (~> 1.17, >= 1.17.2)
21
+ net-http-digest_auth (~> 1.1, >= 1.1.1)
22
+ net-http-persistent (~> 2.5, >= 2.5.2)
23
+ nokogiri (~> 1.4)
24
+ ntlm-http (~> 0.1, >= 0.1.1)
25
+ webrobots (~> 0.0, >= 0.0.9)
26
+ mime-types (1.17.2)
27
+ net-http-digest_auth (1.2.1)
28
+ net-http-persistent (2.7)
29
+ nokogiri (1.5.5)
30
+ ntlm-http (0.1.1)
31
+ rspec (2.11.0)
32
+ rspec-core (~> 2.11.0)
33
+ rspec-expectations (~> 2.11.0)
34
+ rspec-mocks (~> 2.11.0)
35
+ rspec-core (2.11.1)
36
+ rspec-expectations (2.11.2)
37
+ diff-lcs (~> 1.1.3)
38
+ rspec-mocks (2.11.1)
39
+ unf (0.0.5)
40
+ unf_ext
41
+ unf_ext (0.0.5)
42
+ webrobots (0.0.13)
43
+
44
+ PLATFORMS
45
+ ruby
46
+
47
+ DEPENDENCIES
48
+ email-spy!
49
+ rspec (~> 2.11.0)
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 wade
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,21 @@
1
+ email-spy
2
+ =========
3
+
4
+
5
+ Usage
6
+ -----
7
+
8
+ ```ruby
9
+ contacts = EmailSpy.fetch(account, password, emailtype)
10
+ contacts.each do |contact|
11
+ puts "name: #{contact.name}, email: #{contact.email}"
12
+ end
13
+ ```
14
+
15
+ Current Supported Email Type
16
+ --------------------------
17
+
18
+ + gmail
19
+ + hotmail
20
+ + 126
21
+ + yahoo
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
data/email-spy.gemspec ADDED
@@ -0,0 +1,27 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/email-spy/version', __FILE__)
3
+
4
+ Gem::Specification.new do |s|
5
+ s.name = 'email-spy'
6
+ s.version = EmailSpy::VERSION
7
+ s.date = '2012-07-30'
8
+ s.summary = ""
9
+ s.description = "Retrieves contact list of email"
10
+ s.authors = ["Wade Xing"]
11
+ s.email = ['iamxingxing@gmail.com']
12
+ s.files = `git ls-files`.split($\)
13
+
14
+ s.executables = s.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
15
+ s.test_files = s.files.grep(%r{^(test|spec|features)/})
16
+
17
+ s.require_paths = ["lib"]
18
+
19
+ s.homepage = 'https://github.com/xingxing/email-spy'
20
+
21
+ s.add_runtime_dependency "httpclient", "~> 2.2.5"
22
+ s.add_runtime_dependency 'nokogiri', "~> 1.5.0"
23
+ s.add_runtime_dependency 'gdata_19', "~> 1.1.5"
24
+ s.add_runtime_dependency 'mechanize', "~> 2.5.1"
25
+
26
+ s.add_development_dependency 'rspec', "~> 2.11.0"
27
+ end
data/lib/email-spy.rb ADDED
@@ -0,0 +1,38 @@
1
+ # -*- coding: utf-8 -*-
2
+ require 'rubygems'
3
+ require 'bundler/setup'
4
+ require "nokogiri"
5
+ require 'gdata'
6
+
7
+ require 'iconv'
8
+ require "mechanize"
9
+ require "csv"
10
+ require "json"
11
+
12
+ require 'email-spy/contact'
13
+ require 'email-spy/email_types'
14
+ require 'email-spy/version'
15
+ require 'email-spy/errors'
16
+
17
+ require 'email-spy/gmail'
18
+ require "email-spy/hotmail"
19
+ require "email-spy/126"
20
+ require "email-spy/yahoo"
21
+
22
+ module EmailSpy
23
+ # 获取 联系人集合
24
+ # @param [String] 邀请人电邮地址
25
+ # @param [String] 邀请人电邮密码
26
+ # @param [String] 邮件类型
27
+ # @param [Array<EmailSay::Contact>] 联系人集合
28
+ def self.fetch invitor_email_address,invitor_email_password,email_type
29
+ self.const_get(operating_klass_name email_type).fetch invitor_email_address,invitor_email_password
30
+ end
31
+
32
+ private
33
+
34
+ def self.operating_klass_name email_type
35
+ key = email_type.to_s.downcase
36
+ EMAIL_TYPE[key] or raise EmailTypeNotFound
37
+ end
38
+ end
@@ -0,0 +1,60 @@
1
+ # -*- coding: utf-8 -*-
2
+ module EmailSpy
3
+ class OneTowSix
4
+
5
+ # 登录页
6
+ LANDING_PAGE_URL = 'http://mail.126.com'
7
+
8
+ # 联系人 URL 模板
9
+ Contacts_URL = "http://tg1a64.mail.126.com/jy3/address/addrlist.jsp?sid=%s"
10
+
11
+ def self.fetch invitor_email_address,invitor_email_password
12
+ self.new(invitor_email_address,invitor_email_password).contacts
13
+ end
14
+
15
+
16
+ def initialize invitor_email_address,invitor_email_password
17
+ @invitor_email_address = invitor_email_address
18
+ @invitor_email_password = invitor_email_password
19
+ @agent = Mechanize.new
20
+ end
21
+
22
+ # 通讯录联系人
23
+ # @return [Array<EmailSpy::Contract>]
24
+ def contacts
25
+ body = @agent.get(Contacts_URL % sid).body
26
+ contacts = []
27
+
28
+ Nokogiri::HTML(body).xpath(".//*[@id='addrstable']/tbody[1]/tr").each do |tr|
29
+ contacts << Contact.new(tr.css(".Ibx_Td_addrName a").text,
30
+ tr.css(".Ibx_Td_addrEmail a").text)
31
+ end
32
+
33
+ contacts
34
+ end
35
+
36
+ private
37
+
38
+ # 登录
39
+ # @return [String] SID
40
+ def sid
41
+ page = @agent.get(LANDING_PAGE_URL)
42
+ login_form = page.forms[0]
43
+ login_form.action= 'http://reg.163.com/login.jsp'
44
+ login_form.add_field!('type',1)
45
+ login_form.add_field!('product','mail126')
46
+ login_form.add_field!('url' ,URI.encode("http://entry.mail.126.com/cgi/ntesdoor?hid=10010102&lightweight=1&language=0&style=3"))
47
+ login_form.username ,login_form.password = @invitor_email_address,@invitor_email_password
48
+ page = login_form.submit(login_form.buttons.first)
49
+ page1 = login_form.click_button
50
+ page2 = page1.links[0].click
51
+
52
+ page3 = @agent.get('http://entry.mail.126.com/cgi/ntesdoor?verifycookie=1&lightweight=1&style=-1')
53
+ page3.uri.to_s.scan(/sid=(\S+)/).first[0]
54
+ end
55
+ end
56
+
57
+ private
58
+
59
+ EMAIL_TYPE['126'] = "OneTowSix"
60
+ end
@@ -0,0 +1,3 @@
1
+ module EmailSpy
2
+ Contact = Struct.new(:name, :email)
3
+ end
@@ -0,0 +1,3 @@
1
+ module EmailSpy
2
+ EMAIL_TYPE = {}
3
+ end
@@ -0,0 +1,22 @@
1
+ module EmailSpy
2
+ class EmailSypError < StandardError
3
+ end
4
+
5
+ class AuthenticationError < EmailSypError
6
+ def initialize(msg = "Email address or password are incorrect")
7
+ super(msg)
8
+ end
9
+ end
10
+
11
+ class ConnectionError < EmailSypError
12
+ def initialize(msg = "Check your network connection")
13
+ super(msg)
14
+ end
15
+ end
16
+
17
+ class EmailTypeNotFound < EmailSypError
18
+ def initialize(msg = "Does not support this message type")
19
+ super(msg)
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,26 @@
1
+ module EmailSpy
2
+ class Gmail
3
+
4
+ Contacts_API_URL = "http://www.google.com/m8/feeds/contacts/default/full"
5
+
6
+ def self.fetch invitor_email_address,invitor_email_password
7
+ client = GData::Client::Contacts.new
8
+ client.clientlogin(invitor_email_address, invitor_email_password)
9
+ response = client.get(Contacts_API_URL).to_xml
10
+
11
+ response.elements.to_a('entry').map do |entry|
12
+ title, email = entry.elements['title'].text, nil
13
+ entry.elements.each('gd:email') do |e|
14
+ email = e.attribute('address').value if e.attribute('primary')
15
+ end
16
+ Contact.new(title,email) unless email.nil?
17
+ end.compact
18
+ rescue GData::Client::AuthorizationError => e
19
+ raise AuthenticationError
20
+ end
21
+ end
22
+
23
+ private
24
+
25
+ EMAIL_TYPE['gmail'] = "Gmail"
26
+ end
@@ -0,0 +1,35 @@
1
+ # -*- coding: utf-8 -*-
2
+ module EmailSpy
3
+ class Hotmail
4
+ # 登录页 地址
5
+ LANDING_PAGE_URL = 'https://login.live.com/login.srf?id=2'
6
+
7
+ # 用户名密码错误提示
8
+ Login_Error_Message = "That password is incorrect. Be sure you're using the password for your Microsoft account."
9
+
10
+ Contacts_URL = "http://co108w.col108.mail.live.com/mail/GetContacts.aspx"
11
+
12
+ def self.fetch invitor_email_address,invitor_email_password
13
+ agent = Mechanize.new
14
+ agent.verify_mode=OpenSSL::SSL::VERIFY_NONE
15
+ page = agent.get(LANDING_PAGE_URL)
16
+ login_form = page.forms[0]
17
+ login_form.login ,login_form.passwd = invitor_email_address,invitor_email_password
18
+ page = login_form.submit
19
+ raise AuthenticationError if page.body.include? Login_Error_Message
20
+ body = agent.get(Contacts_URL).body
21
+
22
+ contacts = []
23
+
24
+ CSV.parse(body,headers: :first_row).each do |record|
25
+ contacts << Contact.new("#{record['Last Name']} #{record['First Name']}",record['E-mail Address'])
26
+ end
27
+
28
+ contacts.compact
29
+ end
30
+ end
31
+
32
+ private
33
+
34
+ EMAIL_TYPE['hotmail'] = "Hotmail"
35
+ end
@@ -0,0 +1,3 @@
1
+ module EmailSpy
2
+ VERSION = '0.0.3'
3
+ end
@@ -0,0 +1,55 @@
1
+ module EmailSpy
2
+ class Yahoo
3
+
4
+ LANDING_PAGE_URL = 'https://login.yahoo.com/config/login'
5
+
6
+ CONTACTS_URL = "http://address.mail.yahoo.com/?.rand=430244936"
7
+
8
+ def self.fetch invitor_email_address,invitor_email_password
9
+ self.new(invitor_email_address,invitor_email_password).contacts
10
+ rescue SocketError => e
11
+ raise ConnectionError
12
+ end
13
+
14
+ def initialize invitor_email_address,invitor_email_password
15
+ @invitor_email_address = invitor_email_address
16
+ @invitor_email_password = invitor_email_password
17
+ @agent = Mechanize.new
18
+ @agent.verify_mode = OpenSSL::SSL::VERIFY_NONE
19
+ end
20
+
21
+ def contacts
22
+ login
23
+ contacts = []
24
+ contacts_json.each do |contact|
25
+ contacts << Contact.new(contact['contactName'],contact['email'])
26
+ end
27
+
28
+ contacts
29
+ end
30
+
31
+
32
+ private
33
+
34
+ def login
35
+ page = @agent.get(LANDING_PAGE_URL)
36
+ login_form = page.forms[0]
37
+ login_form.login = @invitor_email_address
38
+ login_form.passwd = @invitor_email_password
39
+ page = login_form.submit
40
+ raise AuthenticationError if page.body.index("Invalid ID or passowrd") or page.body.index("This ID is not yet taken")
41
+ end
42
+
43
+
44
+ def contacts_json
45
+ contacts_list_source = @agent.get(CONTACTS_URL).body
46
+ contacts_json = contacts_list_source.scan(/InitialContacts\s*=([^;]*);/m)[0][0].to_s
47
+ JSON.load(contacts_json).flatten
48
+ end
49
+
50
+ end
51
+
52
+ private
53
+
54
+ EMAIL_TYPE['yahoo'] = "Yahoo"
55
+ end
data/spec/126_spec.rb ADDED
@@ -0,0 +1,6 @@
1
+ # -*- coding: utf-8 -*-
2
+ require 'spec_helper'
3
+
4
+ describe "126" do
5
+ it_should_behave_like "fetch A contact list","126"
6
+ end
@@ -0,0 +1,21 @@
1
+ # -*- coding: utf-8 -*-
2
+ require 'spec_helper'
3
+
4
+ describe "EmailSpy" do
5
+
6
+ let(:email){ 'iamxingxing@gmail.com' }
7
+ let(:pwd){ 'password' }
8
+
9
+ describe ".fetch" do
10
+ it "should invoke operating class .fech " do
11
+ EmailSpy::Gmail.should_receive(:fetch).with(email,pwd)
12
+ EmailSpy.fetch(email,pwd,"gmail")
13
+ end
14
+
15
+ context "when email type not found" do
16
+ it "should raise A EmailTypeNotFound" do
17
+ lambda { EmailSpy.fetch(email,pwd,"whatever") }.should raise_error(EmailSpy::EmailTypeNotFound)
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,6 @@
1
+ # -*- coding: utf-8 -*-
2
+ require 'spec_helper'
3
+
4
+ describe "Gamil" do
5
+ it_should_behave_like "fetch A contact list","gmail"
6
+ end
@@ -0,0 +1,6 @@
1
+ # -*- coding: utf-8 -*-
2
+ require 'spec_helper'
3
+
4
+ describe "Hotmail" do
5
+ it_should_behave_like "fetch A contact list","hotmail"
6
+ end
@@ -0,0 +1,31 @@
1
+ # -*- coding: utf-8 -*-
2
+ $:.unshift File.expand_path('../../lib', __FILE__)
3
+
4
+ require 'rubygems'
5
+ require 'bundler/setup'
6
+
7
+ require 'email-spy'
8
+
9
+ shared_examples_for "fetch A contact list" do |email_type|
10
+ let(:expected_result) do
11
+ YAML::load(File.read(File.expand_path("spec/fixture/#{email_type}.yml")))
12
+ end
13
+
14
+ before(:all) do
15
+ @contacts = EmailSpy.fetch(expected_result["invitor email"], expected_result["invitor password"], email_type)
16
+ end
17
+
18
+ it "should return expected contact info" do
19
+ @contacts.find do |contact|
20
+ contact.name == expected_result['contact']['name'] and contact.email == expected_result['contact']['email']
21
+ end.should_not == nil
22
+ end
23
+
24
+ it "should return expected length" do
25
+ @contacts.should have(expected_result['contacts count']).items
26
+ end
27
+
28
+ it "should not include the invitor's email" do
29
+ @contacts.map{|c| c.email }.should_not include expected_result['invitor_email']
30
+ end
31
+ end
@@ -0,0 +1,6 @@
1
+ # -*- coding: utf-8 -*-
2
+ require 'spec_helper'
3
+
4
+ describe "Yahoo" do
5
+ it_should_behave_like "fetch A contact list","yahoo"
6
+ end
metadata ADDED
@@ -0,0 +1,130 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: email-spy
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.3
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Wade Xing
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-07-30 00:00:00.000000000Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: httpclient
16
+ requirement: &70298431184880 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: 2.2.5
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: *70298431184880
25
+ - !ruby/object:Gem::Dependency
26
+ name: nokogiri
27
+ requirement: &70298431184380 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ~>
31
+ - !ruby/object:Gem::Version
32
+ version: 1.5.0
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: *70298431184380
36
+ - !ruby/object:Gem::Dependency
37
+ name: gdata_19
38
+ requirement: &70298431183920 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ~>
42
+ - !ruby/object:Gem::Version
43
+ version: 1.1.5
44
+ type: :runtime
45
+ prerelease: false
46
+ version_requirements: *70298431183920
47
+ - !ruby/object:Gem::Dependency
48
+ name: mechanize
49
+ requirement: &70298431183400 !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ version: 2.5.1
55
+ type: :runtime
56
+ prerelease: false
57
+ version_requirements: *70298431183400
58
+ - !ruby/object:Gem::Dependency
59
+ name: rspec
60
+ requirement: &70298431182860 !ruby/object:Gem::Requirement
61
+ none: false
62
+ requirements:
63
+ - - ~>
64
+ - !ruby/object:Gem::Version
65
+ version: 2.11.0
66
+ type: :development
67
+ prerelease: false
68
+ version_requirements: *70298431182860
69
+ description: Retrieves contact list of email
70
+ email:
71
+ - iamxingxing@gmail.com
72
+ executables: []
73
+ extensions: []
74
+ extra_rdoc_files: []
75
+ files:
76
+ - .gitignore
77
+ - .rspec
78
+ - Gemfile
79
+ - Gemfile.lock
80
+ - LICENSE
81
+ - README.md
82
+ - Rakefile
83
+ - email-spy.gemspec
84
+ - lib/email-spy.rb
85
+ - lib/email-spy/126.rb
86
+ - lib/email-spy/contact.rb
87
+ - lib/email-spy/email_types.rb
88
+ - lib/email-spy/errors.rb
89
+ - lib/email-spy/gmail.rb
90
+ - lib/email-spy/hotmail.rb
91
+ - lib/email-spy/version.rb
92
+ - lib/email-spy/yahoo.rb
93
+ - spec/126_spec.rb
94
+ - spec/email-spy_spec.rb
95
+ - spec/gmail_spec.rb
96
+ - spec/hotmail_spec.rb
97
+ - spec/spec_helper.rb
98
+ - spec/yahoo_spec.rb
99
+ homepage: https://github.com/xingxing/email-spy
100
+ licenses: []
101
+ post_install_message:
102
+ rdoc_options: []
103
+ require_paths:
104
+ - lib
105
+ required_ruby_version: !ruby/object:Gem::Requirement
106
+ none: false
107
+ requirements:
108
+ - - ! '>='
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ required_rubygems_version: !ruby/object:Gem::Requirement
112
+ none: false
113
+ requirements:
114
+ - - ! '>='
115
+ - !ruby/object:Gem::Version
116
+ version: '0'
117
+ requirements: []
118
+ rubyforge_project:
119
+ rubygems_version: 1.8.17
120
+ signing_key:
121
+ specification_version: 3
122
+ summary: ''
123
+ test_files:
124
+ - spec/126_spec.rb
125
+ - spec/email-spy_spec.rb
126
+ - spec/gmail_spec.rb
127
+ - spec/hotmail_spec.rb
128
+ - spec/spec_helper.rb
129
+ - spec/yahoo_spec.rb
130
+ has_rdoc: